본문 바로가기

Programming/C

[ProjectH4C] 코딩도장 Unit 41~45 Write-Up

문자열 다루기

C언어에서는 문자열을 다루는 여러가지 함수들을 제공한다. 이들은 모두 string.h 헤더파일에 선언되어 있다.

 

1. 문자열의 길이

 

문자열의 길이를 반환하는 함수로 strlen(str) 함수가 있다. 이 때 인자로 길이를 구하고자 하는 문자열이 저장된 배열 또는 포인터를 넘긴다. 반환 값은 정수 형태이다.

#include <stdio.h>
#include <string.h>    // strlen 함수가 선언된 헤더 파일

int main()
{
    char *s1 = "Hello";       // 포인터에 문자열 Hello의 주소 저장
    char s2[10] = "Hello";    // 크기가 10인 char형 배열을 선언하고 문자열 할당

    printf("%d\n", strlen(s1));    // 5: strlen 함수로 문자열의 길이를 구함
    printf("%d\n", strlen(s2));    // 5: strlen 함수로 문자열의 길이를 구함

    return 0;
}

이 때, 널 문자를 포함하지 않은 길이가 반환된다. 반환 되는 길이는 배열의 크기와는 전혀 상관없기 때문에 배열의 크기가 100이고 저장된 문자열이 5라면, strlen() 함수는 5를 반환한다.

 

2. 문자열 비교

 

strcmp(str1, str2) 함수는 인자로 넘긴 두 문자열 str1과 str2가 같은지 비교한다. 같으면 0, 다르면 1 또는 -1을 반환한다.

 

#include <stdio.h>
#include <string.h>    // strcmp 함수가 선언된 헤더 파일

int main()
{
    char s1[10] = "Hello";
    char *s2 = "Hello";

    int ret = strcmp(s1, s2);    // 두 문자열이 같은지 문자열 비교

    printf("%d\n", ret);         // 0: 두 문자열이 같으면 0

    return 0;
}

실행 결과

0

두 문자열이 다를 때, 첫 번째 인자(s1)를 기준으로, s2보다 크면 1, 작으면 -1을 반환한다. 문자의 크기 비교 기준은 ASCII 코드이다.

 

 

3. 문자열 복사

 

문자열을 다른 배열에 복사하는 함수로 strcpy(str1, str2)가 있다. 해당 함수는 str1의 문자열을 str2에 복사한다. 이 때, str1의 문자열은 그대로 남아있다. 이 때, 문자열 포인터끼리 복사하려고 시도하면 에러가 난다. 문자열 리터럴이 저장된 포인터는 읽기만 가능하고 쓰기는 불가능하기 때문이다.

 

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

int main()
{
    char s1[10] = "Hello";    // 크기가 10인 char형 배열을 선언하고 문자열 할당
    char s2[10];              // 크기가 10인 char형 배열을 선언

    strcpy(s2, s1);        // s1의 문자열을 s2로 복사
    
    printf("%s\n", s2);    // Hello

    return 0;
}

실행 결과

Hello

복사된 문자열을 저장할 배열의 크기는 널 문자까지 포함해서 모두 담을 수 있을 만큼 지정해주어야 한다. 

 

 

4. 문자열 붙이기

해당 문자열 뒤에 다른 문자열을 이어서 저장하고 싶다면 strcat(str1, str2) 함수를 사용하면 된다. 이 때 str1의 문자열 뒤에 str2 문자열이 붙여지는데, 널 문자를 포함해서 str1, str2의 문자열을 모두 저장할 수 있을만큼의 크기를 가지고 있어야 한다. 이 때에도 마찬가지로 문자열 리터럴이 저장된 포인터에는 붙일 수 없다.

 

#define _CRT_SECURE_NO_WARNINGS    // strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcat 함수가 선언된 헤더 파일

