4.1 문자열 입출력하기
#include <stdio.h>
int main()
{
char fruit_name[40]; // 문자열 배열
printf("What is your favorate fruit?\n");
scanf("%s", fruit_name); // 문자열 배열이므로 %s
printf("You like %s \n!", fruit_name);
return 0;
}
4.2 sizeof 연산자
#include <stdio.h>
#include <stdlib.h>
struct MyStruct
{
int i;
float f;
};
int main()
{
/* 1. sizeof basic types */
int a = 0;
unsigned int int_size1 = sizeof a; // 크기를 나타낼때 음수를 쓰지는 않으므로 unsigned int 자료형 사용
unsigned int int_size2 = sizeof(int);
unsigned int int_size3 = sizeof(a);
size_t int_size4 = sizeof(a); // 다른 시스템에서는 sizeof의 자료형이 unsigned int가 아닐 수 있으므로 typedef unsigned int size_t로 이식성을 높임
size_t float_size = sizeof(float);
printf("Size of int type is %u bytes.\n", int_size1); // Size of int type is 4 bytes. // unsigned에 대응하는 형식지정자 %u
printf("Size of int type is %zu bytes.\n", int_size4); // Size of int type is 4 bytes. // size_t에 대응하는 형식지정자 %zu
printf("Size of float type is %zu bytes.\n", float_size); // Size of float type is 4 bytes.
/* 2. sizeof arrays */
int int_arr[30]; // int_arr[0] = 1024; ...
int* int_ptr = NULL;
int_ptr = (int*)malloc(sizeof(int) * 30); // int_ptr[0] = 1024; ...
printf("Size of array = %zu bytes\n", sizeof(int_arr)); // Size of array = 120 bytes
printf("Size of pointer = %zu bytes\n", sizeof(int_ptr)); // Size of pointer = 4 bytes // 주소를 적는 메모지의 사이즈
/* 3. sizeof character array */
char c = 'a';
char string[10]; // maximally 9 character + '\0' (null character)
size_t char_size = sizeof(char);
size_t str_size = sizeof(string);
printf("Size of char type is %zu bytes.\n", char_size); // Size of char type is 1 bytes.
printf("Size of string type is %zu bytes.\n", str_size); // Size of string type is 10 bytes.
/* 4. sizeof structure */
printf("%zu\n", sizeof(struct MyStruct)); // 8 -> int 4 + float 4
return 0;
}
4.3 문자열이 메모리에 저장되는 구조
#include <stdio.h>
int main()
{
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[10]); // -858993460 -> int_arr[10]은 널문자 '\0'
char c = 'a';
char str1[10] = "Hello";
char str2[10] = { 'H', 'i' };
printf("%c\n", c);
printf("%s\n", str1);
printf("%s\n", str2);
printf("%hhi %hhi % hhi %hhi %hhi\n",
str2[0], str2[1], str2[2], str2[3], str2[4]); // 72 105 0 0 0
//char str3[10] = "Hello, World"; // array size is not enough
char str3[20] = "Hello, \0World";
printf("%s\n", str3); // Hello, -> \0을 만나 끊김
return 0;
}
4.4 strlen() 함수
#include <stdio.h>
#include <string.h> // strlen and more
int main()
{
char str1[100] = "Hello"; // 컴파일러가 \0 이후에 0을 채워주게 된다.
char str2[] = "Hello"; // 글자에 맞게끔 컴파일러가 공간을 할당해줌.
char str3[100] = "\0"; // 빈칸과 \0은 아스키 코드가 다르다.
char str4[100] = "\n";
printf("%zu %zu\n", sizeof(str1), strlen(str1)); // 100 5// 간혹 %zu를 지원안해주는 경우가 있다. // strlen는 인간에게 의미있는 것만 세준다.
//********************************************************
printf("%zu %zu\n", sizeof(str2), strlen(str2)); // 6(문자열+'\0') 5
//********************************************************
printf("%zu %zu\n", sizeof(str3), strlen(str3)); // 100 0 '\0' 문자로인식X
printf("%zu %zu\n", sizeof(str4), strlen(str4)); // 100 1 '\n' 문자로인식o
/*Extra;*/
// 동적할당에 대해서. 나중에 배울건데, 미리 예제로 넣으심.
char* str5 = (char*)malloc(sizeof(char) * 100);
str5[0] = 'H'; str5[1] = 'e'; str5[2] = '1'; str5[3] = '1'; str5[4] = 'o';
str5[5] = '\0'; // 동적할당은 널문자 직접 넣어줘야함
// 동적할당을 할경우에는 위의 예제처럼 편리하게 할 수가 없음.
// 물론 다 처리해주는 다른 프로그래머들의 library를 가져다 쓰면 해결이 되지만
// 기본문법은 편리하지 않다.
printf("%zu %zu\n", sizeof(str5), strlen(str5)); // 4(포인터 변수 자체 사이즈) 5
// >>> 4byte는 포인터 변수 자체의 사이즈
// str1[100]은 컴파일러가 사이즈를 100byte라고 알고있기 때문에 알려줄 수 있지만,
// char *str5는 도대체 얼마나 메모리를 많이 가져와서 할당을 받고, 오퍼레이팅 시스템에게
// 이 메모리 쓸게요 하면서 받아올 지를 알 수가 없기 때문에
// 그냥 포인터 변수 주소를 적는 메모지의사이즈 만큼만 알 수 있다.
// 지금은 sizeof 와 기능적으로 내용들이 다르게 나온다 정도만 이해.
// 5는 글자수.
return 0;
}
4.5 기호적 상수와 전처리기 #define
전처리기 #define 은 사람을 위해, 프로그래머를 위해 사용 - 실수를 줄이고 사용과 보기 용이함
매크로에서 많이 사용
대문자 상수를 쓰는 것이 일반적
※최근에 기호적 상수 권장하는 방식 const
const float pi = 3.141592f; // const 변수 선언을 통해서 기호적 상수(pi) 선언을 할 수 있음
#define PI 3.141592
#define PI = 3.141592 로적으면 "= 3.141592" 통째로 사용
#include <stdio.h>
#define PI 3.141592f // 기호적 상수 선언 (기호가 상수를 대체해서 사용) - 사용과 보기 용이함
#define AI_NAME "Jarvis"
int main()
{
float radius, area, circum;
printf("I'm %s.\n", AI_NAME);
printf("Please, Input radius\n");
scanf("%f", &radius);
area = PI * radius * radius; // area = pi*r*r
circum = 2.0 * PI * radius; // circum = 2.0 * pi * r
// sphere area, sphere volume, ...
printf("Area is %f\n", area);
printf("Circumference is %f\n", circum);
//TODO: wrong usage, strings, const
return 0;
}
4.6 명백한 상수들 manifest constants
복붙과 사용이 유사하다
#include <stdio.h>
#include <limits.h> // INT_MAX, ..., etc.
#include <float.h> // FLT_MAX, ..., etc.
#define PI 3.141592 // manifest constants, symbolic constants
int main()
{
printf("PI is %f\n", PI); // PI is 3.141592
printf("Biggest int: %d\n", INT_MAX); // Biggest int: 2147483647
printf("One byte in this system is %d bits\n", CHAR_BIT); // One byte in this system is 8 bits
printf("Smallest normal float %e\n", FLT_MIN); // Smallest normal float 1.175494e-38
}
4.7 printf() 함수의 변환 지정자들 conversion specifiers
출력을 어떻게 할지 해석을 하는 기능에 가깝다



