지금까지 다룬 type: int , float, _Bool(C99)

이번 장에서는 나머지 타입을 다룸.

7.1: integer -  long, short, unsinged

7.2: floating -  double, long double

7.3: 문자. char

7.4 같은 값의 다른 type으로 변환하기

7.5 typedef 이용해서 새로운 type을 정의

7.6 sizeof - 해당 type에 필요한 저장 공간


7.1 Integer Types


integer type - 정수형

floating type - 부동 소수점형


signed integer의 가장 왼쪽 bit는 수의 부호를 나타냄.

0: positive or zero

1: negative

따라서가장 큰 16비트 정수를 2진법으로 표현하면 

0111 1111 1111 1111 이다. (2^15-1)

가장 큰 16비트 unsigned integer는 

1111 1111 1111 1111 (2^16-1)


다음 6가지 형태가 short, long, signed, unsigned, int를 결합한 타입의 전부이다. 다른 표현 방법도 있으나 아래 있는 애들과 표기 방법만 다르고 동일한 type이다.

short int

unsigned short int

int

unsigned int

long int

unsigned long int


뒤에 오는 int는 생략 가능하다

short int -> short, unsigned long int -> unsigned long


32-bit CPU에서의 정수형 type의 최소값과 최대값(VS 2015는 32bit 기반이다)


Type 

Smallest Value 

Largest Value 

 short int 

 -32,768 

-(2^15) 

32,767 

2^15-1 

 unsigned short int

0 

65,535 

2^16-1 

 int

-2,147,483,648 

-(2^31) 

2,147,483,647 

2^31-1 

 unsigned int

0 

4,294,967,295 

2^32-1 

 long int

-2,147,483,648

-(2^31) 

2,147,483,647

2^31-1 

 unsigned long int

0 

4,294,967,295

2^32-1 

 long long int (C99)

 -9,223,372,036,854,775,808 

-(2^63) 

 9,223,372,036,854,775,807 
2^63-1 

 unsigned long long int (C99)

 0 

 18,446,744,073,709,551,615 
2^64-1 


C99에서는 long long int, unsigned long long int를 추가적으로 지원한다.


Integer Constants

정수를 10진수, 8진수, 16진수로 입력하는 방법

10진수 : 늘 하던대로, 0~9 사이의 숫자를 써서 입력

15 255 32767

8진수: 첫번째 숫자는 반드시 0, 나머지 숫자는 0~7 사이의 숫자를 입력

017 0377 07777

16진수: 0x로 시작하고, 0~9 사이의 숫자, a~f 사이의 문자(대문자여도 된다)를 써서 입력

0xff 0xfF 0xaF


가장 뒤에 L을 붙이면 long integer가 된다.

(C99) LL을 붙이면 long long

U를 붙이면 unsigned가 된다. 둘다 붙이면 순서는 상관이 없다.

ㄴ 소문자로 써도 된다.


Integer Overflow

integer 간 연산을 할 때, 결과가 type이 허용하는 범위를 벗어날 때 overflow가 발생했다고 한다.

signed integer에서 overflow가 발생했을 때에는 결과가 아무렇게나 나온다. (undefined)

unsigned integer에서 overflow가 발생하면 프로그램의 행동은 정의되어 있다(defined).

결과값 % 2^n (n은 결과값을 저장하는데 필요한 비트의 수)


Reading and Writing Integers

printf와 scanf 함수에서 format string 사용하기

%u    unsigned int (base 10)

%o    unsigned int (base 8)

%x    unsigned int (base 16)


short와 long을 표시하려면 h, l(영어 소문자)을 d, o, u, x 앞에 붙이면 된다.

%hd    short

%hu    unsigned short

%hx    unsigned short (base 16)

%ld     long

%lld    long long


7.2 Floating Types


 float

 Single-precision floating-point

 double                

 Double-precision floating-point

 long double

 Extended-precision floating-point

float - 정확도가 그리 중요하지 않은 경우(ex 소수점 첫째 자리까지 표시하는 온도)

double - 좀 더 정확하게 표현 가능하며 대부분의 프로그램에게 충분하다

long double - 매우 정확한 표현. 드물게 쓰인다.