int main()
{
    char s1[10] = "world";
    char s2[20] = "Hello"; // s2 뒤에 붙일 것이므로 배열 크기를 크게 만듦

    strcat(s2, s1);        // s2 뒤에 s1를 붙임

    printf("%s\n", s2);    // Helloworld

    return 0;
}

 

 

 

※배열 형태의 문자열과 문자열 포인터

 

문자열 포인터를 복사하는 것은 불가능하지만, 배열 형태의 문자열을 문자열 포인터에 복사하는 것은 가능하다. 문자열 포인터 s2를 메모리에 할당 한 후에 배열로 선언한 문자열 s1을 문자열 포인터 s2에 저장하면 값이 정상적으로 출력되는 것을 확인할 수 있다.

 

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

int main()
{
    char s1[10] = "Hello";                   // 크기가 10인 char형 배열을 선언하고 문자열 할당
    char *s2 = malloc(sizeof(char) * 10);    // char 10개 크기만큼 동적 메모리 할당

    strcpy(s2, s1);        // s1의 문자열을 s2로 복사

    printf("%s\n", s2);    // Hello

    free(s2);    // 동적 메모리 해제

    return 0;
}

실행 결과

Hello

 

복사 뿐만 아니라 배열 형태의 포인터를 문자열 포인터에 붙이는 것도 가능하다.

 

#define _CRT_SECURE_NO_WARNINGS    // strcpy, strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy, strcat 함수가 선언된 헤더 파일
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

int main()
{
    char s1[10] = "world";                  // 크기가 10인 char형 배열을 선언하고 문자열 할당
    char *s2 = malloc(sizeof(char) * 20);    // char 20개 크기만큼 동적 메모리 할당

    strcpy(s2, "Hello");   // s2에 Hello 문자열 복사

    strcat(s2, s1);        // s2 뒤에 s1을 붙임

    printf("%s\n", s2);    // Helloworld

    free(s2);  // 동적 메모리 해제

    return 0;
}

실행 결과

Helloworld

 

5. 문자열 검색

문자열 내에서 원하는 문자를 검색하고자 한다면 strchr(str1, ch) 함수를 사용하면 된다. 해당 함수를 사용하면 문자가 저장된 위치(포인터)가 저장되기 때문에 이를 저장하기 위해선 문자형 포인터 변수를 사용해야 한다.

#include <stdio.h>
#include <string.h>    // strchr 함수가 선언된 헤더 파일

int main()
{
    char s1[30] = "A Garden Diary";  // 크기가 30인 char형 배열을 선언하고 문자열 할당

    char *ptr = strchr(s1, 'a');     // 'a'로 시작하는 문자열 검색, 포인터 반환

    while (ptr != NULL)              // 검색된 문자열이 없을 때까지 반복
    {
        printf("%s\n", ptr);         // 검색된 문자열 출력
        ptr = strchr(ptr + 1, 'a');  // 포인터에 1을 더하여 a 다음부터 검색
    }

    return 0;
}

실행 결과

arden Diary
ary

 

strchr() 함수는 문자열의 시작점에서 오른쪽으로 검색해서 해당하는 문자의 위치를 반환하지만, strrchr() 함수를 사용하면 오른쪽부터 시작해서 왼쪽으로 검색할 수 있다. 인자로 사용되는 변수와 사용 방법은 strchr() 함수와 동일하다.

 

#include <stdio.h>
#include <string.h>   // strrchr 함수가 선언된 헤더 파일

int main()
{
    char s1[30] = "A Garden Diary";    // 크기가 30인 char형 배열을 선언하고 문자열 할당

    char *ptr = strrchr(s1, 'a');      // 문자열 끝에서부터 'a'로 시작하는 문자열 검색. 포인터 반환

    printf("%s\n", ptr);   // ary

    return 0;
}

 

실행 결과

ary

 

strchr() 함수와 strrchr() 함수는 문자열 내에서 문자를 검색하는 함수이지만, strstr(str1, str2) 함수는 문자열 내에서 문자열을 검사하는 함수이다. 검색을 할 때 문자보다는 단어 단위로 검색하는 경우가 많기 때문에 해당 함수가 더 자주 쓰인다.

 

