11장 포인터

Download Report

Transcript 11장 포인터

쉽게 풀어쓴 C언어 Express
제12장 문자와 문자열
© 2012 생능출판사 All rights reserved
이번 장에서 학습할 내용
•
•
•
•
•
문자 표현
문자열 표현
문자열 입출력
문자 처리 함수
문자열 변환 함수
© 2012 생능출판사 All rights reserved
인간은 문자를
사용하여 정보를
표현하므로 문자열은
프로그램에서 중요한
위치를 차지하고 있다.
이번 장에서는
C에서의 문자열 처리
방법에 대하여 자세히
살펴볼 것이다.
문자 표현
 아스키코드(ASCII code): 표준적인 8비트 문자 코드
 0에서 127까지의 숫자를 이용하여 문자 표현
 유니코드(unicode): 표준적인 8/16/32비트 문자 코드
 전세계의 모든 문자를 일관되게 표현하고 다룰 수 있도록 설계
65
69
© 2012 생능출판사 All rights reserved
71
74
C에서 문자는
숫자로 표현
됩니다.
78
문자열 표현
 문자열(string): 문자들이 여러 개 모인 것
 "Hello" // length = 5
 "변수 score의 값은 %d입니다"
 문자열의 저장: 문자 배열 사용
 NULL 문자('\0'): 문자열의 끝을 나타냄
 NULL 문자열(""): length = 0
H
e
l
l
o \0
"Hello"
\0
""
© 2012 생능출판사 All rights reserved
A
\0
"A"
A
'A'
문자 변수와 문자 상수
#include <stdio.h>
int main(void)
{
char code1 = 'A';
char code2 = 65;
65
printf("code1=%c, code1=%d\n", code1, code1);
printf("code2=%c, code2=%d\n", code2, code2);
return 0;
}
© 2012 생능출판사 All rights reserved
code1=A, code1=65
code2=A, code2=65
아스키 코드 출력
#include <stdio.h>
int main(void)
{
unsigned char code;
for (code = 33; code < 127; code++)
printf("아스키 코드 %d은 %c입니다.\n", code, code);
return 0;
}
© 2012 생능출판사 All rights reserved
아스키
...
아스키
...
아스키
...
아스키
코드 33은 !입니다.
코드 65은 A입니다.
코드 97은 a입니다.
코드 126은 ~입니다.
문자열 예제
#include <stdio.h>
int main(void)
{
int i;
char str[4];
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0';
i = 0;
while (str[i] != '\0') {
printf("%c", str[i]);
i++;
}
return 0;
}
© 2012 생능출판사 All rights reserved
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";
© 2012 생능출판사 All rights reserved
문자열 예제
#include <stdio.h>
int main(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;
}
© 2012 생능출판사 All rights reserved
Seoul is the capital of Korea.
문자열 예제
#include <stdio.h>
int main(void) {
char src[] = "The worst things to eat before you sleep";
char dst[100];
int i;
printf("원본 문자열 = %s\n", src);
for (i = 0; src[i]; i++)
// src[i] != '\0'
dst[i] = src[i];
dst[i] = '\0';
printf("복사된 문자열 = %s\n", dst);
return 0;
}
원본 문자열 = The worst things to eat before you sleep
복사된 문자열 = The worst things to eat before you sleep
© 2012 생능출판사 All rights reserved
문자열 길이
#include <stdio.h>
int main(void)
{
char str[30] = "Hello";
int i = 0;
while (str[i]) i++;
printf("문자열\"%s\"의 길이는 %d입니다.\n", str, i);
return 0;
}
문자열 "Hello"의 길이는 5입니다.
0
1
2
3
4
5
H
e
l
l
o
\0
© 2012 생능출판사 All rights reserved
문자열 저장
1. 각 문자 배열 원소에 일일이 대입
 str[0] = 'W';
 str[1] = 'o';
 str[2] = 'r';
 str[3] = 'l';
 str[4] = 'd';
 str[5] = '\0';
2. strcpy 함수를 사용하여 문자 배열에 복사
 strcpy(str, "World"); // 추후 학습