Floating Type Characteristics(IEEE Standard)


 Type

Smallest Positive Value 

Largest Value 

Precision 

float 

1.17549e-038 

3.40282e+038 

6 digits 

double 

2.22507e-308 

1.79769e+308 

15 digits 


Floating Constants

floating constants는 다양한 방법으로 표현 가능하다. 아랫줄에 써져 있는 모든 표현은 57.0을 나타낸다.

57.0    57.    57.0e0    57E0    5.7e1    5.7e+1    .57e2    570.e-1

C 컴파일러는 기본적으로 floating constant를 double 형식으로 저장한다.

뒤에 f나 l을 붙이면 float, 또는 long double로 저장한다(ex 57.0f 또는 57.0L)


Reading and Writing Floating-Point Numbers

double: e, f, g 앞에 소문자 l을 붙인다.

scanf("%lf", &d);

printf의 경우, l을 붙이지 않아도 된다. 그냥 %e, %f, %g가 float과 double에 모두 적용된다.


long double: e, f, g 앞에 L을 붙인다.

scanf("%Lf", &ld);

print("%Lf", ld);


7.3 Character Types


char type의 value는 사용하는 character set에 따라 컴퓨터마다 다를 수 있다. 

ASCII는 가장 보편적인 character set이며 이를 확장한 256문자 코드인 Latin-1이 있다.


문자 상수는 single quote(' ')로 묶인다. C는 문자를 작은 정수로 간주한다. 사용하는 문자열

ASCII에서 'A'는 65, 'a'는 97이다. 따라서 숫자처럼 문자끼리 비교할 수 있다.


소문자를 대문자로 변환하기

if ('a' <= ch && ch<= 'z')

ch = ch - 'a' + 'A';


Signed and Unsigned Characters

unsigned char는 -128부터 127까지의 값을, signed char는 0부터 255까지의 값을 가진다.

C standard에서는 char가 signed인지 unsigned인지 정해두지 않았고, 실제 사용할 때도 꼭 필요한 경우가 아니면 부호는 지정하지 않는 것이 좋다.


Arithmetic Types

integer types, floating types를 합쳐서 arithmetic types라고 한다.

C99에서 arithmetic type의 구분

-- Integer types

- char

- Signed integer types, both standard (signed char, short int, int, long int, long long int) and extended

- Unsigned integer types, both standard (unsigned char, unsigned short int, unsigned int, unsigned long int, unsigned long long int, _Bool) and extended

Enumerated types

-- Floating types

- Real floating types (float, double, long double)

- Complex types (float_Complex, double_Complex, long double_Complex)


Escape Sequences (3.1에서 추가)


Name 

Escape Sequence 

Alert(bell) 

\a 

Backspace 

\b 

Form feed 

\f 

New line 

\n 

Carriage return 

\r 

Horizontal tab 

\t 

Vertical tab 

\v 

Backslash 

\\ 

Question mark 

\? 

Single quote 

\' 

 Double quote

\" 



Character-Handling Functions

ch = toupper(ch);    /* converts ch to upper case */

toupper 함수는 C library에서 제공하며, 사용하기 위해서는 #include <ctype.h>가 필요하다.


Reading and Writing Characters using scanf and printf

format string으로 %c를 사용한다.

scanf("%c", &ch);

printf("%c", ch);

scanf 함수는 white-space 문자를 생략하지 않기 때문에, 입력한 값에서 space를 생략하기 위해서는 format string안에 space를 넣어주어야 한다.

scanf(" %c", &ch);


Reading and writing Characters using getchar and putchar

getchar, putchar 함수는 하나의 글자를 읽고 쓰는 다른 방법이다.

getchar 함수가 한 번 호출될 때마다 하나의 글자를 읽는다. getchar가 리턴하는 변수의 형은 char가 아니고 int이다.

scanf, getchar와 마찬가지로, 이 둘은 white-space 문자를 스킵하지 않는다.

scnaf, getchar보다 더 빠르고, 다음과 같은 간단한 표현도 가능

while (getchar() != '\n');    /* skips rest of line */

while ((ch = getchar()) == ' ');    /* skips blanks */