#include <stdio.h>
#include <string.h>    // strstr 함수가 선언된 헤더 파일

int main()
{
    char s1[30] = "A Garden Diary";     // 크기가 30인 char형 배열을 선언하고 문자열 할당

    char *ptr = strstr(s1, "den");      // den으로 시작하는 문자열 검색, 포인터 반환

    printf("%s\n", ptr);    // den Diary

    return 0;
}

실행 결과

den Diary

 

6.문자열 자르기

하나의 문자열을 잘라서 여러개의 문자열로 만들기 위해 사용하는 함수로 strtok(str1, ch) 함수가 있다. strtok() 함수는 지정된 문자를 기준으로 문자열을 자른다. 이 때, 한번에 여러개로 자를 수 없기 때문에 여러개로 자르고자 한다면 while 반복문을 이용해야 한다.

 

#define _CRT_SECURE_NO_WARNINGS    // strtok 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strtok 함수가 선언된 헤더 파일

int main()
{
    char s1[30] = "The Little Prince";  // 크기가 30인 char형 배열을 선언하고 문자열 할당

    char *ptr = strtok(s1, " ");      // " " 공백 문자를 기준으로 문자열을 자름, 포인터 반환

    while (ptr != NULL)               // 자른 문자열이 나오지 않을 때까지 반복
    {
        printf("%s\n", ptr);          // 자른 문자열 출력
        ptr = strtok(NULL, " ");      // 다음 문자열을 잘라서 포인터를 반환
    }

    return 0;
}

위의 코드에서 while문 내에서 다음 위치를 지정해줄 때 strtok(NULL, " ")과 같이 문자열 부분에 NULL을 넣는데, NULL을 넣으면 직전에 사용한 strtok() 함수에서 처리했던 문자열에서 잘린 문자열 만큼 뒤로 이동한 후 다음 문자열을 자르게 된다. 처음 strtok() 함수가 실행되고 ptr에는 "The" 문자열의 위치가 저장되어 있는데, while 문 내에서 ptr = strtok(ptr, " ")로 작성한다면 The가 무한히 반복되어 출력되기 때문에, 처음 사용할 때만 자를 문자열을 넣어주고, 두 번째 이상 사용할 때에는 NULL을 넣어주어야 한다. 배열이 아닌 문자열 포인터에 저장되어 있는 문자열 리터럴은 읽기 전용이기 때문에 strtok() 함수를 통해 문자열을 자를 수 없다. 이를 해결하기 위해 문자열 리터럴을 할당하는 대신 동적 메모리를 할당하고 문자열을 복사하는 것이다. 코드는 배열로 선언했을 때와 같다.

 

문자열 자르기는 여러개의 문자를 기준으로도 자를 수 있다. 아래의 코드는 날짜와 시간을 단위별로 잘라서 출력하는 것인데, strtok(s1, "-T:"); 와 같이 작성하면 -, T, : 각각을 기준으로 하여 해당 문자를 기준으로 문자열을 자르게 된다.

 

#define _CRT_SECURE_NO_WARNINGS    // strtok 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strtok 함수가 선언된 헤더 파일

int main()
{
    char s1[30] = "2015-06-10T15:32:19";    // 크기가 30인 char형 배열을 선언하고 문자열 할당

    char *ptr = strtok(s1, "-T:");    // -, T, 콜론을 기준으로 문자열을 자름
                                      // 포인터 반환

    while (ptr != NULL)               // 자른 문자열이 나오지 않을 때까지 반복
    {
        printf("%s\n", ptr);          // 자른 문자열 출력
        ptr = strtok(NULL, "-T:");    // 다음 문자열을 잘라서 포인터를 반환
    }

    return 0;
}

 

 

 

 

문자열 만들기