© 2012 생능출판사 All rights reserved
문자열 상수

문자열 상수("…"): 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
© 2012 생능출판사 All rights reserved
p 100
100
a
0
1
2
3
4
5
H
e
l
l
o
\0
0
1
2
3
4
5
H
e
l
l
o
\0
문자 입출력 함수
함수

기능
int getchar(void)
하나의 문자를 읽어서 반환, 입력 실패의 경우 EOF 반환
putchar(int c)
변수 c에 저장된 문자 출력
scanf("%c", &c)
하나의 문자를 읽어서 변수 c에 저장
printf("%c", c);
변수 c에 저장된 문자 출력
#define EOF (-1)
 End Of File
© 2012 생능출판사 All rights reserved
// <stdio.h>
getchar(), putchar()
#include <stdio.h>
int main(void)
{
int ch;
// 정수형에 주의
while((ch = getchar()) != EOF)
putchar(ch);
return 0;
}
© 2012 생능출판사 All rights reserved
AB
AB
C
C
^Z
입력
출력
버퍼링(buffering)
 엔터키('\n')를 쳐야만 입력을 받는 이유
라인 단위로 버퍼에 저장
엔터키가 입력되면 프로그램으로 전달
#include <stdio.h>
int main(void)
{
int ch;
}
키보드
© 2012 생능출판사 All rights reserved
버퍼(buffer)
ch = getchar();
...
...
프로그램
문자열 입출력 함수
함수
기능
scanf("%s", s)
문자열을 읽어서 s에 저장 (띄어쓰기 단위로 입력)
printf("%s", s)
문자열 s 출력
char *gets(char *s)
한 줄을 읽어서 s에 저장, s를 반환
puts(const char *s)
문자열 s 출력
© 2012 생능출판사 All rights reserved
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); // 입력: ab cd\n  s: ab cd\0
puts(s); // s: ab cd\0  출력: ab cd\n
 char s[100];
while (gets(s)) // gets(s) != NULL
puts(s);
© 2012 생능출판사 All rights reserved
문자열 입출력
#include <stdio.h>
int main(void) {
char name[100], address[100];
printf("이름을 입력하시오: "); gets(name);
printf(“주소를 입력하시오: "); gets(address);
puts(name); puts(address);
return 0;
}
© 2012 생능출판사 All rights reserved
이름을 입력하시오: 홍길동
주소를 입력하시오: 서울시 종로구 100번지
홍길동
서울시 종로구 100번지
문자 처리 함수
 #include <ctype.h>
함수
기능 (int 형으로 참/거짓 반환)
isalpha(c)
c가 영문자인가? (a~z, A~Z)
isupper(c)
c가 대문자인가? (A~Z)
islower(c)
c가 소문자인가? (a~z)
isdigit(c)
c가 숫자인가? (0~9)
isalnum(c)
c가 영문자나 숫자인가? (a~z, A~Z, 0~9)
isxdigit(c)
c가 16진수 숫자인가? (0~9, A~F, a~f)
isspace(c)
c가 공백 문자인가? (' ', \n, \r, \t, \v, \f)
ispunct(c)
c가 구두점 문자인가?
isprint(c)
c가 출력 가능 문자인가?
isgraph(c)
c가 그래프 문자인가?
iscntrl(c)
c가 제어 문자인가?
함수
기능 (int 형으로 문자 반환)
toupper(c)
c의 대문자 반환 (c가 소문자가 아니면 c 반환)
tolower(c)
c의 소문자 반환 (c가 대문자가 아니면 c 반환)
© 2012 생능출판사 All rights reserved
 ASCII 문자 분류
 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>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(toupper(c));
}
return 0;
© 2012 생능출판사 All rights reserved
abc123
ABC123
^Z
문자 검사
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int c = '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;
if (isupper(c)) …
© 2012 생능출판사 All rights reserved
isdigit(A) = 0
isalpha(A) = 1
islower(A) = 0
ispunct(A) = 0
isxdigit(A) = 128
isprint(A) = 1
문자열 처리 함수
 #include <string.h>