모든 루프는 controlling expression이 있어야 한다(switch문 뒤에 오는 바로 그것).

loop이 실행될 때마다, controlling expression이 실행된다. 그리고 그 expression이 true(nonzero)라면, loop이 계속해서 실행된다.

loop 실행 - > controlling expression 실행 -> zero? or nonzero? -> nonzero면 loop 다시 실행


iteration statements는 세 가지: while, do, for

while은 body가 실행되기 전에 controlling expression을 테스트

do는 body가 실행된 후에 controlling expression을 테스트

for는 증가하거나 감소하는 counting variable(index?)를 가지고 루프 돌리기에 적합


break, continue, goto

break: loop에서 뛰쳐 나와서 loop 다음의 statement로 이동

continue: loop interation의 나머지 부분을 생략

goto: 함수 내의 아무  statement로 점프


null statement는 body가 비어 있는 loop를 만들 수 있다.


6.1 The while Statement


C에서 가장 단순하면서 가장 기초적인 loop 문.

while ( expression ) statement


while (i < n)        /* controlling expression */

i = i * 2;       /* loop body */


loop body는 single statement여야 한다. 여러 개의 statements를 원한다면 중괄호로 묶어 하나의 compound statement로 만들면 된다.

- while loop이 종료될 때, controlling expression의 값은 false이다.

- loop body는 단 한번도 실행되지 않을 수도 있다. 


Infinite Loops: controlling expression의 값이 항상 nonzero여서 무한히 실행되는 loop

while (1) 

로 시작하는 loop는 control을 loop 바깥으로 이동시키는 statement(break, goto, return)이나 프로그램을 종료시키는 함수가 들어있지 않으면 무한히 loop을 실행한다.


scanf("%d", &n);

while (n != 0) {

sum += n;

scanf("%d", &n);

}

loop문을 사용할 때, 위에서 scanf문을 두번 쓴 것처럼 같이 동일한 statements를 두 번 써야만 하는 경우가 종종 있다.


6.2 The do Statement


do statement while ( expression ) ;

do 문은 while문과 거의 유사하다. 단 차이는 controlling expression을 테스트하기 전에 body를 먼저 한번 실행한다는 것이다. 그러므로 controlling expression이 false더라도 body는 최소 한 번은 실행된다.


6.3 The for Statement


for ( expr1 ; expr2 ; expr3 ) statement


몇몇 예외적인 경우를 제외하면, for loop는 다음과 같은 형태로 while loop으로 표현할 수 있다.

expr1;

while ( expr 2 )  {

statement

expr3 ;

}


expr1은 초기화 단계로 단 한번만 수행된다.

expr2는 control expression으로 그 값이 nonzero면 계속 진행하고, 아니면 loop을 종료한다.

expr3은 loop이 한 바퀴 돌 떄마다 수행된다.


for statement idioms

 

for (i = 0; i < n; i++)            -> counting up from 0 to n-1

for (i = 1; i <= n; i++)           -> counting up form 1 to n

for (i = n; i >= 0; i--)           -> counting down from n-1 to 0

for (i = n; i > 0; i--)            -> counting down from n to 1 


for(;;) : infinite loop

for(; i > 0;) : disguised while loop


comma expression

expr1, expr2

C에서 하나의 expression을 요구하지만, 두개 이상의 expression을 사용하고 싶다면, expression들을 콤마로 구분해서 사용하면 된다. 가장 마지막에 있는 expression의 값이 전체 expression의 value가 되며, 그 이전의 expression은 side-effect가 있어야만 존재할 가치가 있다.


sum = 0;

for (i=1; i <= N; i++)

sum += i;

 ->

 for (sum = 0, i = 1; i <= N; i++)

      sum += i;



6.4 Exiting from a Loop


while, for 문에서는 loop body 전에 loop 종료가 가능하고, do 문에서는 loop body 후에 종료가 가능하다.

만약 중간에 loop을 끝내고 싶다면? break statement를 쓰자.

continue statement는 loop 전체를 종료하지 않고 지금 돌고 있는 loop의 나머지 부분만 스킵할 수 있다.