C언어에서 제공하는 표준 출력 함수는 printf이지만, 문자열을 처리하기 위해 특화된 함수로 sprintf 함수가 존재한다. hello, world!라는 문자열을 출력하고자 할때 printf 함수를 사용했지만, 이는 따로 저장되지 않는다. 만약 출력하지 않고 문자열을 따로 저장하고자 할 때 사용되는 함수가 바로 sprintf이다. 기본 형태는 다음과 같다.

 

sprintf(배열, 서식, 값);

 

#define _CRT_SECURE_NO_WARNINGS    // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>     // sprintf 함수가 선언된 헤더 파일

int main()
{
    char s1[20];    // 크기가 20인 char형 배열을 선언

    sprintf(s1, "Hello, %s", "world!");    // "Hello, %s"로 서식을 지정하여 s1에 저장

    printf("%s\n", s1);    // Hello, world!: 문자열 s1 출력

    return 0;
}

위의 코드에선 %s서식을 사용하고 world!라는 문자열로 바뀌면서 s1에 Hello, world! 가 저장된다. 문자형 배열 s1처럼 문자열을 존재하기 위한 비어있는 배열을 버퍼(buffer)라고 한다. 배열 형태의 문자열이 아닌 문자열 포인터를 인자로 넘겨도 동일하게 동작한다.

 


 

#41.3 퀴즈

문자열의 길이는 strlen() 함수를 통해 구할 수 있다. 답은 c.

 

문자열이 같으면 0을 반환한다. 문자열이 다를 땐, 앞의 문자열을 기준으로 뒤의 문자열이 더 크면 -1을, 뒤의 문자열이 더 작으면 1을 반환한다. 이를 옳게 작성한 것은 c, d, f.

 

#41.4 연습문제: 문자열 길이 구하기

#include <stdio.h>
#include <string.h>

int main()

{
    char *s1 = "C Language";

    printf("%d\n", ____________);

    return 0;

}

실행 결과

10

출력된 값이 문자열의 길이와 같다. 그러므로 답은 strlen(s1).

 

 

#41.5 연습문제: 문자열 비교하기

#include <stdio.h>
#include <string.h>

int main()
{
    ____________________________   
    char *s2 = "Pachelbel Canon";

    int ret = strcmp(s1, s2);

    printf("%d", ret);

    return 0;
}

실행 결과

0

strcmp가 0이 되려면 비교하는 두 문자열 s1과 s2가 같아야 한다. 그러므로 답은 char *s1 = "Pachelbel Canon";.

 

#41.6 심사문제: 문자열 길이 구하기

입력 예시

Beethoven

 

출력 예시

9

 

 

strlen(s1)을 통해 문자열의 길이를 출력해주면 된다.

 

#include <stdio.h>
#include <string.h>

int main(){
    char *s1 = malloc(sizeof(char) * 30);
    scanf("%s", s1);
    
    printf("%d \n", strlen(s1));
    
    return 0;
}

 

 

#41.7 심사문제: 문자열 비교하기

두 문자열 s1, s2를 선언하고 입력 받은 후에 strcmp의 결과값을 출력해주면 된다.

 

#include <stdio.h>
#include <string.h>

int main(){
    char *s1 = malloc(sizeof(char) * 30);
    char *s2 = malloc(sizeof(char) * 30);
    
    scanf("%s %s", s1, s2);
    printf("%d", strcmp(s1, s2));
    
    return 0;
}

 

 

#42.5 퀴즈

Hello 5글자를 저장할 공간 + 널 문자를 저장할 공간이 필요하기 때문에 답은 b.

 

 

 

 

Hello 문자열 뒤에 저장되어 있던 널 문자가 사라지고 그 자리부터 시작해서 world를 붙여 넣는다. world의 뒤에 널 문자가 추가 되므로 답은 11.

str이 들어간 함수는 대부분 string.h 헤더 파일에 선언되어 있다고 생각하면 편하다. 답은 c.

 

 

 

#42.6 연습문제: 문자열 포인터를 배열에 복사하기

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char *s1 = "C Language";
    char s2[20];

    _______________________________

    printf("%s\n", s2);

    return 0;
}

