4.1 스트링 I/O
char fruit_name; // 하나의 문자만 저장
printf("What is your favorite fruit?");
scanf("%c", &fruit_name);
printf("You like %c!
\n", fruit_name);
char fruit_name(40);
printf("What is your favorite fruit?");
scanf("%s", fruit_name);
printf("You like %s!
\n", fruit_name);
fruit_name 자체는 배열을 나타내는 주소이므로 앞에 &를 붙일 필요가 없습니다.
4.2 오퍼레이터의 규모
int a = 0;
unsigned int int_size1 = sizeof a;
unsigned int int_size2 = sizeof(int);
unsigned int int_size3 = sizeof(a);
size_t int_size4 = sizeof(a);
size_t float_size = sizeof(float);
배열 크기
int int_arr(30);
int *int_ptr = NULL; // 배열의 주소값을 적을 수 있는 공간
int_ptr = (int*)malloc(sizeof(int) * 30); // 메모리를 받아서 그중 대표하는 메모리를 하나 받아서 적음
printf("Size of array = %zu bytes\n", sizeof(int_arr)); // 배열의 크기, 120bytes
printf("Size of pointer = %zu bytes\n", sizeof(int_ptr)); // 배열 주소를 적는 공간의 크기, 4bytes
문자열 배열의 크기
char c="a";
char string(10); // 맨 끝에 '/0'가 들어가기 때문에 최대 9개 문자 수용
size_t char_size = sizeof(char); // 1 bytes
size_t str_size = sizeof(string); // 10 bytes
printf("Size of char type is %zu bytes.\n", char_size);
printf("Size of string type is %zu bytes.\n", str_size);
구조의 크기
struct MyStruct
{
int i;
float f;
};
int main()
{
printf("%zu\n", sizeof(struct MyStruct)); // 8byte(int 4, float 4)
};
4.3 문자열이 메모리에 저장되는 구조
문자열의 끝을 ‘\0′(널 문자)로 표시한 다음 아무 것도 출력하지 마십시오.
int a = 1;
int int_arr(10) = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
printf("%i %i %i\n", int_arr(0), int_arr(1), int_arr(9));
printf("%i\n", int_arr(10000));
// 인덱스가 배열의 크기를 넘어서기 때문에 err
char c="a";
char str1(10) = "Hello"; // null character 때문에 크기는 6byte
// 문자열을 초기화할 때는 큰따옴표 사용
char str2(10) = { 'H', 'i' }; // 다른 방식으로 초기화
printf("%c\n", c);
printf("%s\n", str1);
printf("%s\n", str2);
printf("%hhi, %hhi, %hhi, %hhi\n", str2(0), str2(1), str2(2), str2(3), str2(4));
// 72 (H 아스키 코드) 105 (i 아스키 코드) 0 0 0 출력
char str3(10) = "Hello, World"; // 배열 크기가 충분하지 않아 err
char str3(20) = "Hello, \0World"; // printf함수에서 \0이후로 출력하지 않음, 실제로는 배열에 저장되어 있음
printf("%s\n", str3);
4.4 strlen() 함수
char str1(100) = "Hello";
char str2() = "Hello";
char str3(100) = "\0";
char str4(100) = "\n";
printf("%zu %zu\n"n sizeof(str1), strlen(str1)); // zu를 지원하지 않는 컴파일러도 간혹 존재, 100 5 출력
printf("%zu %zu\n"n sizeof(str2), strlen(str2)); // 6 5 출력
printf("%zu %zu\n"n sizeof(str3), strlen(str3)); // 100 0 출력
printf("%zu %zu\n"n sizeof(str4), strlen(str4)); // 100 1 출력
strlen() 함수는 null이 아닌 문자의 수를 계산합니다.
/*동적할당 예시*/
char *str5 = (char*)malloc(sizeof(char) * 100);
str(0) = 'H'; str(1) = 'e'; str(2) = 'l'; str(3) = 'l'; str(4) = 'o';
str(5) = '\0';
printf("%zu %zu\n", sizeof(str5), strlen(str5)); // 4 5 출력
4는 포인터 변수 자체의 크기입니다.
5는 문자 수입니다.
4.5 기호 상수 및 전처리기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define PI 3.141592f
#define AI_NAME "Friday"
int main()
{
float radius, area, circum;
printf("I'm %s.\n", AI_NAME);
printf("Input radius\n");
scanf("%f", &radius);
/*
area = 3.141592f * radius * radius; // area = pi * r * r
circum = 2.0 * 3.141592f * radius; // circum = 2.0 * pi * r
// 리터럴(상수)를 기호적 상수로 바꿔 사용하면 보기에도 깔끔하고 실수할 가능성도 줄음
*/
area = PI * radius * radius; // area = pi*r*r
circum = 2.0 * PI * radius; // circum = 2.0 * pi * r
printf("Area is %f\n", area);
printf("Circumference is %f\n", circum);
return 0;
}
컴파일러의 관점에서 기호 상수는 해당 상수로 대체하여 처리됩니다.
즉 인간을 위한 기능이다.
#define PI = 3.141592f
#define AI_NAME = "Friday"
덮어쓰지 않도록 주의
함수 내에서 정의할 수 있지만 나중에 변수의 상수 값을 다른 값으로 변경하면 오류가 발생할 수 있습니다.
const float pi = 3.141592f;
float const pi = 3.141592f;
최근에는 후자의 경우를 추천한다.
4.6 매니페스트 상수
매니페스트(분명하고 명백한) 상수, 기호 상수, 매니페스트 상수
limits.h(데이터 유형의 최대 범위를 미리 선언한 헤더) 등
4.7 printf() 함수의 변환 식별자
printf("제어-문자열", 아이템1, 아이템2, ...) 변수, 상수, 표현식 등
printf("%d + %d = %d", 1, a, 1 + a);
형식 지정자
전환 식별자
%(flags)(width)(p.precidion)(length)specifier
printf("%+10.5hi", 256);
double d = 3.14159265358979323;
// 한글자, '' 표시
printf("%c\n", 'A');
printf("%s", "I love you");
printf("Even if there's a small chance, \
we owe this to everyone who's not in this room to try.\n");
printf("\n");
// signed decimal integer
printf("%d %i %i %i\n", 1004, 1234, INT_MAX, UINT_MAX); // overflow 발생하여 -1 출력
printf("%u %u %u\n", 1024, -1, UINT_MAX); // overflow 발생하여 -1 출력
printf("\n");
// 부동 소수점 수, 10진수
printf("%f %f %lf\n", 3.141592f, d, d); // l 무시됨, printf 함수에서 float형을 출력할 때 double형으로 바꾸기 때문에
// 부동 소수점 수, 16진수, p-표기법
printf("%a %A\n", d, d);
// 부동 소수점 수, 16진수, P-표기법
printf("%e %E\n", d, d);
printf("\n");
// 부동 소수점 수, %e, %f처럼 보여줌(더 짧은 것), 지수가 -4보다 작거나 정밀도보다 크거나 같을 경우에는 %e
printf("%g %g\n", 123456.789, 1234567.89); // 1234567 1.23457e+06
// 부동 소수점 수, %E, %F처럼 보여줌(더 짧은 것), 지수가 -4보다 작거나 정밀도보다 크거나 같을 경우에는 %E
printf("%G %G\n", 123456.789, 1234567.89); // 1234567 1.23457E+06
printf("%g %g\n", 0.00012345, 0.000012345); // 0.00012345 1.2345e-05
printf("%G %G\n", 0.00012345, 0.000012345); // 0.00012345 1.2345E-05
printf("\n");
// unsigned octal integer
printf("%o\n", 9); // 11
// pointer
printf("%p\n", &d); // 이 변수가 사용하고 있는 메모리의 주소 출력
printf("\n");
// 16진수
printf("%x %X\n", 11, 11); // b B 출력
printf("%%\n", d); // d는 무시됨, % 출력
printf("\n");
printf("%9d\n", 12345); // 최소 9자리로 출력
printf("%09d\n", 12345); // 최소 9자리로 출력하는데 빈자리는 0으로 채움
printf("%.2f\n", 3.141592); // 소수점 2번째자리까지 출력
printf("%.20f %.f20lf\n", d, d);
printf("\n");
int n_printed = printf("Counting"); // printf 함수의 리턴값은 출력한 글자수
printf("%u\n", n_printed); // 9 출력
4.8 변환 지정자를 위한 수정자
%(flags)(width)(p.precidion)(length)specifier
printf("%+10.5hi", 256);
깃발
여러 옵션 중 하나를 선택하려면
– | 링크 삽입(왼쪽 정렬) 그렇지 않다면 맞다 너비와 함께 사용해야 합니다. |
+ | 긍정적인 경우에도 표시 표시 그렇지 않은 경우 음수인 경우에만 부호 표시 |
비어 있는 | 긍정적인 경우 비어 있음 |
# | 8진수와 16진수를 출력할 때 0과 0x를 함께 출력합니다. 지정자 o, x, X, a, A, e, E, f, F, g, G 등과 함께 사용됩니다. |
0 | 너비가 지정되면 나머지 공간은 0으로 채워집니다. |
넓은
숫자 | 인쇄할 최소 문자 크기입니다. 이 숫자보다 작으면 공백으로 채워집니다. |
* |
.정도
.숫자 | 최소 출력 정밀도와 자릿수를 보장하며, 숫자가 충분하지 않으면 0으로 채웁니다. |
.* |
길이
데이터 유형의 길이
printf("%10i\n", 1234567); // 1234567
printf("%-10i\n", 1234567); //1234567
printf("%+i %+i\n", 123, -123); //+123 -123
printf("% i \n% i\n", 123, -123); // 123,-123
printf("%X\n", 17); //11
printf("%#x\n", 17); //0x11
printf("%05i\n", 123); //00123
printf("%*i\n", 7, 456); // 456
printf("\nPrecision\n");
printf("%.3d\n", 1024); //1024
printf("%.5d\n", 1024); //01024
printf("%.3f\n", 123456.1234567); //123456.123
printf("%.3f\n", 123456.1235); //123456.124(반올림)
printf("%10.3f\n", 123.45678); // 123.457(반올림)
printf("%010.3f\n", 123.45678); //000123.457(반올림)
printf("%.5s\n", "ABCDEFGHIJKLMN"); //ABCDE
printf("%.s\n", "ABCDEFGHIJKLMN"); //
printf("\nLength\n");
printf("%hhd %hd %d\n", 257, 257, 257); //1(오버플로우 발생) 257 257
printf("%d %lld %lld\n", INT_MAX + 1, INT_MAX + 1, 2147483648LL); //-2147483648 2147483648 2147483648
4.10 scanf() 함수 사용
* : 무시하다
개수: 입력을 받을 수 있는 최대 너비
hh: 부호 있는 문자 또는 부호 없는 문자로 정수 읽기
ll: 정수를 long long 또는 unsigned long long으로 읽습니다.
h, l, L: %hd(%hi) -> 짧은 정수
%ho, %hx, %hu -> unsigned short int (%d, %i, %o, %x -> int)
%ld, %li -> 길다
%lo, %lx, %lu -> unsigned long
%le, %lf, %lg -> double(%e, f, %g -> float)
%Le, %Lf, %Lg -> 롱 더블
j: 데이터 유형 intmax_t 또는 uintmax_t(C99)
z: sizeof 연산자 반환 값의 데이터 유형
t: 두 포인터의 차이(C99)
입력을 받고 입력을 출력하는 것은 모두 scanf가 하는 일입니다.
/* multiple inputs with blank separators */
int i;
float f;
char str(30);
scanf("%d %f %s", &i, &f, str); // 문자열 앞에는 % 안붙음 % is absent in front of str
printf("%d %f %s\n", i, f, str);
/* character
* 문자 입력 시 빈칸도 문자로 입력받음, 아스키코드 32
*/
char c;
scanf("%c", &c);
printf("%i\n", c);
/* Unsigned as signed
* 음수를 넣었을 때 정상으로 나옴
* unsigned인데 받을 때 signed로 받아 unsigned 메모리에 저장해뒀다가 signed로 꺼내서 -가 그대로 붙어 나옴, 비추
*/
unsigned i;
scanf("%i", &i);
printf("%i\n", i);
/* Unsigned as unsigned
* 음수를 넣으면 오버플로우 발생하여 엉뚱한 값이 나옴
*/
unsigned i2;
scanf("%u", &i2);
printf("%u\n", i2);
/* floating point numbers */
// l for double for %f, %e, %E, %g
double d = 0.0;
scanf("%lf", &d); // lf, try E notation
printf("%f\n", d); // double 형에는 lf 변환지정자를 써야 함
/* Width
* 어느 자리까지 입력을 받을 것인지 설정 가능
*/
char str(30);
scanf("%5s", str); // 5번째 자리까지 입력받을 수 있음
printf("%s\n", str);
char i;
scanf("%hhd", &i); // 변수와 변환지정자 타입을 잘 맞춰줘야 함
printf("%i\n", i);
/* 문자와 정수를 함께 사용
* -> 문자 시작점부터 잘라서 i에 넣어줌
*/
int i;
scanf("%i", &i);
printf("%i\n", i);
/* j modifier
* intmax_t를 받는다는 의미로 j를 써줌 portable type
*/
intmax_t i;
scanf("%ji", &i);
printf("%ji", i);
/* regular characters, 정규식 */
int a, b;
scanf("%d,%d", &a, &b); // 입력시 해당하는 글자를 같이 넣어줘야 scanf가 제대로 인식, 공백 갯수는 상관 없음
scanf("%d ,%d", &a, &b);
scanf("%d, %d", &a, &b);
scanf("%d,%d", &a, &b);
scanf("%d-%d", &a, &b);
scanf("%dA%d", &a, &b);
printf("%d %d\n", a, b);
/* char recieve blank */
int a, b;
char c;
scanf("%d%c%d", &a, &c, &b); // 123A456 입력시
scanf("%d|%c|%d", &a, &c, &b); // 123|A|456 출력
// sentence, getchar() fgets(), etc.
/* scanf의 return 값
* item을 몇개나 입력받았는가
*/
int a, b;
int i = printf("%d%d", &a, &b); // i = 2
printf("%d", i);
/* printf()를 위한 *변환지정자 (modifier) */
int i = 123;
int width = 5; // from script, file, scanf, etx.
printf("Input width : ");
scanf("%d", &width);
printf("%*d\n", width, i); // width가 *에, i가 d에 들어가게 됨
/*width가 1이면 123 다 출력, 5면 ' 123' 출력*/
/* scanf()를 위한 *변환지정자 (modifier) */
int i;
scanf("%*d%*d%d", &i); /* *붙은 modifier는 넘어가고 마지막만 저장
scanf가 빈칸이나 줄바꿈을 찾아 인식하고 중간에 다른 기호가 있는 경우 기호와 빈칸 조합하여 진행
123 456 789 입력시 i에 789 저장 */
printf("Your third input = %d", i);