본문 바로가기

개발공부(C, C++)

따배씨(따라 배우는 C언어_홍정모) Chapter4

CHAPTER 4 문자열과 형식 맞춘 입출력

"우리의 모든 꿈들은 이뤄질 수 있다. 우리에게 끝까지 밀어붙일 용기가 있다면." __월트 디즈니

4.1 문자열 입출력하기

scanf() 사용주의할 점

scanf() 를 통해 일반 변수에 입력값을 넣을 때와, 배열에 입력값을 넣을 때는 & 의 사용 여부에 차이가 있다. 배열은 그 자체가 첫번째 주소를 가리키고 있기 때문에 & 를 붙이지 않는다. (붙여도 상관은 없다.) 문자열이면 %s 를 쓴다.

char fruit_name;
scanf("%c", &fruit_name);
char fruit_name[40];
scanf("%s", fruit_name);

4.2 sizeof() 연산자

sizeof(int), sizeof(a) 같이 주로 사용하기 때문에 함수라고 생각하기 쉬우나, sizeof a 라고도 사용할 수 있는 등 사실상 연산자다.

sizeof() 는 기본적으로 unsigned int 자료형으로 반환하지만, 혹시나 다른 시스템에서 다른 자료형을 사용할 것을 우려해 size_t 라는 자료형을 반환 자료형으로 쓰기도 한다.(호환이식성 관련) size_t 의 형식 지정자

(format specifier || conversion specifier)

%zu 이다.

4.3 문자열이 메모리에 저장되는 구조

숫자의 배열과 달리, 문자의 배열은 배열의 마지막을 알리는 null character('\0') 이 마지막 한 칸의 메모리를 차지하고 있다. 즉, char str[10]; 을 선언했을 때 그 문자열에는 최대 9개의 character + 1개의 null character 가 들어간다.

4.4 strlen() 함수

  • #include <string.h> 필요.
  • null character 를 제외한 문자열의 길이를 반환함.
  • 얘도 null character 까지만 길이를 재기 때문에 중간에 null character 가 삽입되면 뒤쪽에 있는 건 세지 못함.

4.5 기호적 상수와 전처리기

기호적 상수는,

  1. #define PI 3.141592f 같이 #define 전처리기를 이용해서 정의할 수 있다.. PI 와 수치 사이에 = 이 없음에 주의하자! 전처리기는 컴파일 때 해당 심볼에 미리 정해진 수치를 대입하는 것이기에 = 3.141592f 가 대입되어 버리는 불상사가 발생할 수 있다.
  2. 요즘은 굳이 전처리기를 쓰기보다 const float pi = 3.141592f; 같이 const 를 써서 기호적 상수를 만드는 게 더 일반적이다.

4.6 명백한(대표적) 상수들 Manifest Constants

  • 국내 번역서에 명단 상수 라고 오역된 경우가 있다.
  • 꼭 알아두어야 할 중요한 개념까지는 아니다.
  • 앞서 살펴본 기호적 상수를 포함해서 각종 매크로 등에 사용되는 명백하게 용도가 정해진 상수들을 Manifest Constants 라고 한다.

4.7 printf() 함수의 변환 지정자들 Conversion specifiers