실행 결과

C Language

s1의 내용을 s2로 복사해야 한다. strcpy(str1, str2)를 이용하면 된다. 답은 strcpy(s2, s1);.

 

#42.7 연습문제: 문자열 포인터를 동적 메모리에 복사하기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    char *s1 = "The Little Prince";
    char *s2 = ①______________________

    ②__________________________

    printf("%s\n", s2);

    free(s2);

    return 0;
}

s1의 내용을 s2에 저장해야 하기 때문에 s1의 크기를 충분히 잡은 후 동적 할당해준다. 그런 후에 strcpy를 이용해서 s2에 s1을 복사해주면 된다. 답은

malloc(sizeof(char) * 20);

strcpy(s2, s1);

 

 

#42.8 연습문제: 문자 배열을 붙이기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char s1[20] = " 9th Symphony";
    char s2[40] = "Beethoven";

    ________________________

    printf("%s\n", s2);

    return 0;
}

 

실행 결과

Beethoven 9th Symphony

 

문자열 붙이기 함수는 strcpy이다. s2가 앞에오고 뒤에 s1이 와야하기 때문에 s2의 뒷부분에 s1 문자열을 붙여주면 된다.

답은 strcat(s2, s1);

 

 

#42.9 연습문제: 문자열 리터럴과 동적 메모리 붙이기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    char *s1 = " Wonderland";
    char *s2 = malloc(sizeof(char) * 30);

    ①____________________

    ②____________________

    printf("%s\n", s2);

    free(s2);

    return 0;
}

 

Alice in Wonderland

먼저 Alice in 이란 글자를 s2에 복사해서 넣어준다. 그 후에 s2 뒤에 s1을 붙여서 문장을 완성하면 된다.

 

strcpy(s2, "Alice in");
strcat(s2, s1);

 

 

#42.10 심사문제: 문자 배열 복사하기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char s1[31];
    char s2[31];

    _______________
    _______________
 
    printf("%s\n", s1);
    printf("%s\n", s2);

    return 0;
}

 

두 줄을 작성해서 아래의 두 출력이 같은 결과가 나오도록 해야 한다. 먼저 s1과 s2중 아무 곳에 문자열을 입력 받은 후에, 입력 받지 않은 문자열에 복사해주면 둘의 출력 결과가 같아진다. 

 

scanf("%s", s1);
strcpy(s2, s1);

 

 

#42.11 심사문제: 두 문자열 붙이기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char s1[40];

    ______________________________________
    ______________________________________

    printf("%s\n", s1);

    return 0;
}

먼저 s1에 문자열을 입력 받은 후에, s1뒤에 "th"를 붙여준다. 이 때 strcat 함수를 사용하는데, 두 번째 인자를 어떠한 변수가 아닌 그냥 "th"와 같이 써주어도 된다.

 

scanf("%s", s1);
strcat(s1, "th");

 

 

#43.3 퀴즈

 

 

 

sprintf 함수의 형태는 sprintf(배열 이름, 서식, 값) 이다. 답은 d.

 

 

a와 10은 각각 문자, 정수이다. 이에 맞는 서식을 써야하므로 답은 "%c %d".

 

 

문자열을 저장하기 위한 배열 혹은 메모리 공간을 버퍼(buffer)라고 한다.

 

 

 

#43.4 연습문제: 숫자와 문자열을 조합하여 문자열 만들기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    char s1[20];

    sprintf(s1, "%dth %s", ________________);

    printf("%s\n", s1);

    return 0;
}

 

실행 결과

9th Symphony

 

각각의 서식이 정수형과 문자열이기 때문에 서식에 맞는 형태로 작성하면 된다. 답은 9, "Symphony".

 

 

 

#43.5 연습문제: 서식에 맞게 문자열 만들기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    char s1[20];
 
    sprintf(s1, _________________, 10, 20, 30, 'c', 99);

    printf("%s\n", s1);

    return 0;
}