#include <stdio.h>
#include <limits.h>
#include <float.h>
int main()
{
double d = 3.141592653589793238462643383279502884197169399375105820974944;
printf("%c\n", 'A'); // A
printf("%s", "I love you\n"); // I love you // 출력을 하려는 문자열에 '\n'을 넣어도 줄바꿈이 됨
printf("Even if there's a small chance, \
we owe this to everyone whos not in this room to try.\n");
//출력상 줄바꿈이 아니고, 코딩하는데 읽기 불편해서 줄바꿈 할 경우에 '\' 사용. 없으면 컴파일 에러
// Even if there's a small chance, we owe this to everyone whos not in this room to try.
printf("\n");
printf("%d %i %i %i\n", 1004, 1234, INT_MAX, UINT_MAX); // 1004 1234 2147483647 '-1(overflow)'
// %i(signed integer) 범위에 UINT_MAX(unsigned integer)를 넣었으니 overflow
printf("%u %u %u\n", 1024, -1, UINT_MAX); // 1024 '4294967295(overflow)' 4294967295
// %u(unsigned integer) 범위에 -1(음수)을 넣어 overflow
printf("\n");
printf("%f %f %lf\n", 3.141592f, d, d); // 3.141592 3.140000 3.140000
// double을 쓸려면 float 에서 l을 붙여줘야 하지 않을까.
// 맞는 말인데, 다음강에서 설명해 주신다고 함.
// 전통적인 이유로 float을 넣으면 double로 처리된다고 함.
// 그러므로 printf를 할떄는 l을 붙일 필요 없지만 sancf는 붙여야함.
printf("%a %A\n", d, d); // 0x1.91eb851eb851fp+1 0X1.91EB851EB851FP+1
printf("%e %E\n", d, d); // 3.140000e+00 3.140000E+00
printf("\n");
printf("%g %g\n", 12345.6789, 12345678.9); // 12345.7(%f, 유효숫자 6자리) 1.23457e+07(%e)
printf("%G %G\n", 123456.789, 1234567.89); // 123457 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
//%f %e인지 컴파일러가 정해줌.
printf("\n");
printf("%o\n", 9); // 11
printf("%p\n", &d); // 010FF85C
// pointer-of pperator
//d변수가 가지고있는 메모리의 주소를 출력할 수 있다.
printf("\n");
printf("%x %X\n", 11, 11); // b B
// 16진수
printf("%%\n", d); // %
printf("\n");
printf("%9d\n", 12345); // 12345
//숫자를 쓸때 9자리를 써라. 나머지는 빈칸.
printf("%09d\n", 12345); // 000012345
//위에서 앞에 빈칸을 0으로 써라
printf("%.2f\n", 3.141592); // 3.14
// 소수점이하자리를 2자리만 출력해준다.
printf("%.20f %.20lf\n", d, d); // 3.14000000000000012434 3.14000000000000012434
// 앞에 숫자가 붙으면 자릿수를 맞춰줄 수 있다.
printf("\n");
int n_printed = printf("Counting!");
//printf("Counting!")가 출력한 값을 n_printed에 담음
printf("%u\n", n_printed); // Counting!9 // 숫자 9는 문자열의 글자개수
//n_printed를 출력하면 어떻게 되나
//********************************************************
// printf를 변수에 담은 return값은
// 선언할때의 printf("Counting!")이 출력되고
// 출력할 글자의 개수이다
//********************************************************
return 0;
}
4.8 변환 지정자의 수식어들 modifiers

