420 likes | 1.6k Views
제 12 장 문자와 문자열. 쉽게 풀어쓴 C 언어 Express. C Express. 이번 장에서 학습할 내용. 인간은 문자를 사용하여 정보를 표현하므로 문자열은 프로그램에서 중요한 위치를 차지하고 있다 . 이번 장에서는 C 에서의 문자열 처리 방법에 대하여 자세히 살펴볼 것이다. 문자 표현 문자열 표현 문자열 입출력 문자 처리 함수 문자열 변환 함수. 문자 표현. 아스키코드 (ASCII code ) : 표준적인 8 비트 문자 코드 0 에서 127 까지의 숫자를 이용하여 문자 표현
E N D
제12장 문자와 문자열 쉽게 풀어쓴C언어 Express C Express
이번 장에서 학습할 내용 인간은 문자를 사용하여 정보를 표현하므로 문자열은 프로그램에서 중요한 위치를 차지하고 있다. 이번 장에서는 C에서의 문자열 처리 방법에 대하여 자세히 살펴볼 것이다. • 문자 표현 • 문자열 표현 • 문자열 입출력 • 문자 처리 함수 • 문자열 변환 함수
문자 표현 • 아스키코드(ASCII code): 표준적인 8비트 문자 코드 • 0에서 127까지의 숫자를 이용하여 문자 표현 • 유니코드(unicode): 표준적인 8/16/32비트 문자 코드 • 전세계의 모든 문자를 일관되게 표현하고 다룰 수 있도록 설계 C에서 문자는 숫자로 표현 됩니다. 69 74 71 65 78
문자열 표현 • 문자열(string): 문자들이 여러 개 모인 것 • "Hello" // length = 5 • "변수 score의 값은 %d입니다" • 문자열의 저장: 문자 배열 사용 • NULL 문자('\0'): 문자열의 끝을 나타냄 • NULL 문자열(""): length = 0 A A H e l l o 'A' "" "A" \0 \0 \0 "Hello"
문자 변수와 문자 상수 #include<stdio.h> intmain(void) { char code1 = 'A'; char code2 = 65; printf("code1=%c, code1=%d\n", code1, code1); printf("code2=%c, code2=%d\n", code2, code2); return 0; } 65 code1=A, code1=65 code2=A, code2=65
아스키 코드 출력 #include<stdio.h> int main(void) { unsignedchar code; for (code = 33; code < 127; code++) printf("아스키코드 %d은 %c입니다.\n", code, code); return 0; } 아스키 코드 33은 !입니다. ... 아스키 코드 65은 A입니다. ... 아스키 코드 97은 a입니다. ... 아스키 코드 126은 ~입니다.
문자열 예제 #include<stdio.h> intmain(void) { inti; charstr[4]; str[0] = 'a'; str[1] = 'b'; str[2] = 'c'; str[3] = '\0'; i = 0; while (str[i] != '\0') { printf("%c", str[i]); i++; } return0; } abc
문자 배열의 초기화 • char str[4] = { 'a', 'b', 'c', '\0' }; • char str[4] = "abc"; • char str[4] = "abcdef"; // X • char str[6] = "abc"; • char str[4] = ""; • char str[ ] = "abc";
문자열 예제 #include<stdio.h> intmain(void) { char str1[6] = "Seoul"; char str2[3] = { 'i', 's'}; char str3[ ] = "the capital of Korea."; printf("%s %s %s\n", str1, str2, str3); return 0; } Seoul is the capital of Korea.
문자열 예제 #include<stdio.h> intmain(void) { charsrc[] = "The worst things to eat before you sleep"; chardst[100]; inti; printf("원본 문자열 = %s\n", src); for (i = 0; src[i]; i++) // src[i] != '\0' dst[i] = src[i]; dst[i] = '\0'; printf("복사된 문자열 = %s\n", dst); return0; } 원본 문자열 = The worst things to eat before you sleep 복사된 문자열 = The worst things to eat before you sleep
문자열 길이 #include<stdio.h> intmain(void) { charstr[30] = "Hello"; inti = 0; while (str[i]) i++; printf("문자열\"%s\"의 길이는 %d입니다.\n", str, i); return 0; } 문자열 "Hello"의 길이는 5입니다.
문자열 저장 • 각 문자 배열 원소에 일일이 대입 • str[0] = 'W'; • str[1] = 'o'; • str[2] = 'r'; • str[3] = 'l'; • str[4] = 'd'; • str[5] = '\0'; • strcpy함수를 사용하여 문자 배열에 복사 • strcpy(str, "World"); // 추후학습
문자열 상수 • 문자열 상수("…"): read-only 메모리 영역에 저장 • 수정 불가 • char *p = "Hello"; • p[0] = 'h'; (X) • p = "World"; (O) • sizeof p : 4(8) • length : 5 • char a[ ] = "Hello"; • a[0] = 'h'; (O) • a = "World"; (X) • sizeof a : 6 • length : 5 100 p 100 a
문자 입출력 함수 • #define EOF (-1) // <stdio.h> • End Of File
getchar(), putchar() #include<stdio.h> intmain(void) { intch;// 정수형에 주의 while((ch = getchar()) != EOF) putchar(ch); return0; } 입력 AB AB C C ^Z 출력
버퍼링(buffering) • 엔터키('\n')를 쳐야만 입력을 받는 이유 라인 단위로 버퍼에 저장 엔터키가입력되면 프로그램으로 전달 #include <stdio.h> int main(void) { intch; ch = getchar(); ... ... } 키보드 버퍼(buffer) 프로그램
gets(), puts() char *gets(char*str); puts(const char *str); • gets(): '\n'을 만날 때까지 한 줄을 입력하여 str에저장 • '\n'은 읽어들이지만 저장하지는 않음 • 입력이 성공하면 str반환 • 입력이 실패하거나 파일 끝을 만나면 NULL 포인터 반환 • puts(): str과 '\n'을 출력 • puts(s) printf("%s\n", s) • char s[100];gets(s); // 입력: abcd\n s: abcd\0puts(s); // s: abcd\0 출력: abcd\n • char s[100];while (gets(s)) // gets(s) != NULL puts(s);
문자열 입출력 #include<stdio.h> intmain(void) { charname[100], address[100]; printf("이름을 입력하시오: "); gets(name); printf(“주소를 입력하시오: "); gets(address); puts(name); puts(address); return0; } 이름을 입력하시오: 홍길동 주소를 입력하시오: 서울시 종로구 100번지 홍길동 서울시 종로구 100번지
문자 처리 함수 • ASCII 문자 분류 • #include <ctype.h> • control: 0~31, 127(DEL) • printing: 32~126 • blank: ' '(32) • punctuation: !, ", … • alphanumeric • alphabet(letter) • - uppercase: A~Z • - lowercase: a~z • number(digit): 0~9 • graph: printing – ' '(32) • punctuation: graph – alphanumeric • whitespace: ' ', \n, \r, \t, \v, \f
대문자 변환 #include<stdio.h> #include<ctype.h> intmain(void) { int c; while ((c = getchar()) != EOF) putchar(toupper(c)); return 0; } abc123 ABC123 ^Z
문자 검사 #include <stdio.h> #include <ctype.h> intmain(void) { intc = 'A'; printf("isdigit(%c) = %d\n", c, isdigit(c)); printf("isalpha(%c) = %d\n", c, isalpha(c)); printf("islower(%c) = %d\n", c, islower(c)); printf("ispunct(%c) = %d\n", c, ispunct(c)); printf("isxdigit(%c) = %d\n", c, isxdigit(c)); printf("isprint(%c) = %d\n", c, isprint(c)); return 0; } isdigit(A) = 0 isalpha(A) = 1 islower(A) = 0 ispunct(A) = 0 isxdigit(A) = 128 isprint(A) = 1 if (isupper(c)) …
문자열 처리 함수 • #include <string.h> • (s, t: char *; cs, ct: const char*; c: int(char), n: int)
strlen(), strcpy(), strcat() size_tstrlen(const char *s) {const char *p = s;while (*p) p++;return (size_t)(p - s);}char *strcpy(char *s, const char *t) {char *p = s;while ((*p++ = *t++)) ;return s;}char *strcat(char *s, const char *t) {char *p = s;while (*p) p++;while ((*p++ = *t++)) ;return s;} • strlen("Hello") : 5 • char s[100];strcpy(s, "Hello");// s : "Hello"puts(strcpy(s, "Hello"));// Hello • char s[100] = "Hello";strcat(s, " World");// s : "Hello World"puts(strcat(s, " World"));// Hello World
문자열 처리 #include<stdio.h> #include<string.h> int main(void) { charstring[100]; strcpy(string, "Hello world from "); strcat(string, "strcpy"); strcat(string, "and "); strcat(string, "strcat!"); printf("string = %s\n", string); return 0; } string = Hello world from strcpy and strcat!
문자열 비교: strcmp() intstrcmp(const char *s1, const char *s2); • 숫자 < 대문자 < 소문자 < 한글 • if (strcmp(s1, s2)) // s1 ≠ s2 ? if (strcmp(s1, s2) != 0) • if (!strcmp(s1, s2)) // s1 = s2 ? if (strcmp(s1, s2) == 0) s t r c m p s1 = = = = > m이 p보다 아스키 코드값이 작으므로 음수 반환 p y s t r c \0 \0 s2
문자열 비교 #include<stdio.h> #include<string.h> intmain( void) { char s1[80], s2[80]; int result; printf("첫번째단어를입력하시오: "); scanf("%s", s1); printf("두번째단어를입력하시오: "); scanf("%s", s2); result = strcmp(s1, s2); if (result < 0) printf("%s가 %s보다앞에있읍니다.\n", s1, s2); elseif (result > 0) printf("%s가 %s보다뒤에있습니다.\n", s1, s2); else printf("%s와%s가같습니다.\n", s1, s2); return 0; } 첫번째 단어를 입력하시오:Hello 두번째 단어를 입력하시오:World Hello가 World보다 앞에 있습니다.
문자 검색 #include<stdio.h> #include<string.h> intmain(void) { chars[ ] = "language"; charc = 'g'; char*p; intloc; p = strchr(s, c); loc = (int)(p - s); if(p) printf( "첫번째%c가 %d에서 발견되었음\n", c, loc); else printf( "%c가 발견되지 않았음\n", c); return0; } 첫번째g가 3에서 발견되었음
문자열검색 #include<stdio.h> #include<string.h> intmain(void) { chars[ ] = "A joy that's shared is a joy made double"; charsub[ ] = "joy"; char*p; intloc; p = strstr(s, sub); loc = (int)(p - s); if(p) printf( "첫번째%s가 %d에서 발견되었음\n", sub, loc); else printf( "%s가 발견되지 않았음\n", sub); return0; } 첫번째joy가 2에서 발견되었음
문자열 처리 (보충) #include <stdio.h>#include <string.h>void main() {char s[100], *p; puts(strcpy(s, "ab#")); // ab# puts(strncpy(s, "ABC", 2)); // AB# puts(strncpy(s, "12", 3)); // 12strcpy(s, "AB"), puts(strcat(s, "123")); // AB123strcpy(s, "AB"), puts(strncat(s, "123", 2)); // AB12printf("%d\n", strcmp("가", "a")); // +printf("%d\n", strcmp("a", "A")); // +printf("%d\n", strcmp("A", "0")); // +printf("%d\n", strcmp("ab", "ab")); // 0printf("%d\n", strcmp("ab", "abc")); // -if (!strncmp("abc", "abC", 2)) printf("equal\n"); // equalif ((p = strchr("abab", 'b'))) puts(p); // babif ((p = strrchr("abab", 'a'))) puts(p); // abif ((p = strstr("AABC", "AB"))) puts(p); // ABC}
토큰 분리: strtok() char *strtok(char *s, const char *delimiters); • delimiters에 속한 분리자로 구분되는 s의 토큰 반환 • 토큰이 없으면 NULL 포인터 반환 • 계속 분리하는 경우,s에 NULL 포인터 사용 • 분리자가 공백 문자나 탭 문자인 경우 t1 = strtok(s, " \t");// 첫 번째 토큰 t2 = strtok(NULL, " \t");// 두 번째 토큰 t3 = strtok(NULL, " \t");// 세 번째 토큰 t4 = strtok(NULL, " \t");// 네 번째 토큰
토큰 분리 #include<stdio.h> #include<string.h> int main(void) { char s[] = "Man is immortal, because he has a soul"; char *seps = " ,\t\n"; char *token; token = strtok(s, seps); while (token) { printf("토큰: %s\n", token); token = strtok(NULL, seps); } return0; } 토큰: Man 토큰: is 토큰: immortal 토큰: because 토큰: he 토큰: has 토큰: a 토큰: soul
문자열 ↔ 수치 변환 • 문자열과 수치 • #include <stdio.h> 3 6 . 5 36.5 v src[0]src[1] src[2]src[3]src[4] \0
문자열 ↔ 수치 변환 #include<stdio.h> int main( void ) { char s1[ ] = "100 200 300"; chars2[30]; int value; sscanf(s1, "%d", &value); printf("%d\n", value); sprintf(s2, "%d", value); printf("%s\n", s2); return 0; } 100 100
문자열 ↔ 수치 변환 #include<stdio.h> void process(const char *filename) { printf("%s\n", filename); // do something } intmain(void) { charfilename[100]; inti; for (i = 0; i < 6; i++) sprintf(filename, "image%d.jpg", i); process(filename); } return0; } image0.jpg image1.jpg image2.jpg image3.jpg image4.jpg image5.jpg
문자열 수치 변환 함수 • #include <stdlib.h> • sscanf보다 빠름
문자열 수치 변환 #include<stdio.h> #include<stdlib.h> int main(void) { char s1[ ] = "100", s2[ ] = "12.93"; inti; double d, result; i = atoi(s1); d = atof(s2); result = i + d; printf("연산 결과는 %g입니다.\n", result); return 0; } 연산 결과는 112.93입니다.
문자열 배열 • 문자 포인터 배열 • 2차원 문자 배열 charmenu[3][6] = { "quit", "open", "close" }; char *menu[3] = { "quit", "open", "close" }; menu menu // 메뉴 출력 for (i = 0; i < 3; i++) printf("%d: %s\n", i, menu[i]);
문자열 배열 #include<stdio.h> intmain(void) { inti; charfruits[3][20]; for (i = 0; i < 3; i++) { printf("과일 이름을 입력하시오: "); scanf("%s", fruits[i]); } for (i = 0; i < 3; i++) printf("%d번째 과일: %s\n", i, fruits[i]); return0; } 과일 이름을 입력하시오: 사과 과일 이름을 입력하시오: 배 과일 이름을 입력하시오: 포도 0번째 과일: 사과 1번째 과일: 배 2번째 과일: 포도
영한 사전 #include<stdio.h> #include<string.h> #define ENTRIES 5 int main(void) { inti; chardic[ENTRIES][2][30] = { { "book", "책" }, { "boy", "소년" }, { "computer", "컴퓨터" }, { "language", "언어" }, { "rain", "비" } }; char word[30]; printf("단어를입력하시오: "); scanf("%s", word); for (i = 0; i < ENTRIES; i++) if (!strcmp(dic[i][0], word)) { printf("%s: %s\n", word, dic[i][1]); return 0; } printf("사전에서발견되지않았습니다.\n"); return 1; } 단어를 입력하시오: book book: 책