goto statement는 하나의 statement에서 다른 statement로 점프하게 해 준다. (거의 사용되지 않음)

break, continue, return으로 대부분의 goto문을 대체할 수 있지만, goto문이 쓰일 수 있는 하나의 예시는 loop 안에 있는 switch문 안에서 loop를 끝내는 경우이다(break를 쓰면 switch 만 빠져나옴)




6.5 The Null Statement


statement can be null.

다음 line은 세개의 statements로 구성되어 있다.

i = 0;  ; j = 1;

an assignment to i, a null statement, an assignment to j.

가장 중요한 용도는, for 문 뒤에 붙이는 것이다.

for (d = 2; d < n && n % d != 0; d++);

for 문 뒤에 ;를 붙인 것에 주목하자.




Programmers are not to be measured by their ingenuity and their logic but by the completeness of their case analysis


operator에 비하면 statement의 종류는 꽤 적음.

앞에서 다룬 return statement와 expression statement 이외에 다른 statement는 크게 세 종류로 나눌 수 있다.


Selection statements: if and switch statements

Iteration statements: while, do, for statements

Jump statemets: break, continue, goto, return도 여기에 속함.

compound statement: 여러개의 statement를 묶어서 하나의 statement로 만듬

null statment: no action


이 장에서는 selection, compound statement를 다룸


5.1 Logical Expressions


C는 논리 연산자가 boolean type을 반환하는 것이 아니라 정수를 반환한다. 0(false) 또는 1(true)


relational operators: <, >, <=, >=

1 < 2.5의 값은 1

6 < 4의 값은 0