변수, 상수, 표현식들이 들어갈 자리를 지정해놓는다.

  • 사실 conversion 이라고 하기엔 '변환' 하는 게 딱히 대단치 않기 때문에 형식 지정자 (format specifier) 로 더 많이 통용된다. 하지만 공식 명칭은 conversion specifier다..

  • 풀 형식은 %[flag][width][.precision][length]specifier 로 상당히 길다. ex) printf("%+10.5hi", 256); 그러나 보통은 자료형만 쓰고 만다.

  • printf() 에서 % 기호를 입력하고 싶다면 %% 처럼 두 개를 연달아 써주면 된다.

  • printf() 내의 문자열의 길이가 지나치게 길어져 다음줄로 넘기고 싶다면 '\' 를 쓰고 다음줄로 내려야 한다.

  • 해당 형식이 감당하지 못하는 건 overflow 나 underflow 가 발생함에 주의하자.

  • %f 는 사실상 float 이 아닌 double 을 위한 지정자다. %lf 같이 long float 을 써도 어차피 double 이기 때문에 l 이 무시된다. (scanf() 에서는 구별이 된다!)

  • %9d 로 9자리 출력, %.2f 로 소숫점 둘째자리까지만 출력 등 다양한 옵션을 줄 수 있다.

  • printf()return 값이 있다. printf() 를 변수에 저장한 후 해당 변수를 %u 형식 지정자와 함께 출력해보면 해당 printf() 가 출력한 문자열의 길이를 출력한다. 변수에 저장한다고 해서 출력이 이루어지지 않는 게 아니라 일단 출력이 되고 그 길이만을 반환한다는 점에 유의!

    int n_printed = printf("Counting!");
    printf("%u\n", n_printed); // 9 를 반환. ("Counting!" 의 길이.)

4.8 변환 지정자의 수식어들(modifiers)

출력할 때의 세세한 옵션 지정이 가능하다.
%[flag][width][.precision][length]specifier 의 순서로 작성하는데, 대괄호는 구분을 위한 것이지 실제로 작성하지는 않는다.

flag

  • '-' 는 default 값인 오른쪽 정렬 대신 왼쪽 정렬해준다.

  • '+' 는 양수일 경우에도 + 를 출력해준다.

  • '#' 는 진수에 따른 표기법을 다 표시해준다.

  • 0 은 width 가 정해져 있는 상태에서 빈 자리가 있을 때 빈칸 대신 0 으로 채워준다.

width

  • 숫자만큼의 최소 표시 자리수를 만들어준다. 예를 들어 %5i 라고 쓸 경우 한자리 수라도 5자리만큼을 차지하여 출력한다.

  • '*' 은, 그 자리에 또다른 변수를 넣을 수 있는 자리를 만든다. 즉 이 출력 옵션을 위한 변수 자리다. ex: `printf("%*i\n", 7, 456); 가 printf("%7\n", 456); 로 변환됨.`

.precision

  • 소수점 이하의 정밀 표시를 위한 자릿수를 설정한다. 출력 데이터의 소수점 아래 자릿수가 설정값보다 많은 경우 반올림되며, 부족한 경우 0으로 채운다.

  • 위 width 와 같이 '*' 옵션이 있다.

  • . 을 쓰고 그 뒤에 아무 숫자도 쓰지 않으면 0 이 들어간 것이라고 해석된다.

  • %.5s 처럼 string 형식에 쓰일 경우 string 의 자릿수를 정해준다. 즉 %.5s 는 5자리까지만 출력한다.

length

  • 데이터타입의 크기를 정한다. short, long, signed, unsigned 등과 관련있다.

4.9 print() 함수가 인자들을 해석하는 과정

4.10 scanf() 의 사용법

  • printf() 와 달리 '*' 는 그게 붙은 지정자를 무시하는 용도로 쓰인다. 입력은 받아야 되는데 무시됨.

  • printf() 와 달리 lf(double) 와 f 자료형이 구분된다.

  • 'j' 는 int_max_t 또는 uintmax_t 자료형으로 해석된다. ex: intmax_t i; scanf("%ji", i);

  • scanf("%i", &i); 에 숫자와 문자가 섞인 입력값을 넣으면, 숫자가 아닌 것을 만난 시점에서 입력이 중지된다. 즉 '123a456' 을 입력하면 123 까지만 입력받는다.

  • 여러 변수를 위한 값을 입력받을 때, 기본설정인 빈칸이나 줄바꿈 대신 다른 것으로 입력값을 구분하고 싶다면 형식 지정자 사이에 원하는 것을 써넣으면 된다. ex: scanf("%d,%d", &a, &b); // 쉼표(,) 를 기준으로 나누어져 입력됨.

  • scanf() 의 반환값은 입력받은 변수의 개수이다.