|
|
19장
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | //19-1-1(1) #include <stdio.h> int WhoIsFirst(int age1, int age2, int (*cmp)(int n1, int n2)); //함수의 자료형: int ()(int, int, int(*)(int, int)) int OlderFirst(int age1, int age2); //함수명의 자료형: int(*)(int, int) int YoungerFirst(int age1, int age2); //함수명의 자료형: int(*)(int, int) int main(void) { int age1 = 20; int age2 = 30; int first; printf("입장순서 1 \n"); first = WhoIsFirst(age1, age2, OlderFirst); //WhoIsFirst함수의 3번째 매개변수 자료형과 OlderFirst함수 자료형 일치 printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first); printf("입장순서 2 \n"); first = WhoIsFirst(age1, age2, YoungerFirst); //WhoIsFirst함수의 3번째 매개변수 자료형과 YoungerFirst함수 자료형 일치 printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first); return 0; } int OlderFirst(int age1, int age2) { if (age1 > age2) return age1; else if (age1 < age2) return age2; else return 0; } int YoungerFirst(int age1, int age2) { if (age1 < age2) return age1; else if (age1 > age2) return age2; else return 0; } int WhoIsFirst(int age1, int age2, int (*cmp)(int n1, int n2)) { return cmp(age1, age2); //int()(int, int)* cmp = OlderFirst = YoungerFirst } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //19-1-1(2) #include <stdio.h> int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main(void) { int (*fp[4])(int, int); //함수 포인터 배열 fp[0] = add; // fp[0]에 add함수의 주소 저장 fp[1] = sub; // fp[1]에 sub함수의 주소 저장 fp[2] = mul; // fp[2]에 mul함수의 주소 저장 fp[3] = div; // fp[3]에 div함수의 주소 저장 for (int i = 0; i < 4; i++) { printf("배열[%d] 함수의 실행 값 : %d\n", i, fp[i](20, 10)); } return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //19-1-2 #include <stdio.h> int JetData(void* p_data, char type) { //void*: 인자에 어떠한 포인터 자료형(주소)이 오든 대입이 가능한 매개변수, 첫 번째 인자에 대한 타입을 알려주어 강제 형변환을 통해 값을 바꾸기위한 매개변수 int result = 0; if (type == 1) result = *(char*)p_data; //char형을 가리킴 else if (type == 2) result = *(short*)p_data; //short형을 가리킴 else if (type == 4) result = *(int*)p_data; //int형을 가리킴 return result; } void main(void) { int data = 123456; printf("%d\n", JetData(&data, 4)); //int data의 type == sizeof(data) return 0; } | cs |
20장
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | //20-도전1 #include <stdio.h> void turn(int* arr, int* arr2); void show(int* arr2); int main(void) { int arr[4][4] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }; int arr2[4][4] = { 0 }; for (int k = 0; k < 3; k++) { turn(arr, arr2); show(arr2); printf("\n"); } return 0; } void turn(int* arr, int* arr2) { int i = 3, j = 0; for (int a = 0; a < 4; a++) { for (int b = 0; b < 4; b++) { *(arr2 + (4 * b) + i) = *(arr + (4 * j) + b); //90도 회전 } i--; j++; } i = 3; j = 0; for (int a = 0; a < 4; a++) { for (int b = 0; b < 4; b++) { *(arr + (4 * b) + i) = *(arr2 + (4 * b) + i); //회전한 값을 arr배열에 초기화 } i--; j++; } } void show(int* arr2) { for (int a = 0; a < 4; a++) { for (int b = 0; b < 4; b++) { printf("%d ", *(arr2 + (4 * a) + b)); } printf("\n"); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //20-도전3 #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { srand((unsigned int)time(NULL)); printf("난수의 범위: 0부터 99까지\n"); //for (int i = 0; i < 5; i++) // printf("난수 출력: %d\n", rand() % 100); int i = 0; while (i < 5) { int random = rand() % 100; if (random >= 0 && random < 100) { printf("%d\n", random); i++; } } return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | //20-도전5 #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:6031) #include <stdio.h> #include <stdlib.h> #include <time.h> char* show(int x); int main(void) { int x, y, w = 0, l = 0, t = 0; srand((int)time(NULL)); for (int i = 0; i < 4; i++) { printf("바위는 1, 가위는 2, 보는 3: "); scanf("%d", &x); y = (rand() % 3) + 1; printf("당신은 %s 선택, 컴퓨터는 %s 선택, ", show(x), show(y)); if ((x == 1 && y == 2) || (x == 2 && y == 3) || (x == 3 && y == 1)) { printf("이겼습니다!\n"); w++; } else if ((x == 1 && y == 3) || (x == 2 && y == 1) || (x == 3 && y == 2)) { printf("졌습니다!\n"); l++; } else { printf("비겼습니다!\n"); t++; } printf("\n"); } printf("게임의 결과: %d승, %d패, %d무\n", w, l, t); return 0; } char* show(int x) { if (x == 1) return "바위"; if (x == 2) return "가위"; if (x == 3) return "보"; } | cs |
21장
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //21-1-1 #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:6031) #include <stdio.h> int main(void) { char c; while (1) { printf("문자 입력: "); scanf(" %c", &c); if (c == 'q' || c == 'Q') break; printf("입력된 문자: %c\n", c); } return 0; } | cs |
21-1-2번 이유
scanf함수가 실행될 때 버퍼가 비어있으면 운영체제 함수가 호출되고 버퍼로 입력을 하게됨.
엔터키가 입력이 되면 scanf함수에서 설정한 서식문자와 서식문자의 개수에 맞게 각 변수에 저장 후 버퍼에서 사라지는데 엔터키('\n')는 남아있게 됨.
scanf(“%c”, &blood_type); 이 코드가 실행되면 버퍼에는 엔터키가 남아있어 입력 버퍼를 실행시키지 않고 blood_type에 엔터키를 저장시킴.
결과적으로 입력을 패스하기 때문에 그 다음 코드가 바로 실행되는 것.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //21-1-2 #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:6031) #include <stdio.h> int main(void) { char name[10]; char blood_type; printf("이름을 입력하시오: "); scanf("%s", name); //입력한 데이터(아스키코드로 버퍼에 저장)가 공백 이전까지 문자열로 배열에 저장 printf("혈액형을 입력하시오: "); scanf(" %c", &blood_type); //버퍼에 '\n'이 저장되어 있는데 %c앞에 공백을 추가함으로써 '\n'무시 printf("이름: %s\n", name); printf("혈액형: %c\n", blood_type); return 0; } | cs |
21-1-3번
처음 scanf함수가 실행될 때는 버퍼가 비워져있어 입력을 할 수 있음.
scanf함수의 서식문자는 %c임. => 버퍼에 있는 하나의 문자를 변수 ch에 저장.
다음 scanf함수가 실행되면 버퍼에는 데이터가 남아있어 입력 버퍼가 실행이 안되고, printf함수가 실행됨.
이때 변수 ch에 남아있는 하나의 문자를 저장. 이 과정을 반복하게 됨.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //21-1-4 #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:6031) #include <stdio.h> int main(void) { char str[20]; int i = 0; printf("문자열을 입력하시오: "); while (i < sizeof(str)) { scanf("%c", (str + i)); if (str[i] == '\n') break; i++; } str[i] = '\0'; printf("문자열: %s\n", str); return 0; } | cs |
21-2-1번
(두번째 인자에 입력한 값(n) - 1)개의 문자를 저장
21-2-2번
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //21-2-3 #include <stdio.h> int main(void){ char name[10], add[30], carNum[15]; fputs("이름: ", stdout); fgets(name, sizeof(name), stdin); fputs("주소: ", stdout); fgets(add, sizeof(add), stdin); fputs("자동차 번호: ", stdout); fgets(carNum, sizeof(carNum), stdin); puts("<결과출력>"); printf("이름: %s주소: %s자동차 번호: %s\n", name, add, carNum); return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //21-2-4 #include <stdio.h> int main(void){ char str[20]; int i = 0; fputs("문자열 입력: ", stdout); fgets(str, sizeof(str), stdin); while (str[i] != '\n') { if (str[i] >= 'a' && str[i] <= 'z') str[i] -= ('a' - 'A'); i++; } printf("대문자로 변환결과: %s\n", str); return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //21-3-1 #include <stdio.h> #include <string.h> int main(void) { char c[10], str[100] = ""; while (1) { fputs("문자열 입력: ", stdout); fgets(c, sizeof(c), stdin); c[strlen(c) - 1] = ' '; if (!strcmp(c, "quit ")) break; strcat(str, c); printf("입력된 문자열: %s\n", str); } return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //21-3-2 #include <stdio.h> #include <string.h> int my_strlen(char* ptr); void RemoveBSN(char* ptr); int main(void) { char str[100]; printf("문자열 입력: "); fgets(str, sizeof(str), stdin); printf("길이: %d, 내용: %s \n", my_strlen(str), str); RemoveBSN(str); printf("길이: %d, 내용: %s \n", my_strlen(str), str); return 0; } int my_strlen(char* ptr) { return strlen(ptr); } void RemoveBSN(char* ptr) { ptr[strlen(ptr) - 1] = '\0'; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //21-3-3 #include <stdio.h> #include <string.h> void my_strcpy(char* ptr2, char* ptr1); int main(void) { char str1[20] = "1234567890"; char str2[20]; my_strcpy(str2, str1); puts(str2); return 0; } void my_strcpy(char* ptr2, char* ptr1) { int i = 0; while (*(ptr1+i) != NULL) { *(ptr2 + i) = *(ptr1 + i); i++; } *(ptr2 + i) = NULL; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //21-3-4 #include <stdio.h> #include <string.h> void my_strcat(char* ptr1, char* ptr2); int main(void) { char str1[20] = "First~"; char str2[20] = "Second"; my_strcat(str1, str2); puts(str1); return 0; } void my_strcat(char* ptr1, char* ptr2) { int i = 0; while (*(ptr1 + i) != NULL) { *(ptr1 + strlen(ptr1)) = *(ptr2 + i); i++; } } | cs |
21장 정리문제
1) 문자는 컴퓨터에서 어떻게 저장되는가?
응용프로그램이 호출되면 운영체제가 자동으로 스트림을 생성하여 키보드로부터 입력을 하게되면 버퍼에 아스키코드로 저장.
scanf함수의 서식문자에 따라 자료형이 변환되어 메모리에 저장.
2) 문자입력함수를 아는대로 설명하라.
입력함수가 호출되면 입력버퍼가 비워져있을 때 운영체제에 의해서 입력스트림이 실행되고 엔터키를 입력받으면 종료.
문자입력함수 getchar, fgetc는 입력버퍼에 아스키코드로 저장된 문자를 읽어 정수형으로 리턴.
반환형이 int인 이유는 오류나 파일의 끝이 입력되었을 때 -1을 반환하게 되는데 char형은 unsigned char로 처리하는 컴파일러가 존재하기 때문.
3) 문자출력함수를 아는대로 설명하라.
문자출력함수 putchar, fputc가 호출되면 출력데이터를 버퍼로 전송하고 버퍼에 아스키코드 형식으로 저장되어있는 문자 한 개를 모니터에 출력.
4) 다음 문장을 실행할 때 문제점을 설명하라.
scanf(“%d”,&num);
scanf(“%c”,&ch);
첫 번재 코드의 실행과정은 입력함수를 호출했는데 입력버퍼가 비워져 있으니 운영체제가 입력버퍼를 호출하고 엔터키를 입력 받을 때까지 버퍼에 저장을 함.
두 번째 코드의 실행과정은 입력함수를 호출했는데 입력버퍼에 입력한 값+'\n'가 저장되어있어 아무런 실행없이 다음 코드로 넘어가는 문제점.
5) 4번의 해결방법을 설명하라. 게시판의 문자 및 문자열 입력시 엔터키 처리방 법을 참고할 것
두 번째 코드 실행시 버퍼에 '\n'이 남는 문제점이 발생.
%c앞에 공백을 추가하면 버퍼에 남아있는 공백문자를 무시하기 때문에 입력버퍼가 엔터키 입력 받을 때까지 대기.
변수에 저장되는 값도 엔터키를 제외하고 공백문자가 있기 직전까지의 값을 저장됨.
6) 널문자의 역할은?
문자열에 끝을 알려줌.
7) 널문자를 자동으로 저장해주는 경우를 설명하라.
char형 포인터를 선언과 동시에 초기화하는 경우와 키보드로부터 입력하는 경우.
8) scanf함수로 문자열을 입력받을 때 종료문자는?
'\n'
9) gets함수로 문자열을 입력받을 때 종료문자는?
'\n'
10)scanf와 gets함수의 차이점은?
scanf의 첫 번째 매개변수에 %s로 지정문자를 사용했을 때 gets함수와 공통점으로는 '\n'입력시 문자열 입력을 종료하는 것.
차이점: gets함수는 해당 메모리에 저장할 때 문자열 끝에 '\n'를 저장하지 않고 '\0'(NULL문자)로 저장.
11) 문자열 출력함수를 설명하라.
gets함수는 널문자를 만날때까지의 문자열을 출력 후 '\0'를 '\n'로 대체. 결과적으로 문자열을 출력하고 개행처리까지 실행.
fgets함수는 개행처리 안 함.
12) C표준라이브러리 함수인 strcpy, strlen, strcat과 똑같은 기능을 갖는 함수를 작성하시오. 함수를 활용하는 예제까지 포함하여 만들것.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | //21장 정리문제 12번 #include <stdio.h> char* get_strcpy(char* str1, char* str2); int get_strlen(char* str); char* get_strcat(char* str1, char* str2); int main(void) { char str1[20] = "hello"; char str2[30]; char str3[10] = "world"; printf("%s\n", get_strcpy(str2, str1)); printf("%d\n", get_strlen(str2)); printf("%s\n", get_strcat(str2, str3)); return 0; } char* get_strcpy(char* str1, char* str2) { int i; for (i = 0; str2[i] != '\0'; i++) { str1[i] = str2[i]; } str1[i] = '\0'; return str1; } int get_strlen(char* str) { int i = 0; while (str[i] != '\0') { i++; } return i; } char* get_strcat(char* str1, char* str2) { int n = get_strlen(str1); for (int i = 0; str2[i] != '\0'; i++) { str1[n++] = str2[i]; } str1[n] = '\0'; return str1; } | cs |
13) 문자열 저장시 아래 2문장 모두 가능합니다. 2가지방법의 차이를 설명하라.
char str[20] = "apple";
char *p = "pineapple";
첫 번째 코드는 str배열에 순서대로 문자(문자 끝에는 '\n')가 저장. str은 배열의 첫 번째 요소의 주소일 뿐임.
두 번째 코드는 문자열 "pineapple"은 메모리 어딘가에 배열형태로 저장되는 것뿐이고 char형 포인터 p가 문자열 첫 번째 요소인 'p'의 주소를 가리키는 것이다.
따라서 키보드로부터 입력을 한 값으로부터 문자열을 저장할 때는 주소값이 변하지않는(포인터 상수) str만 가능하고
포인터 변수p가 가리키는 문자열을 바꿀 때는 코드에서 p = "hello";처럼 코드에서 작성해야 됨.(가리키는 대상의 주소를 변경)
scanf("%s", p);로 하면 에러뜸. => 문자열을 p에 저장하겠다는 뜻이 됨. 말이 안됨.
