본문 바로가기

C언어

24. 열거형 1) 열거형의 정의와 그 의미 다음 그림에서는 열거형을 정의 하는 방법을 보여주고 있다. 열거형 정의는 자료형의 정의와 상수의 선언이라는 두 가지 측면을 지닌다고 말할 수 있다. #include enum color {RED=1, GREEN=3, BLUE=5}; int main(void){ enum color c1=RED; enum color c2=GREEN; enum color c3=BLUE; printf("열거형 변수 출력 : %d, %d, %d \n", c1, c2, c3); printf("상수 출력 : %d, %d, %d \n", RED, GREEN, BLUE); return 0; } - 실행 결과 열거형 변수 출력 : 1, 3, 5 상수 출력 : 1, 3, 5 Press any key to con.. 더보기
23. 공용체 구조체와 비슷하지만 공용체만의 특징을 지닌다. union data{ int d1; double d2; char d3; }; 공용체는 멤버 중 가장 메모리를 많이 요구하는 멤버(위 경우는 d2가 double형 이므로 가장 많이 요구한다.)에 초점을 둬서 메모리를 할당한다. 더보기
22-5. 새로운 자료형의 완성 int형 변수를 선언할 때는 " int i " 라고 선언 한다. person이라는 이름의 구조체를 정의하고 나서, person 구조체 변수를 선언할 때는 " struct person p " 라고 선언 한다. 만약 person도 int와 똑같은 하나의 자료형이라면 " person p " 라고 변수를 선언할 수 있어야 하지만 반드시 struct라는 키워드를 넣어 줘야만 한다. 1) typedef란 키워드는 무엇인가 ? 키워드 typedef는 이미 존재하는 자료형에 새로운 이름을 붙이기 위한 용도로 사용된다. 즉, 다음의 두 문장은 동일하다. int val; INT val; 2) typedef와 구조체 변수의 선언 기본 자료형 변수 선언처럼 변수 선언 시 struct 키워드를 사용하지 않는 것 #include.. 더보기
22-4. 구조체를 포함하는 구조체 1) 구조체가 구조체를 포함한다는 의미는 ? 구조체란 하나 이상의 변수를 그룹 지어서 새로운 자료형을 정의하는 것이다. 구조체를 포함하는 구조체를 중첩된 구조체라 한다. #include struct point{ int x; int y; }; struct circle{ struct point p; // point 구조체의 변수 double radius; }; int main(void){ struct circle c1 = {10, 10, 1.5}; struct circle c2 = {{30, 30}, 2.4}; printf("[circle1] \n"); printf("x : %d, y : %d \n", c1.p.x, c1.p.y); printf("radius : %f \n", c1.radius); print.. 더보기
22-3. 구조체 변수의 전달과 리턴 1) 함수의 인자로 전달되는 구조체 변수 일반 변수를 전달하는 방법과 마찬가지로 값에 의한 전달(Call-By-Value)과 레퍼런스에 의한 전달(Call-By-Reference)로 나뉜다. #include struct simple{ int data1; int data2; }; void show(struct simple ts);// Call-By-Value void swap(struct simple *ps);// Call-By-Reference int main(void){ struct simple s = {1, 2}; show(s);// s의 멤버 출력 swap(&s);// s의 멤버 data1, data2의 값 변경 show(s);// s의 변경된 멤버 출력 return 0; } void show(st.. 더보기
22-2. 구조체와 배열 그리고 포인터 1) 구조체와 배열 ⓐ 구조체 배열의 선언 및 접근 struct person{ char name[20]; char phone[20]; int age; }; int main(void){ struct person pArray[10]; ... return 0; } ⓑ 구조체 배열의 초기화 struct person{ char name[20]; char phone[20]; }; int main(void){ struct person pArray[3]={ {"Lee", "333"}, {"Kim", "555"}, {"SES", "777"} }; ... return 0; } 2) 구조체와 포인터 첫째, 구조체 포인터를 선언하여 구조체 변수를 가리키는 경우 둘째, 구조체의 멤버로 포인터 변수가 선언되는 경우 ⓐ 구조체 변.. 더보기
22-1. 구조체란 무엇인가? 1. 구조체의 정의 구조체란 하나 이상의 변수를 구릅 지어서 새로운 자료형을 정의 하는 것. struct point // point라는 이름의 구조체 선언 { // 구조체 정의 int x; // 구조체 멤버 int x int y; // 구조체 멤버 int y } 2. 구조체 변수의 선언 구조체 변수를 선언하는 방법은 크게 두 가지로 나뉘어 진다. (이때 구조체 변수는 구조체 멤버와 다른 의미로 햇갈리지 않도록 주의) ⓐ 구조체 정의와 구조체 변수의 동시에 하기 struct point { int x; int y; }p1, p2, p3; ⓑ 구조체의 정의와 구조체 변수의 선언의 분리 struct point { int x; int y; }; int main(){ struct point p1, p2, p3; ... 더보기
21. 문자열 조작 함수 - atoi과 대소변경 함수 1) 문자열을 숫자로 변환하는 함수들 헤더파일 stdlib.h에 선언되어 있다. #include int atoi(char *ptr); // 문자열을 int형 데이터로 변환 int atol(char *ptr); // 문자열을 long형 데이터로 변환 int atof(char *str); // 문자열을 double형 데이터로 변환 #include #include int main(){ char *str1 = "123"; char *str2 = "321"; printf("str1 : %s, str2 : %s\n", str1, str2); printf("123 + 321 : %d\n", atoi(str1) + atoi(str2)); return 0; } - 실행결과 str1 : 123, str2 : 321 123.. 더보기
21. 문자열 조작 함수 - strcmp와 strncmp 함수 4) 문자열을 비교하는 strcmp 그리고 strncmp 함수 문자열을 비교 하는 함수는 문자열의 길이를 비교하는 것이 아니라, 문자열의 내용자체를 비교하는 것이다. strcmp와 strncmp함수를 보기 전에 다음 예제를 살펴보자 #include #include char *str1 = "Hello!"; // 문자열 길이 7 int main(){ char str2[7]; strcpy(str2, str1); // 문자열 복사 printf("str1 : %s \n", str1); printf("str2 : %s \n", str2); if(str1 == str2) printf("str1과 str2는 같습니다.\n"); return 0; } 실행결과 str1 : Hello! str2 : Hello! Press .. 더보기
21. 문자열 조작 함수 - strcat과 strncat 함수 3) 문자열을 추가하는 strcat과 strncat 함수 ① strcat 함수 #include char *strcat(char *dest, const char *src); str로 전달된 문자열을 dest로 전달된 문자열 뒤에 추가하는 기능을 가진 함수이다. #include #include int main(){ char str1[30] = "Your favorite language is "; // null문자 포함 27문자 char str2[10]; fputs("What is your favorite computer language ? : ", stdout); fgets(str2, sizeof(str2), stdin); strcat(str1, str2); printf("생성된 문자열 : %s\n", st.. 더보기
21. 문자열 조작 함수 - strcpy와 strncpy 함수 2) 문자열을 복사하는 strcpy와 strncpy 함수 ① strcpy 함수 #include char *strcpy(char *dest, const char* src); 이 함수는 dest로 전달된 배열에 src로 전달된 문자열을 복사한다. #include #include int main(){ char str1[20] = "Samuel P. Harbison"; char str2[20]; printf("Original String : %s\n", str1); strcpy(str2, str1); // str에 저장된 문자열을 str2에 복사 printf("New String : %s\n", str2); return 0; } 실행결과 Original String : Samuel P. Harbison New .. 더보기
21. 문자열 조작 함수 - strlen 1) 문자열 길이 반환하는 strlen함수 #include size_t setlen(const char *s) NULL 문자는 문자열 길이에 포함되지 않는다. #include #include int main(){ char str[100]; while(1){ fgets(str, sizeof(str), stdin); printf("문자열의 길이 : %d\n", strlen(str)); } return 0; } 실행결과 123456 문자열의 길이 : 7 C program 문자열의 길이 : 10 한글 문자열의 길이 : 5 123456를 입력했는데 왜 7일까 ? Enter 키까지 포함됬기 때문이다. 그러므로 "123456"이 아닌 "123456\n"의 길이를 계산한 것이다. 영문자는 1byte, 한글은 2byte.. 더보기
20. 표준 입 · 출력과 버퍼(Buffer) 1) 표준 입 · 출력 기반의 버퍼(Buffer) 지금까지 사용했던 scanf, printf, putchar, getchar 함수들은 모드 표준 입출력 함수라 한다. 이러한 표준 입 · 출력 함수를 사용하는 경우에는 버퍼라는 것을 제공받게 된다는 특징이 있다. 여기서 말하는 버퍼는 '여분의 임시 메모리 공간' 이라고 생각하면 된다. 키보드를 통해서 입력하는 데이터는 실행중인 프로그램으로 바로 읽혀지는 것이 아니라, 일단은 입력 버퍼라는 곳에 저장이 된다는 것을 알 수 있다. 그리고 나서 입력 버퍼에 존재하는 데이터가 프로그램으로 이동하는 것이다. 이렇듯 프로그램상에서 printf와 같은 함수 호출을 통해서 모니터에 데이터를 출력하려는 경우에도 바로 출력이 이뤄지는 것이 아니라, 일단은 출력 버퍼라는 곳에.. 더보기
19. 문자열 단위 입 · 출력 함수 1) 문자열 출력 함수 #include int puts(const char* s); int fputs(const char* s, FILE* stream); puts 함수는 문자열을 표준 출력 스트림(stdout)으로 출력하기 위해 사용하는 함수이다. 인자로 전달되는 포인터는 문자열을 가리키고 있어야 한다. fputs 함수는 문자열을 출력할 스트림을 선택할 수 있다는 것을 제외하면, puts 함수와 동일한 기능을 지니는 함수이다. 단 한가지 차이점을 더 지닌다. puts 함수는 문자열을 출력한 다음에 자동으로 줄을 바꿔 주지만, fputs 함수는 자동으로 줄을 바꿔주지 않는다. 다음 예제의 출력 결과를 통해서 차이점을 확인해 보자 #include int main(){ fputs("fputs 함수에 의한 출.. 더보기
18. 문자 입 · 출력 함수 1) 문자 출력 함수 #include int putchar(int c); int fputc(int c, FILE* stream); putchar 함수는 함수 호출 시 인자로 전달된 문자를 '표준 출력 스트림(stdout)'으로 출력해 주는 역할을 하는 함수이다. 따라서 모니터에다가 하나의 문자를 출력해 주는 함수라고 할 수 있다. fputc 함수도 putchar 함수와 같은 기능을 하는 함수인데, 다만 차이점이 있다면 "문자를 출력할 스트림을 지정할 수 있다는 특징"이 있다. 즉 putchar 함수는 모니터로만 문자를 출력하지만, fputc 함수는 모니터뿐만 아니라, 파일에도 문자를 출력할 수 있는 함수이다.(파일에 문자를 출력 한다는 의미는 파일에 문자를 저장한다는 의미이다.) 2) 문자 입력 함수 #.. 더보기
17. 스트림과 데이터의 전송 1) 입 · 출력에 대한 이해 실행중인 프로그램이 데이터를 받아들이는 것을 입력이라 함. scanf와 같은 함수를 입력함수라 한다. 실행중이 프로그램에서 데이터를 보내는 것을 출력이라함. printf와 같은 함수를 출력함수라 한다. 2) 입 · 출력이 가능한 이유는 어디에 - 스트림이 있어 가능한 입 · 출력 구현한 프로그램과 모니터는 연결되어 있는 개체가 아닌, 완전히 동떨어져 있는 두 개의 서로 다른 개체이다. 따라서 프로그램성에서 모니터로 데이터를 전송해 주기 위해서는 이 둘을 연결해 주는 '다리'가 필요하다. 이러한 다리 역할을 하는 것을 스트림이라 한다. 입력과 출력 스트림 이러한 스트림은 운영체제에 의해서 만들어지는 가상적인 다리이다. 3) 스트림의 생성과 소멸 파일 입 · 출력과 콘솔(키보드.. 더보기
16. 함수포인터 메모리상에 존재하는 함수의 위치를 가리키는 포인터 함수 이름의 포인터 타입을 결정짓는 요소는 리턴형과 전달인자이다. 다음은 예를 들어보겠다. int (*fptr1)(int); void (*fptr2)(int, int); 다음은 함수 포인터의 이해를 돕는 예제이다. #include void Add(int a, int b); void SPrint(char *str); int main(void){ char *string = "Function Pointer"; int a=10, b=20; void (*fptr1)(int, int) = Add; void (*fptr2)(char*) = SPrint; /*함수 포인터에 의한 호출*/ fptr1(a, b); fptr2(string); return 0; } void A.. 더보기
15. 포인터와 const 키워드 1 ) 포인터가 가리키는 변수의 상수화 int main(void) { int a = 10; const int *p = &a; *p = 30; // Error! a = 30; // OK!} 포인터가 p가 가리키는 변수를 상수화하겠다는 뜻이다. 즉, 포인터가 p가 가리키는 변수의 값을 못 바꾸게 하겠다는 뜻이다. ※ a 자체가 상수화되는 것이 아니다. 포인터 p를 통해서 변수 a의 값을 변경하는 것만 막는것 이다. 따라서 5번줄에 있는 변수 a의 조작은 전혀 문제되지 않는다. 2 ) 포인터 상수화 int main(void) { int a = 10; int b = 20; int* const p = &a; p = &b; // Error! *p = 30; //OK!} 여기서 1번 예제와 다른 const위치를 확인.. 더보기
14. scanf 함수 호출 시 &를 붙이는 이유 int main(void) { int val; scanf("%d", &val); return 0; } scanf 함수 내에서 main 함수에서 선언된 지역 변수에 접근하기 위해서는 해당 변수의 주소를 알아야만 한다. 그래서 scanf 함수를 호출하면서 값이 채워질 지역 변수 val의 주소 값을 인자로 전달하고 있는 것 이다. 결국 call-by-regerence에 해당된다. 다음 예제는 &를 붙이지 않는다. int main(void) { char str[100]; printf("문자열 입력 : "); scanf("%s", str); .. ... } 배열 이름 str은 배열의 주소를 나타낸다. 그러므로 &연산을 할 필요가 없다. 더보기
13. Call-By-Value와 Call-By-Reference 1 ) Call by value - 값에 의한 호출 - 두 변수가 지니고 있는 값을 서로 바꿔주는 swap이라는 함수 구현 #include void swap(int a, int b); int main(void){ int a = 10; int b = 20; printf("swap 함수 실행전 a : %d \n", a); printf("swap 함수 실행전 b : %d \n", b); swap(a, b); printf("swap 함수 실행후 a : %d \n", a); printf("swap 함수 실행후 b : %d \n", b); return 0; } void swap(int x, int y){ int temp = x; x = y; y = temp; printf("x : %d", x); printf("y .. 더보기
12-2. 문자열 상수에 대한 조금 더 깊은 이해 char *str = "ABCDEFG"; 대입 연산자를 왼쪽에 char형 포인터를 선언하고 있다. 즉, 대입 연산자의 오른쪽에 char형 데이터의 주소 값이 오기를 기대한다는 뜻이다. "문자열 상수는 메모리 공간에 저장이 되면, 그 순간에 문자열 상수의 주소 값이 반환된다." int main(void) { char *str1 = "ABCD"; char *str2 = "ABCD"; printf("%d, %d \n", str1, str2); return 0; } str1과 str2의 주소를 출력하고있다. - 출력결과 4337696, 4337696 출력결과를 보면 str1과 str2가 가리키는 문자열이 같음을 알 수 있다. 즉, "ABCD"라는 문자열 상수를 메모리 공간에 하나만 저장하고 두 개의 포인터가 이.. 더보기
12. 문자열 표현 방식의 이해 int main(void) { char str1[5] = "abcd"; // 문자열 변수 선언 char *str2 = "ABCD"; // 문자열 상수 선언 printf("%s \n", str1); printf("%s \n", str2); str1[0] = 'x'; // 문자열 변수 변경 str2[0] = 'x'; // 문자열 상수 변경, Error 발생! printf("%s \n", str1); printf("%s \n", str2); return 0; } 8, 9번째 줄에서 문자열의 첫 번째 문자를 변경하려 하고 있다. 8 : str1이 가리키는 문자열은 변수이므로 문제될 것이 없지만 9 : str2는 문자열 상수 이므로 변경 시 문제를 일으키게 된다. - 9번줄을 주석처리후 실행 결과 abcd ABC.. 더보기
11-2. 포인터를 배열의 이름처럼 사용할 수 있다. int main(void) { int arr[3] = {0, 1, 2}; int *ptr; ptr = arr; // 배열의 이름은 첫번째 요소의 주소 printf("%d, %d, %d \n", ptr[0], ptr[1], ptr[2]); return 0; } 7번째 줄에서는 ptr이라는 포인터를 마치 배열의 이름인 마냥 사용하고 있다. 전혀 문제될 것이 없다. 더보기
11. 포인터와 배열의 관계 "배열의 이름도 포인터다!" int main(void) { int a[5] = {0, 1, 2, 3, 4}; printf("a[0] = %d, a[1] = %d \n", a[0], a[1]); // 배열 요소 출력 printf("&a[0] = %d번지, a[1] = %d번지 \n", &a[0], &a[1]); // 배열 요소의 주소 출력 printf("배열이름 : %d \n", a); // 배열 이름 출력 return 0; } - 출력결과 a[0] = 0, a[1] = 1 &a[0] = 1245036번지, &a[1] = 1245040번지 배열이름 : 1245036 배열 a[0]과 a[1]의 주소는 1245036번지와 1245040번지이다. 이둘의 차이는 4이다. 선언한 배열은 int형이기 때문에 주소값이.. 더보기
10-2. 잘못된 포인터의 사용 int main(void) { int *pA; *pA = 10; return 0; } 2번 줄에서는 pA라는 포인터 변수를 선언만하고 초기화는 안 하고 있다. 따라서 pA가 지니는 값을 쓰레기 값이다. 이상태에서 3번줄에서 pA라는 포인터가 기리키는 메모리 공간에 10이라는 정수 값을 대입하고 있다. 그러므로 이 코드는 오류를 지니고 있다. pA가 가리키는 곳이 어딘지 모른다. 더보기
10. 포인터에 대한 이해 "포인터란 메모리의 주소 값을 저장하기 위한 변수이다." - 포인터 선언하기 int main(void) { int *a; // int형 변수의 주소 값을 지닐 수 있는 int형 포인터 char *b; // char형 변수의 주소 값을 지닐 수 있는 char형 포인터 double *c; // double형 변수의 주소 값을 지닐 수 있는 double형 포인터 포인터를 선언할 때에는 *연산자를 사용한다. - 포인터 변수가 자료형과 상관없이 4byte인 이유 플랫폼 (H/W + O/S)에 따라 가기 때문이다. 32bit CPU와 32bit 운영체제(xp) 일때는 포인터변수의 공간이 4byte가 된다. 64bit CPU와 64bit 운영체제(vista) 일때는 포인터변수의 공간이 8byte가 된다. 64bit .. 더보기
9. 전역변수 (Global Variable) 그 이름처럼 프로그램 어디에서나 접근이 가능한 변수를 말함. int val = 0; // 전역변수 val void fct(void); int main(){ val = 10; printf("val : %d ", val); fct(); printf("val : %d ", val); return 0; } void fct(void){ int val=20; // 지역변수 val val++; } 1 번째 줄에서 전역변수 val을 선언하고 10대입 후 main에서 10이 출력된다. 17번째 줄에서 지역변수 val을 선언하고 20대입 후 함수가 종료 되었기 때문에 main함수에서는 그대로 10이 출력이 된다. - 실행 결과 val : 10 val : 10 참고 : 문법적인 특징을 설명하기위해 위와 같은 예시를 들었지만.. 더보기
8. continue와 break의 차이점 더보기
7. scanf 사용시 주의사항 - 실수를 입력받을때 int main(){ float f; double d; printf("두 개의 실수 입력 : "); scanf("%f, %e", &f, &d); printf("입력에 대한 출력 : "); printf("%f %e \n", f, d); return 0; } 여기서 double형을 입력받기 위해서는 %e를 사용한다. 하지만 다음과 같이 입력하면 잘못된 출력결과를 얻게 된다. 두 개의 실수 입력 : 3.15 3.15 입력에 대한 출력 : 3.150000 -9.255960e+061 이를 해결하기 위해 printf("%f %le \n", f, d); %e를 %le로 변경하면 된다. 더보기
6-4. 필드 폭을 지정하여 출력 더보기