(s, t: char *;
cs, ct: const char*;
c: int(char),
함수
n: int)
기능
size_t strlen(cs)
cs의 길이 반환
char *strcpy(s, ct)
ct를 s에 복사, s 반환
char *strncpy(s, ct, n) ct를 s에 복사, 최대 n 문자만 복사, s 반환
char *strcat(s, ct)
ct를 s에 끝에 접속, s 반환
char *strncat(s, ct, n) ct를 s에 끝에 접속, 최대 n 문자만 접속, s 반환
int strcmp(cs, ct)
cs와 ct의 비교 결과 반환
int strncmp(cs, ct, n)
cs와 ct의 비교 결과 반환, 최대 n 문자만 비교
char *strchr(cs, c)
cs에서 c가 처음 나타난 위치 반환, 없으면 NULL 반환
char *strrchr(cs, c)
cs에서 c가 마지막으로 나타난 위치 반환, 없으면 NULL 반환
char *strstr(cs, ct)
cs에서 ct가 처음 나타난 위치 반환, 없으면 NULL 반환
© 2012 생능출판사 All rights reserved
strlen(), strcpy(), strcat()
size_t strlen(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;
}
© 2012 생능출판사 All rights reserved
 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)
{
char string[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!
© 2012 생능출판사 All rights reserved
문자열 비교: strcmp()
int strcmp(const char *s1, const char *s2);
반환 값
관계
-
s1 < s2
0
s1 = s2
+
s1 > s2
s
t
 숫자 < 대문자 < 소문자 < 한글
 if (strcmp(s1, s2)) // s1 ≠ s2 ?
 if (strcmp(s1, s2) != 0)
 if (!strcmp(s1, s2)) // s1 = s2 ?
 if (strcmp(s1, s2) == 0)
r
c
m
p
\0
=
=
=
=
>
s1
s
t
r
c
p
s2
© 2012 생능출판사 All rights reserved
m이 p보다 아스키 코드
값이 작으므로 음수 반환
y
\0
문자열 비교
#include <stdio.h>
#include <string.h>
int main( 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);
else if (result > 0)
printf("%s가 %s보다 뒤에 있습니다.\n", s1, s2);
else
printf("%s와 %s가 같습니다.\n", s1, s2);
첫번째 단어를 입력하시오: Hello
return 0;
}
© 2012 생능출판사 All rights reserved
두번째 단어를 입력하시오: World
Hello가 World보다 앞에 있습니다.
문자 검색
#include <stdio.h>
#include <string.h>
int main(void) {
char s[ ] = "language";
char c = 'g';
char *p;
int loc;
첫번째 g가 3에서 발견되었음
p = strchr(s, c);
loc = (int)(p - s);
if (p)
printf( "첫번째 %c가 %d에서 발견되었음\n", c, loc);
else
printf( "%c가 발견되지 않았음\n", c);
}
return 0;
© 2012 생능출판사 All rights reserved
문자열 검색
#include <stdio.h>
#include <string.h>
int main(void) {
char s[ ] = "A joy that's shared is a joy made double";
char sub[ ] = "joy";
char *p;
int loc;
p = strstr(s, sub);
loc = (int)(p - s);
if (p)
printf( "첫번째 %s가 %d에서 발견되었음\n", sub, loc);
else
printf( "%s가 발견되지 않았음\n", sub);
첫번째 joy가 2에서 발견되었음
}
return 0;
© 2012 생능출판사 All rights reserved
문자열 처리 (보충)
#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));
// 12
strcpy(s, "AB"), puts(strcat(s, "123"));
strcpy(s, "AB"), puts(strncat(s, "123", 2));
// AB123
// AB12
printf("%d\n", strcmp("가", "a"));
// +
printf("%d\n", strcmp("a", "A"));
// +
printf("%d\n", strcmp("A", "0"));
// +
printf("%d\n", strcmp("ab", "ab")); // 0
printf("%d\n", strcmp("ab", "abc")); // if (!strncmp("abc", "abC", 2)) printf("equal\n");
if ((p = strchr("abab", 'b'))) puts(p); // bab
if ((p = strrchr("abab", 'a'))) puts(p); // ab
if ((p = strstr("AABC", "AB"))) puts(p); // ABC
}
© 2012 생능출판사 All rights reserved
// equal
토큰 분리: strtok()
char *strtok(char *s, const char *delimiters);
 delimiters에 속한 분리자로 구분되는 s의 토큰 반환
 토큰이 없으면 NULL 포인터 반환
 계속 분리하는 경우, s에 NULL 포인터 사용
 분리자가 공백 문자나 탭 문자인 경우