['+': 부호를 표시]
[10: 10자리]
[.5: 정밀도 5자리]
[h: 짧은것 담음]
i: 정수

[flag] 여러가지를 할 수 있을 때 그 중에 어떤 방식으로 출력을 할 것이다
-: 왼쪽으로 붙여라 -flag가 있으면 있으면 왼쪽, 없으면 오른쪽으로 default, ‘width'랑 같이 써야한다.
+: -의 반대개념이 아니다. +는 양수일때도 +기호를 출력하라.
space: 부호가 없을경우. 양수일 경우 빈칸이 출력
#: 16진수등을 출력할때 0, 0x, 0X 출력하는 옵션.
0: width 지정해줬을때 남는자리를 0으로 채운다.

[width]
숫자를 넣어주면 123인데 숫자 5를 지정해주면 앞에 빈칸 2개 생김
[.precision] 정밀도 조정
'.number' 숫자 자릿수 만큼 최소 출력되는 정밀도를 보장하는 것. 숫자가 부족하면 0으로 채워버림.
‘.*’ 용법은 위와 비슷한데 예제로 설명해주심.

[legnth] 데이터 타입(메모리)의 길이.
h: 짧은것
l: 긴것
z: sizeof
ptrdiff_t: 주소의 차이
(none): float는 내부적으로 double로 바뀌기 때문에 printf는 double만 출력
L: long double 출력하려면 L 붙여줌
n같은 경우가 표준 스펙은 있는데 구동도 안됨.
#include <stdio.h>
#include <limits.h>
int main()
{
printf("%10i\n", 1234567); // 1234567
// 1234567 10자리가 안되서 앞에 빈칸으로 채워짐.
printf("%-10i\n", 1234567); // 1234567
// '-' 빈칸 상관없이 왼쪽으로 정렬됨.
printf("%+i %+i\n", 123, -123); // +123 -123
// '+' +인지 -인지 꼭 표기해줌.
printf("% i \n% i\n", 123, -123); // 123 // +인경우 부호자리 space.
// 'space' // -123
printf("%X\n", 17); // 11
// 17을 16진수로
printf("%#X\n", 17); // 0X11
// '#' 0X로 표기
printf("%#x\n", 17); // 0x11
// 소문자일경우.
printf("%05i\n", 123); // 00123
//5는 width, 0이 붙으면 남는자리 0으로 채워줌.
//file이름 같은거 지어줄때 필요함.
printf("%*i\n", 7, 456); // 456
// 자리는 하난데 item은 2개. 왜 ? 7이 *자리로 들어감.
// 즉 width를 뒤에서 안에서 바꾸는게 아니라 뒤에서 바꾸고 싶을때 사용.
// scanf에선 의미가 다름. 나중에 설명.
printf("\nPrecision\n"); // Precision
printf("%.3d\n", 1024); // 1024 //정수는 .3d를 해도 소수점이 없으므로 '.'은 영향이 없는건가?
// 작으면 그냥 출력되고
printf("%.5d\n", 1024); // 01024
//크면 채워주려고 앞에 0넣어줌.
printf("%.3f\n", 123456.1234567); // 123456.123
//위에는 d(정수)인거고 f는 소수점 이하자리. 이경우 3자리
printf("%.3f\n", 123456.1235); // 123456.124
// 반올림이 된다.
printf("%10.3f\n", 123.45678); // 123.457
//10은 전체 자리수(소수점 아래 포함)를 의미하고 .3f이므로 소수점 이하는 3자리만.
printf("%010.3f\n", 123.45678); // 000123.457
printf("%.5s\n", "ABCDEFGHIJKLMN"); // ABCDE
//string이랑 사용하면 5개만 끊어버림
printf("%.s\n", "ABCDEFGHIJKLMN"); // 아무글자도 출력x
//.뒤애 숫자입력이없으면 .0이랑 동일하게 작동. string뿐만아니라 decimal floating 둘다 동일하게 작동.
printf("\nLength\n");
printf("%hhd %hd %d\n", 257, 257, 257); // 1(overflow) 257 257 // hhd(signed char) hd(short int)
printf("%d %lld %lld\n", INT_MAX + 1, INT_MAX + 1, 2147483648LL); // -2147483648(overflow) 2147483648 2147483648
// LL은 x64(64비트)에서 작동시킬것.
// // -2147483648 -9223372034707292160 28731583158550528 // x86에서 작동시 출력값
return 0;
}
4.9 printf() 함수가 인자들을 해석하는 과정