실행 결과

10 20 30 c 99

각각의 출력 결과가 정수 정수 정수 문자 정수이다. 이에 맞게 서식을 작성하면 된다. 답은 "%d %d %d %c %d".

 

 

#43.6 심사문제: 서수 줄임말 문자열 만들기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    int number;
    char name[31], result[40];

    ______________________________________

    ______________________________________
    ______________________________________
    ______________________________________
    ______________________________________
    ______________________________________
    ______________________________________
    ______________________________________
    ______________________________________

    printf("%s\n", result);

    return 0;
}

먼저 띄어쓰기로 구분해서 정수와 문자열을 각각 number와 name에 입력받는다. 숫자가 1, 2, 3일 때만 다르고 4~7일때는 모두 뒤에 th가 붙기 때문에 1, 2, 3이 입력되었을 때의 경우를 if문으로 작성하고 else로 4~7인 경우에 대해 작성한다. 이 때, result를 출력했을 때 number와 name이 모두 출력되어야 하기 때문에 result를 버퍼로서 sprintf문을 사용해서 하나의 문자열로 저장해준다.

 

scanf("%d %s", &number, name);

if(number==1){
    sprintf(result, "%dst %s", number, name);
}
else if(number==2){
    sprintf(result, "%dnd %s", number, name);
}
else if(number==3){
    sprintf(result, "%drd %s", number, name);
}
else{
    sprintf(result, "%dth %s", number, name);
}

 

 

#44.4 퀴즈

문자열에서 문자를 검색하는 함수는 왼쪽에서 시작하는 strchr(), 오른쪽에서 시작하는 strrchr() 함수가 있다. 답은 c, e.

 

문자열 내에서 문자열을 검색하는 함수는 strstr() 함수이다. strstr() 함수는 검색하고자 하는 문자열의 시작 위치(주소)를 반환하기 때문에 이를 저장하기 위해선 문자형 포인터 변수를 선언해야 한다. 답은 b.

 

 

#44.5 연습문제: 문자열 안에서 문자로 검색하기

#include <stdio.h>
#include <string.h>

int main()
{
    char s1[30] = "Alice in Wonderland";
    
    ①___________________________________

    ②___________________________________
    {
        printf("%s\n", ptr);
        ③___________________________________
    }
    
    return 0;
}

실행 결과

n Wonderland
nderland
nd

 

실행 결과의 문자열의 시작이 모두 n이기 때문에, n을 검색한 후에 ptr을 출력하는 while 반복문을 작성하면 된다. 이 때의 조건은 ptr != NULL이 된다.

1. char *ptr = strchr(s1, 'n');

2. while(ptr != NULL)

3. ptr = strchr(ptr+1, 'n');

 

 

#44.6 연습문제: 문자열의 오른쪽 끝부터 문자로 검색하기

#include <stdio.h>
#include <string.h>

int main()
{
    char s1[30] = "The Little Prince";

    ____________________________________

    printf("%s\n", ptr);

    return 0;
}

실행 결과

ince

 

i를 검색한 후 ptr에 저장해준 다음 출력해주면 되지만, 왼쪽부터 검색하면 i가 하나 더 있기 때문에 ittle Prince가 출력된다. 문자열의 모든 i중 출력하고자 하는 i의 위치가 오른쪽에서 첫 번째에 있기 때문에 strrchr() 함수를 이용해서 문자열을 오른쪽에서부터 검사해주면 된다.

char *ptr = strrchr(s1, 'i');

 

#44.7 심사문제: 공백 개수 세기

길이 1001을 저장할 수 있는 배열(널 문자 포함)을 선언한 후에 문자열을 입력받는다. 그리고 while 반복문을 통해서 공백문자를 검색한 후, 카운트를 하나 증가시킨다.그 후에 ptr의 다음 위치부터 공백문자를 또 검색한다. while 반복문이 끝나면 카운트 변수를 출력해준다.

