다음과 같이 문자열을 선언했다면 무엇이 잘못되었는가?
int main(void)
{
char name[] = {'F', 'e', 's', 's'};
...
}
답안
문자열이 되기위해서는 문자열의 끝을 의미하는 널('\0')문자가 들어가야 한다.
위 코드는 '문자열'이 아닌 '문자'배열이다.
만약 문자열로 만들고자 한다면
char name[] = {'F', 'e', 's', 's', '\0'};
위 방식으로 해야 할 것이다.
다음 프로그램은 무엇을 출력하는가?
#include <stdio.h>
int main(void)
{
char note[] = "See you at the snack bar.";
char *ptr;
ptr = note;
puts(ptr);
puts(++ptr);
note[7] = '\0';
puts(note);
puts(++ptr);
return 0;
}
결과
See you at the snack bar.
ee you at the snack bar.
See you
e you
다음 프로그램은 무엇을 출력하는가?
#include <stdio.h>
#include <string.h>
int main(void)
{
char food[] = "Yummy";
char *ptr;
ptr = food + strlen(food);
while(--ptr >= food)
puts(ptr);
return 0;
}
결과
y
my
mmy
ummy
Yummy
다음 프로그램은 무엇을 출력하는가?
#include <stdio.h>
#include <string.h>
int main(void)
{
char goldwyn[40] = "art of it all ";
char samuel[40] = "I read p";
const char * quote = "the way through.";
strcat(goldwyn, quote);
strcat(samuel, goldwyn);
puts(samuel);
return 0;
}
결과
I read part of it all the way through.
다음은 문자열, 루프, 포인터, 포인터 증가 연산을 복습한다. 먼저, 함수가 다음과 같은 정의되었다고 가정하자.
#include <stdio.h>
char *pr(char *str)
{
char *pc;
pc = str;
while(*pc)
putchar(*pc++);
do {
putchar(*--pc);
} while(pc - str);
return pc;
}
그리고 다음과 같은 함수 호출을 가정하자.
x = pr("Ho Ho Ho!");
a. 무엇이 출력되는가?
b. x는 어떤 데이터형이어야 하는가?
c. x는 어떤 값을 얻는가?
d. 표현식 *--pc는 무엇을 의미하는가? 그것은 --*pc와 어떻게 다른가?
e. *--pc를 *pc--로 대체하면 무엇이 출력될까?
f. 두 while 표현식은 무엇을 검사하는가?
g. pr()에 전달인자로 널 문자열을 전달하면 무슨 일이 일어나는가?
h. pr()을 보기와 같이 사용하려면, 호출 함수에서 무엇을 해야 하는가?
답안
a. Ho Ho Ho!!oH oH oH
b. char형 포인터
c. "Ho Ho Ho!" 문자열의 첫'H'문자의 주소값
d. *--pc는 pc의 주소를 감소시키고 그 값을 가리키는 연산식이며,
--*pc는 pc값을 감소시키는 연산식이다.
e. Ho Ho Ho!!oH oH o
f. while(*pc)는 pc의 값이 null이 아님을 체크한다.
while(pc - str)는 pc의 주소가 str의 주소와 같지 않은지 체크한다.
g. 널 문자열("\0")을 전달하면 2번째 while문의 조건을 만족할 수 없어 무한 반복문이 된다.
(segmentation fault (core dumped))
h. 호출함수에 함수 프로토타입을 선언해야 한다.
char * pr(char *);
다음과 같은 선언이 있다고 가정하자.
char sign = '$';
문제
a. sign은 메모리를 몇 바이트 사용하는가?
b. '$'은 메모리를 몇 바이트 사용하는가?
c. "$"은 메모리를 몇 바이트 사용하는가?
답안
a. 1바이트를 사옹한다.
b. 1바이트를 사용한다.
c. '$'문자(1바이트) + '\0'(널문자)문자(1바이트)를 사용하여
총 2바이트를 사용한다.
다음 프로그램은 무엇을 출력하는가?
#include <stdio.h>
#include <string.h>
#define M1 "How are ya, sweetie? "
char M2[40] = "Beat the clock.";
char *M3 = "chat";
int main(void)
{
char words[80];
printf(M1);
puts(M1);
puts(M2);
puts(M2 + 1);
strcpy(words, M2);
strcat(words, " Win a toy.");
puts(words);
words[4] = '\0';
puts(words);
while(*M3)
puts(M3++);
puts(--M3);
puts(--M3);
M3 = M1;
puts(M3);
return 0;
}
출력
How are ya, sweetie? How are ya, sweetie?
Beat the clock.
eat the clock.
Beat the clock. Win a toy.
Beat
chat
hat
at
t
t
at
How are ya, sweetie?
다음 프로그램은 무엇을 출력하는가?
#include <stdio.h>
int main(void)
{
char str1[] = "gawsie";
char str2[] = "bletonism";
char *ps;
int i = 0;
for(ps = str1; *ps != '\0'; ps++)
{
if(*ps == 'a' || *ps == 'e')
putchar(*ps);
else
(*ps)--;
putchar(*ps);
}
putchar('\n');
while(str2[i] != '\0')
{
printf("%c", i % 3 ? str[i] : '*');
++i;
}
return 0;
}
출력
faavrhee
*le*on*sm
이 장에서 정의된 s_gets() 함수는 변수 i를 제거할 수 있도록 배열 표기법 대신 포인터 표기법으로 작성될 수 있다. 직접 이렇게 작성하라.
기존 s_gets()
char *s_gets(char *st, int n)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while(st[i] != '\n' && st[i] != '\0')
i++;
if(st[i] == '\n')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
수정한 s_gets()
// i변수를 없애고, *st의 주소를 직접 증가시켜 다음 문자를 기리킬 수 있도록 수정.
char *s_gets(char *st, int n)
{
char *ret_val;
ret_val = fgets(st, n, stdin);
if(*st)
{
while(*st != '\n' && *st != '\0')
st++;
if(*st == '\n')
*st = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
strlen() 함수는 문자열을 가리키는 포인터를 전달인자로 취하여, 그 문자열의 길이를 리턴한다. 같은 기능을 하는 함수를 작성하라.
int str_len(char *ch)
{
int count = 0;
while(*ch)
count++;
return count;
}
이 장에서 정의된 s_gets() 함수는 개행을 찾는데 while 루프 대신 strchr()을 사용하여 작성될 수 있다. 직접 이렇게 작성해 보라.
기존 s_gets()
char *s_gets(char *st, int n)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while(st[i] != '\n' && st[i] != '\0')
i++;
if(st[i] == '\n')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
수정한 s_gets()
char *s_gets(char *st, int n)
{
char *ret_val;
char *chr;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
chr = strchr(st, '\n');
if(chr)
*chr = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
문자열 포인터를 전달인자로 취하여, 그 문자열에 있는 또는 그 포인터가 가리키는 곳 이후에 있는 첫 번째 스페이스 문자를 가리키는 포인터를 리턴하는 함수를 작성하라.
char *find_space(char *ch)
{
char *chr;
chr = strchr(ch, ' ');
if(!chr)
return NULL;
return chr;
}
type.h 계열의 함수들을 사용하여 대소문자에 상관없이 사용자의 응답을 바르게 인식하도록 리스트 11.21을 수정하라.
기존 리스트11.21
#include <stdio.h>
#include <string.h>
#define ANSWER "Grant"
#define SIZE 40
char * s_gets(char *st, int n);
int main(void)
{
char try[SIZE];
puts("Grant의 무덤에 누가 잠들어 있습니까?");
s_gets(try, SIZE);
while(strcmp(try, ANSWER) != 0)
{
puts("틀렸습니다. 다시 말해 보십시오.");
s_gets(try, SIZE);
}
puts("맞았습니다!");
return 0;
}
char *s_gets(char *st, int n)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while(st[i] != '\n' && st[i] != '\0')
i++;
if(st[i] == '\n')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
수정한 리스트11.21
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define ANSWER "Grant"
#define SIZE 40
char * s_gets(char *st, int n);
int compare(char *try, char *ans);
int main(void)
{
char try[SIZE];
puts("Grant의 무덤에 누가 잠들어 있습니까?");
s_gets(try, SIZE);
while(compare(try, ANSWER))
{
puts("틀렸습니다. 다시 말해 보십시오.");
s_gets(try, SIZE);
}
puts("맞았습니다!");
return 0;
}
char *s_gets(char *st, int n)
{
char *ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while(st[i] != '\n' && st[i] != '\0')
i++;
if(st[i] == '\n')
st[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
int compare(char *try, char *ans)
{
while(tolower(*try) == tolower(*ans))
{
if(*try == '\n' || *try == '\0')
return 0;
try++, ans++;
}
return 1;
}