t1
t2
t3
t4
=
=
=
=
strtok(s, " \t");
strtok(NULL, " \t");
strtok(NULL, " \t");
strtok(NULL, " \t");
© 2012 생능출판사 All rights reserved
//
//
//
//
첫
두
세
네
번째
번째
번째
번째
토큰
토큰
토큰
토큰
토큰 분리
#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);
}
return 0;
}
© 2012 생능출판사 All rights reserved
토큰:
토큰:
토큰:
토큰:
토큰:
토큰:
토큰:
토큰:
Man
is
immortal
because
he
has
a
soul
문자열 ↔ 수치 변환
 문자열과 수치
3
6
.
5
\0
src[0] src[1] src[2] src[3] src[4]
36.5
v
 #include <stdio.h>
함수
기능
sscanf(s, …)
scanf와 유사; 단, 문자열 s에서 입력 (문자열  수치)
sprintf(s, …)
printf와 유사; 단, 문자열 s에 출력 (수치  문자열)
© 2012 생능출판사 All rights reserved
문자열 ↔ 수치 변환
#include <stdio.h>
int main( void )
{
char s1[ ] = "100 200 300";
char s2[30];
int value;
sscanf(s1, "%d", &value);
printf("%d\n", value);
sprintf(s2, "%d", value);
printf("%s\n", s2);
return 0;
}
© 2012 생능출판사 All rights reserved
100
100
문자열 ↔ 수치 변환
#include <stdio.h>
void process(const char *filename) {
printf("%s\n", filename);
// do something
}
int main(void) {
char filename[100];
int i;
for (i = 0; i < 6; i++)
sprintf(filename, "image%d.jpg", i);
process(filename);
}
return 0;
}
© 2012 생능출판사 All rights reserved
image0.jpg
image1.jpg
image2.jpg
image3.jpg
image4.jpg
image5.jpg
문자열  수치 변환 함수
 #include <stdlib.h>
함수
기능
int atoi(const char *str);
str을 int형으로 변환
long atol(const char *str);
str을 long형으로 변환
double atof(const char *str);
str을 double형으로 변환
 sscanf보다 빠름
© 2012 생능출판사 All rights reserved
문자열  수치 변환
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s1[ ] = "100", s2[ ] = "12.93";
int i; double d, result;
i = atoi(s1);
d = atof(s2);
result = i + d;
printf("연산 결과는 %g입니다.\n", result);
return 0;
}
© 2012 생능출판사 All rights reserved
연산 결과는 112.93입니다.
문자열 배열
 2차원 문자 배열
 문자 포인터 배열
char menu[3][6] = {
"quit",
"open",
"close"
};
char *menu[3] = {
"quit",
"open",
"close"
};
q
u
i
t
\0
\0 \0
o
p
e
n
\0
e
c
l
o
s
e
menu q
u
i
t
\0 \0
o
p
e
n
c
l
o
s
menu
\0
// 메뉴 출력
for (i = 0; i < 3; i++)
printf("%d: %s\n", i, menu[i]);
© 2012 생능출판사 All rights reserved
\0
문자열 배열
#include <stdio.h>
int main(void) {
int i;
char fruits[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]);
return 0;
}
© 2012 생능출판사 All rights reserved
과일 이름을 입력하시오: 사과
과일 이름을 입력하시오: 배
과일 이름을 입력하시오: 포도
0번째 과일: 사과
1번째 과일: 배
2번째 과일: 포도
영한 사전
#include <stdio.h>
#include <string.h>
#define ENTRIES 5
int main(void) {
int i;
char dic[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;
© 2012 생능출판사 All rights reserved
단어를 입력하시오: book
book: 책