#include <stdio.h>
#include <string.h>

int main(){
    char s1[1001];
    int cnt=0;
    scanf("%[^\n]s", s1);
    
    char *ptr= strchr(s1, ' ');
    while(ptr != NULL){
        cnt++;
        ptr = strchr(ptr+1, ' ');
    }
    printf("%d \n", cnt);
    
    return 0;
}

 

 

 

#45.5 퀴즈

문자열을 자를 땐 strtok() 함수를 사용한다. 답은 d.

 

strtok() 함수는 여러 개의 기준 문자를 지정할 수 있으며 문자열을 복제하지 않고 해당 문자열 내에서 해당하는 위치의 포인터를 반환한다. 답은 a, c.

strtok(대상 문자열, 기준 문자)의 형태이며 포인터를 반환하기 때문에 포인터형 변수를 선언해야 한다. 답은 b.

 

 

#45.6 연습문제: 문자열 자르기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char s1[40] = "Alice's Adventures in Wonderland";

    ①__________________________________

    ②__________________________________                             
    {
        printf("%s\n", tok);
        ③__________________________________
    }

    return 0;
}

strtok() 함수를 이용해 기준 문자를 공백문자로 지정해서 띄어쓰기마다 줄을 바꿔서 출력해줄 수 있다. 이 때, 처음 사용하는 strtok() 함수는 기준 문자열을 s1으로 지정해주어야 하지만, while 반복문을 통해 그 이후에 strtok() 함수를 사용할 땐 기준 문자열을 NULL로 지정해주어야 한다.

1. char *tok = strtok(s1, " ");

2. while(tok != NULL)

3. tok = strtok(NULL, " ");

 

 

#45.7 심사문제: 문자열 자르기

문자열을 입력받아서 s1에 저장한 후에 strtok() 함수를 통해 문자열을 잘라서 출력해주면 된다. 이 때 기준문자는 "."이 된다.

입력 받는 문자열의 길이가 최대 60이기 때문에, 널 문자를 포함한 61개의 문자를 저장할 수 있도록 크기를 지정해주어야 한다.

 

 

#include <stdio.h>
#include <string.h>

int main(){
    char s1[61];
    char *ptr;
    
    scanf("%s", s1);
    ptr = strtok(s1, ".");
    
    while(ptr != NULL){
        printf("%s \n", ptr);
        ptr = strtok(NULL, ".");
    }
    
    return 0;
}

 

 

#45.8 심사문제: 특정 단어 개수 세기

 

입력의 최대 길이가 1000이기 때문에 1001의 크기의 배열을 선언해야 한다. 문자열을 검색할 때 "the"만 검색한다면 "them", "there" 등등 "the"의 개수보다 많이 카운팅하게 된다. 이러한 방법을 해결하기 위해, "the"는 어차피 한 단어이고, 그 뒤엔 띄어쓰기가 있을 것이기 때문에 "the"로 검색하는게 아니라 띄어쓰기까지 포함해서 "the "를 검색하였는데. 문장의 맨 마지막 부분을 보면 "the "가 아닌 "the."여서 카운팅이 안 되었다. 단어는 띄어쓰기 뿐만 아니라 콤마, 점 등으로도 끝날 수 있기 때문에 strtok을 통해서 기준 문자를 공백, 점, 쉼표로 해주어서 각각의 단어를 잘라주었다. 이 때, 해당 문자열이 "the"인지 확인하려면 strcmp를 사용해야 한다. strcmp는 같으면 0을 반환한다. 코드는 다음과 같다.

 

#include <stdio.h>
#include <string.h>

int main(){
    char s1[1001];
    char *ptr;
    int cnt=0;
    
    scanf("%[^\n]s", s1);
    ptr = strtok(s1, "., ");

    while(ptr != NULL){
        if(strcmp(ptr, "the")==0){
            cnt++;
        }
        ptr = strtok(NULL, "., ");
    }
    
    printf("%d \n", cnt);
    return 0;
}