relational operators의 우선순위는 arithmetic operators(+-/*&)보다 낮다.


equality operators: ==, !=


logical opeators:  !, &&, ||


logical negation 

&& 

logical and 

|| 

logical or 


short-circuit evaluation: &&와 ||의 경우 첫번째 operand(피연산자)만으로 이미 값을 알 수 있는 경우, 두번째 operand는 처리하지 않는다.

ex) (i != 0) && (j / i > 0);에서 i = 0이라면, 첫번째 operand의 값이 0이므로 이 statement의 값은 뒷 operand에 상관 없이 0이 된다. 그러므로 뒷 operand를 처리하지 않고 0이 된다. 만약 뒷 operand까지 처리했다면 division by zero로 에러가 발생했을 것이다.


! 연산자는 unary plus, unary minus(+-기호)와 우선순위가 같다. &&와 ||는 relational, equality 연산자보다 우선순위가 낮다.


5.2 The if Statement

형식: if (expression) statement

if statement가 실행되면, 괄호 안의 expression의 값이 0인지 아닌지를 따져서 0이 아니면(nonzero) 괄호 뒤에 있는 statement를 실행한다.


compound statements

형식: { statements }

중괄호 안에 여러 개의 statements를 넣어 주면, 컴파일러는 그것을 하나의 statement로 인식하게 된다.

loop이나 C가 한 개의 statement를 요구하지만 우리가 여러개를 넣고 싶을 때 사용된다.


else를 사용 하는 경우

if ( expression ) statement else statement

 

cascaded if statements

if ( expression )

statement

else if ( expression )

statement

...

else if( expression )

statement

else

statement



The "Dangling else" problem

다중 if 문이 있을 때, else는 가장 가까운 if문과 짝을 이루게 된다. 파이썬처럼 indentation을 이용해더 먼 if문과 짝을 이루게 할 수 없다. 만약 바깥쪽의 if문과 else를 매치시키려면, 중괄호를 사용해 안쪽의 if문을 compound statement로 묶어야 함.


Conditional expressions

lvalue = expr 1 ? expr 2 : expr 3

if expr1 then {lvalue = expr2} else {lvalue = expr3}과 동일한 의미.


boolean values

오랫동안 C에는 적합한 boolean type이 없었다. C99에 이르러 _Bool 이란 type이 제공됨. 이 type으로 선언된 변수는 0 또는 1만 값으로 가질 수 있다.

_Bool flag;

flag = -1243; // 어떠한 nonzero value를 입력하면, flag의 값은 1로 설정된다. 

또는 <stdbool.h> 를 include해서, 

bool flag;  // _Bool flag;와 같음

flag = true; flag = false;


5.3 The switch Statement


cascaded if statement보다 읽기 편하고, case가 많다면 if보다 빠른 경우가 많다

switch ( expression ) {

case constant-expression : statements

...

case constant-expression : statements

default : statements

}


controlling expression : switch 다음에는 반드시 괄호 안에 들어있는 정수 expression이 와야 함. 소수나 문자열은 올 수 없음

case labels: 각각의 case는 case constant-expression으로 시작해야 함.

constant-expression에는 5 가능, 5 + 10 가능, 그러나 n + 10 불가능(n이 상수인 macro가 아닌 이상). 정수 또는 문자 한개여야 함.

case 다음엔 하나의 constant expression만 올 수 있지만, 

case 5: case 4: case 3: 

printf("passing");

break;

같은 형태로 여러 개의 case를 동시에 처리할 수 있다.

하나의 case를 범위로 지정하는 것은 불가능하다.

case뒤 statement 다음에 break;를 써주지 않으면 그 다음 case의 statement도 순차적으로 실행된다. 

만약 의도적으로 case 뒤에 break;를 빼먹은 거라면 그 의도를 명확히 표시해 주는것이 좋다. 왜냐하면 다른 누군가가 그걸 보고 실수라고 생각해서 break;를 추가할 수도 있기 때문이다.




C의 두드러지는 특징은 'expression(값을 계산하는 식)'을 statement보다 강조하는 것.

expression은 주로 표현식, statement는 문장으로 번역되는 것 같다.


가장 단순한 expression은, 변수와 상수.

operator : 연산자(덧셈, 뺄셈)

operand : 피연산자. 연산 당하는 수들


C는 흔치 않을 정도로 풍부한 operator collection을 가지고 있음

그중 가장 기본적인 것들

- arithmetic operators(addition, subtraction, multiplication, division)

- relational operators to perform comparisons

- logical operators to build conditions


이 장에서는 C의 가장 근본적인 operator들을 다룸. 

arithmetic, assignment, increment and decrement operators. 

precedence(우선순위), associativity(결합)

how C expressions are evaluated

expression statement(allows any expression to serve as a statement)


4.1 Arithmetic Operators


 Unary

 Binary

 + unary plus

 - unary minus

 Additive

Multiplicative 

 + addition

 - subtraction

 * multiplication

 / division

 % remainder


unary operators require one operand; inary operators require two operand


- Using both operands are intergers, the / operator truncates fraction part and returns a integer

- % operator requires integer operands

In C99, result of a division is always truncated toward zero. -9 / 7 = -1, -9 % 7 = -2(파이썬과 다름)

Implementation-Defined Behavior에 의존하는 코드를 가능한 피하는 것이 좋다.


associativity : 여러개의 동등한 우선순위를 가진 operator를 처리하는 순서. 

left associative: 왼쪽에서 오른쪽으로 처리함. binary arithmetic operators(*, /, %, +, -)는 모두 left associative.

ex) i - j - k 는 (i - j) - k와 같다

right associative: 오른쪽에서 왼쪽으로 처리함. unary arithmetic oprators(+, -)는 right associative

ex) - + i 는 - (+i)와 같다


12345라는 입력을 5개의 변수에 각각 한 자리 정수로 넣으려면, format string으로 "%1d%1d%1d%1d"를 사용하자.


4. 2 Assignment Operators


simple assignment operator : =

많은 언어에서 assignment는 statement이나, C에서는 operator이다. 

다시 말해 = 기호를 사용하는 것은 + 기호를 사용하는 것과 같이 '결과'를 만들어 내는 것.

(v = e: evaulate the expression e and copy its value into v)

i = j = k = 0;의 의미는 i = (j = (k = 0));과 같다. (=> operator is right associative)


lvalue : assignment operator requires an lvalue as its left operand. 지금까지 배운 것에서는 variable만이 lvalue가 될 수 있다.



compound assignment operators : +=

10 compound assignment operators, +=, -+, *=, /=, %=, 등등

v += e가 항상 v = v + e와 동일한 의미를 지니지는 않는다.(side effect)

compound assignment도 = operator와 마찬가지로 right associative.

i += j += k; 는 i += (j += k); 와 동일


4.3 Increment and Decrement Operators


++(increment), --(decrement) operators

prefix(++i, --i), postfix(i++, i--)로 구분된다.

이 연산자는 side effect를 발생시킴(they modify the values of their operands)

prefix는 먼저 값이 변경되고 읽어들인다, postfix는 값을 먼저 읽어들이고 그 다음에 변경된다.


prefix는 먼저 1증가(감소)시키고 읽는다!

postfix는 일단 읽고, 그다음에 1증가(또는 1 감소)


4.4 Expression Evaluation


연산자들을 계산하는 순서


Precedence 

Name 

Symbol(s) 

Associativity 

increment(postfix)

decrement(postfix)

++

-- 

left 

2 

increment(prefix)

decrement(prefix)

unary plus

unary minus 

++

--

+

- 

right 

3 

multiplicative 

* / % 

left 

4 

additive 

+ - 

left 

5 

assignment 

= *= /= %= += -= 

right 


a = 5;

c = (b = a + 2) - (a = 1);

라는 식이 있을 때, 두 괄호 (subexpression) 중 어떤 것이 먼저 처리되는 것인지는 정의되지 않음. 전자가 먼저 처리되어 c = 6이 될 수도, 후자가 먼저 처리되어 c = 2가 될 수도 있는 것. 위 식은 undefined behavior를 발생시킨다.

그러므로 같은 expression 안에서 한 변수의 값에 접근하기도 하고 변경하기도 하는 것은 피해야 한다.

따라서 이렇게 쓰자

a = 5;

b = a + 2;

a = 1;

c = b - a;


4.5 Expression Statements

C의 어떤 expression이라도 statement가 될 수 있다. expression 뒤에 세미콜론(;)을 붙이면 statement가 된다.

예를 들어, i = 0일 때, i + 1;이라는 라인도 statement이다. 그 statement의 값은 1이 되며, 기껏 덧셈을 수행해 놓고 그 결과가 아무 곳에도 저장되지 않는 것이므로 "do-nothing" expression statement가 된다. 이런 statement가 발생하면 컴파일러에서 헛심을 켜는것에 대해 경고해 준다.




Printf function

conversion specification: %d, %s등 %로 시작되는 placeholder. %뒤의 글자는 internal form(binary)에서 printed form(character)으로 변환되는 방법을 의미한다.

ex) %d: integer, %f: float


컴파일러는 다음을 체크해 주지 않는다.

- format string 안의 conversion specification과 output items의 갯수가 같은지

- conversion specifaction의 형식이 해당되는 변수와 적절하게 맞는지


conversion specification의 기본 형태

%m.pX

m, p: integer constatns(optional), X: a letter.

p가 생략되면 마침표도 생략. %.X와 같이 쓰면 p가 0으로 취급되는 것 같다


m: minimun field width. 출력될 최소한의 글자 개수. 만약 값을 출력하는 데 m보다 적은 글자가 필요하면, 우측 정렬됨.

%4d , 123 --> _123

%4d, 12345 --> 12345 (그대로 표시된다)

%-4d , 123 --> 123_ (m이 음수이면 좌측 정렬된다)


p: precision. 어떤 X를 선택하느냐에 따라 달라진다.

X: conversion specifier. 값을 출력할 때 어떤 변환을 적용하는지 지정한다.



X의 종류 몇 가지


d: 정수를 10진수 형태로 표시. p는 표시될 최소한의 숫자를 의미하며 필요하다면 숫자 0들이 앞자리에 붙음. p가 생략되면 p = 1. %d 와 %.1d는 동일한 의미.

e: floating-point(부동 소수점) number를 지수 형태로 표시. ex)[%e, 11.123 - > 1.112300e+01] p는 소수점 뒤에 숫자 몇개가 표시될지를 의미하며, 기본값은 6. p가 0이면 소수점 표시 안됨

f: floating-point number를 일반적으로 우리가 보는 소수 형태로 표시. p의 의미는 e에서와 같다.

g: floating-point number를 수의 크기에 따라 지수형태 또는 일반적인 소수 형태로 표시. p는 유효 숫자의 최대값. f와 달리 소수점 아래의 불필요한 0을 표시하지 않는다.

%g, 0.00000000123 --> 1.23e-09 

%e, 0.00000000123 --> 1.230000e-09

g는 아주 큰 값이나 아주 작은 값이 들어오면 지수형태로 바꿔서 더 적은 글자들로 숫자를 표현하게 해 준다.


escape sequence

\a: alert

\b: backspace

\n: new line

\t horizontal tab

"" 안에서 "를 쓸 때 - \", \문자를 쓸 때 - \\


Scanf Function

scanf 함수에서 integer를 읽으라고 요청 받았을 때

+또는-부호를 읽는다 -> 숫자가 끝날 때까지 숫자를 읽는다

floating-point number를 읽으라고 요청 받았을 때

1. a plus or minus sign(optional)

2. a series of digits(possibly containing a decimal point)

3. an exponent(optional). an exponent consists of the letter e(or E), an optional sign, and one or more digits


scanf("%d%d%f%f", &i, &j, &x, &y);

1-20.3-4.0e3\n

1    -20    .3    -4.0e3\n

둘중 어느것을 입력해도 결과는 같다. scanf 함수는 whitespace 문자는 무시하기 때문.

마지막 입력한 엔터키(\n)는 읽지 않고 'peek' 한다.

이 줄바꿈 문자는 다음번 scanf 함수를 호출할 때 읽어들이는 첫번째 문자가 된다.


format string에 whitespace가 아닌 다른 문자가 왔을 때는, 입력값에서 그 문자가 그대로 들어오기를 기대한다.

format string 이 "%d/%d"일 때

5_/_96 : 5는 입력이 되지만 96은 안 된다. /를 기대하는데 빈칸이 왔기 때문. _/_96은 다음 scanf함수로 넘겨진다.

___5/____96: 5, 96모두 제대로 입력된다.

(*underscore 문자는 빈칸을 나타냄)

그냥 format string에는 conversion specification 이외에는 아무것도 넣지 않는 것이 좋다.


%d와 %i의 차이: %d는 10진수 정수만 입력 가능하지만, %i는 8진수, 10진수, 16진수 형태로 입력 가능. 0x... ->16진수. %i를 사용했을 때 숫자 앞에 실수로 0을 집어넣으면 이상한 숫자가 나올수 있으므로, %d를 사용하는 것을 추천함



<stdio.h>: C's standard I/O library


when one integer is divided by another, the answer is 'truncated': all digits after the decimal point are lost.


defining a constant using macro definition

#define INCHES_PER_POUND 166

세미콜론 없는 것에 유의(preprocessing directive에 속함. 코드 맨 윗부분에 작성)


%.1f : float형 변수를 소수점 첫째 자리까지 표시.


identifiers: names for variables, functions, macros, and other entities

case-sensitive, 문자, 숫자, underscore를 포함할 수 있으나 숫자로는 시작하지 못함.

identifier의 글자의 길이는 걱정할 필요가 없다. C89에서는 첫 6글자, C99에선 첫 31글자가 유효하지만, 대부분의 컴파일러와 링커는 저 기준들보다 길이의 제한에 관대하다.





python을 초등 수준 이상으로는 다룰 수 있게 되었지만, python은 너무 많은 것을 알아서 척척 해 준다.

예를 들어, 정렬을 할 때 엑셀에서 오름차순/내림차순 정렬을 할 때 이상의 지식을 요구하지 않는다. 언어에서 알아서 자동으로 적당한 알고리즘 방식으로 정렬해 주기 때문이다. 그렇기 때문에 merge sort, quick sort 이런 방법을 전혀 몰라도 프로그래밍을 하는 데에는 지장이 없다. 그런데 이렇게 '자료구조'에 대해 전혀 모르고 프로그래밍을 하다보니 비효율적인 코드가 발생한다.


예를 들어 간단한 피보나치 수를 구하는 함수를 작성할 때, 초보자인 나는 아무 거리낌 없이 리스트에 이전 두 개의 인수를 더한 값을 append하는 방법으로 수를 구했다. 그런데 다른 사람의 코드에 비해 내 코드는 수백배가 느리다. 알고 보니 yield를 이용해 generator로 피보나치 수를 구하면 훨씬 훨씬 속도가 빨라진다. 파이썬 책에서는 generator 기법에 대해서는 알려주지만, 왜 그것이 빠른 것인지는 책을 보고 잘 이해가 되지 않았다.


때문에 자료구조와 알고리즘을 학습하기 전에 low-level언어를 학습해야 한다는 생각이 들어 C를 공부하게 되었다. 파이썬을 하다 C를 접하니 파이썬은 천국이었다. string이라는 type 자체가 없는 것, 배열을 선언할 때 크기를 지정하는 것 등은 처음 접할 때는 충격적이었다. 문자열과 포인터는 또 왜 이리 복잡한지.. 이런저런 책을 찾다가 C Programming A Modern Approach라는 책을 알게 되었다. 딱딱한 구성으로 되어 있지만 그림이 많은 책보다 오히려 읽기가 편하다. C에 대한 지식을 벽돌 쌓듯 차근차근 세워줄 수 있을것 같다. 그래서 이 책을 읽으면서 나중에 분명히 다시 찾게 될 내용들을 여기에 기록해놓을 것이다.


적히는 내용은 전부 내 머리의 외장 하드 같은 것이다. 나중에 문법이나 개념 등을 빠르게 다시 찾아가면서 쓰기 위한 목적이고 C를 공부하는 다른 사람을 위한 요약 정리 자료가 절대 아니다.

컨트롤 여러개를 배열로 묶어서 사용할 수 있다. VB 6.0에서는 쉽게 가능했는데 .net으로 오면서 방법이 달라졌다고 하는데 원래 방법을 모르니..


Public Class Form1

    Private txtArray(2, 1) As TextBox

->우선 txtArray라는 3x2짜리 배열을 선언해 주되 형식을 TextBox로 한다.

    Public Sub New()

        InitializeComponent()

        txtArray(0, 0) = TextBox1

        txtArray(0, 1) = TextBox2

        txtArray(1, 0) = TextBox3

        txtArray(1, 1) = TextBox4

        txtArray(2, 0) = TextBox5

        txtArray(2, 1) = TextBox6

->윗 두줄이 있어야만 txtArray에 TextBox를 할당할 수 있다. 각각의 항목(엑셀로 따지면 셀)에 TextBox를 할당해 준다. 

    End Sub


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        For i = 0 To 2

            For j = 0 To 1

                txtArray(i, j).Text = i & "," & j

            Next

        Next

->다중 For..Next문으로 각각의 TextBox에 주소를 넣어주었다.

    End Sub

End Class


그리고 실행하면 이렇게 나온다.




 Function ExtractNumber(ByVal InputString As String)

        Dim i As Integer = 0

        Dim Num As String = ""


        For i = Len(InputString) To 1 Step -1

            If IsNumeric(Mid(InputString, i, 1)) Then

                Num = Mid(InputString, i, 1) & Num

            End If

        Next i


        ExtractNumber = Num

    End Function

텍스트박스에서 엔터키 감지하기 + 다른 프로시져에서 버튼 클릭 이벤트를 활성화하는 방법이다.


텍스트박스 이름은 TextBox1, 버튼 이름은 Button1


Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As _ system.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown

        If e.KeyCode = Keys.Return Then

                  Button1_Click(sender, New System.EventArgs())

        End If

    End Sub


둘다 유용하게 쓸 수 있다!



1. 영문입력시 대문자로만 입력되게 하기: 속성에서 CharacterCasting을 Upper로 설정


2. 영문과 숫자만 입력되게 하기: 속성에서 ImeMode를 Disable로 설정


3.숫자만 입력되게 하려면 코드창에서 텍스트박스의 KeyPress 이벤트를 만들고 다음과 같이 입력하면 된다.


Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As _ System.Windows.Forms.KeyPressEventArgs) Handles tbSticks.KeyPress

        If Not Char.IsDigit(e.KeyChar) And Not Char.IsControl(e.KeyChar) Then

            e.Handled = True

        End If

    End Sub

+ Recent posts