/**************************************************
printf는 부동소수점이 들어오면 double로 변환
그렇기 때문에 %f를 써도 문제 x (but scanf는 double은 무조건 %lf)
/**************************************************
n1은 float 부동소수점이므로 double로 변환
n2는 double이므로 유지
n3는 4bytes
but, 위 그림에서 %d 이므로 n1에 4bytes 쌓이고 나머지 4bytes에 또 쌓이고 n2에 4bytes 쌓이고 끝
해석을 할때는 %d를 사용했으므로 4bytes만 읽고 출력을 하려고해서 문제가 생김
#include <stdio.h>
#include <limits.h>
int main()
{
float n1 = 3.14; // 4byte이긴한데printf가8바이트변환.
double n2 = 1.234; // 8byte
int n3 = 1024; // 4byte
printf("%f %f %d\n\n", n1, n2, n3); // 3.140000 1.234000 1024
// Note the warnings in output window
printf("%d %d %d\n\n", n1, n2, n3); // 4,4,4(N,N,N) // 1610612736 -927712936 1024
// %d 4 4 4로읽으니 스택에서 밀려읽게됨. 연쇄적으로 전부 다 이상한 값이 생성.
printf("%lld %lld %d\n\n", n1, n2, n3); // 8,8, 4(N,N,Y) // 4614253070451212288 4608236261112822104 1024
// 이거는타입이안맞아서그렇다. 부동소수점수를 강제로integer인것처럼
// 해석을하고 출력을하려고드니까 이상한숫자가 나온것이다.
// n3는 데이터 타입은 맞으므로(스택에서 밀리지 않았으므로) 제대로 출력
printf("%f %d %d\n\n", n1, n2, n3); // 8,4,4 (Y,N,N) // 3.140000 -927712936 1024
// 마지막 %d는 타입도맞고 byte도 맞아보이나 앞에서 밀려읽었기 때문에 문제가생김.
printf("%f %lld %d\n\n", n1, n2, n3); // 8,8,4 (Y,N,Y) // 3.140000 4608236261112822104 1024
// 가운데꺼만잘안나옴. byte는맞으나, type이안맞기때문.
return 0;
}
4.10 scanf() 함수의 사용법


※ '*'의 의미가 printf와는 다르다
#include <stdio.h>
#include <inttypes.h> // intmax_t 사용위해
#include<Windows.h>
int main()
{
/* multiple inputs with blank separators*/
int i;
float f;
char str[30];
scanf("%d %f %s", &i, &f, str); // 123 123 hello hi
Note % is absent in front of str
//printf에서는 double 입력받을때도 %f써도 문제 없는데,
//scanf에서는 %lf로 써야한다.
printf("%d %f %s\n", i, f, str); // 123 123.000000 hello
/* character */
char c;
scanf("%c", &c); // a
printf("%i\n", c); // 97
// 문자를 정수로 출력하려고하는 코드. 아스키코드를 출력하려고 하는것.
// 빈칸도 문자로 입력 받는다. blank is 32.
// 위에선 구분의 용도로 빈칸. 여기선 문자 입력이므로 빈칸도 문자로 인식.
///* Unsigned as signed*/
unsigned i;
// unsigned를 선언하고
scanf("%i", &i); // -123
printf("%i\n", i); // -123
// signed를 출력하면 어떨까
// 분명히 unsigned인데, 받을 때 %i(signed)로 받고, 그 받은 것을
// unsigned memory에 저장해놨다가 출력해서 signed가 정상 출력 되는 것.
요런 트릭은 사용하지 않는 것이 좋다.
/* Unsigned as unsigned*/
unsigned i2;
scanf("%u", &i2); // -123
printf("%u\n", i2); // 4294967173
//unsigned는 unsigned로 대접해 주는게 제일 깔끔.
/*floating point numbers*/
l for double for %f, %e, %E, %g
double d = 0.0;
scanf("%lf",&d); // scanf double은 %lf로 받아야한다.
printf("%f\n", d); // printf는 %f
float d = 0.0;
scanf("%f", &d); //float은 f로.
printf("%f\n", d);
/* width */
char str[30];
scanf("%5s", str); //5글자 까지만 입력을 받겠다.
printf("%s\n", str);
/* h modifier */
char i; // 입력받는 변수의 사이즈 맞춰줘야한다.
scanf("%hhd", &i);
printf("%i\n", i);
/*integer with characters*/
// 문자를 섞어서 하면 , 문자를 만나게 될때 더이상 출력안함.
// 숫자들만 가지고 i에 넣어줌.
int i;
scanf("%i", &i); // 123a456
printf("%i\n", i); // 123 (integer이므로 문자 전까지만 출력)
/* j modifier */
intmax_t i; // int max 포터블 타입.
scanf("%ji", &i); //j는 이 포터블타입을 받아 들이겠다.
printf("%ji", i);
/* Regular characters */
나중에 정규식이라는게 있음. 규칙에 맞춰 입력받는다.
이 강의를 벗어남. 나중에 확장될 수 있다.
int a, b;
scanf("%d ,%d", &a, &b); // 여러개 입력할 때 구분법으로
// space나 enter로 구분했는데 이번엔 ,로 구분할 것이다.
//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 receives blank*/
int a, b;
char c;
scanf("%d%c%d", &a, &c, &b); // try 123 456 (blank)
printf("%d|%c|%d", a, c, b); // | is separator
sentences?, getchar(), fgets(), etc.
입출력을 받는 다른함수, 파일로도, 한글자로도 등등..
/*return value of scanf()*/
scanf의 return값은 item을 몇개 입력 받았는가
int a, b;
int i = scanf("%d%d", &a, &b); // ab
printf("%d", i); // 2
/* *modifier for printf() */
int i = 123;
int width = 5;
printf("Input width : ");
/**************************************************
scanf("%d", &width);
printf("%*d\n", width, i); // *에 width 대응
/**************************************************
/* *modifier for scanf() */
int i;
/**************************************************
scanf("%*d%*d%d", &i); // 12 23 56
//%*d는 *때문에 무시된다.
printf("Your third input = %d", i); // Your third input = 56
/**************************************************
//1회 입력하면 입력을 받긴 받았는데 1,2회는 무시되고
//3회%d가 출력된다. 구분은 빈칸 or 줄바꿈. 다른 기호, 문자를 쓰면 다른걸로 구분가능.
//surpress
return 0;
}
'Programming > C' 카테고리의 다른 글
[따배씨] 섹션5. 연산자, 표현식, 문장 (0) | 2020.07.22 |
---|---|
[따배씨] 섹션 3. 데이터와 C언어 (0) | 2020.07.16 |
[따배씨] 섹션 2. C언어 소개 (0) | 2020.07.16 |
[따배씨] 섹션 1. 천천히 시작해봅시다 (0) | 2020.07.16 |
[따배씨] 섹션 0. 초보 프로그래머를 위한 컴퓨터의 작동원리 (0) | 2020.07.16 |
댓글