012. STRING

Posted on by pkchan

012-01 // DECLARATION & INITIALIZATION

C언어에서는 char형 배열을 string이라 부릅니다. char형 변수에 하나의 문자를 대입하므로 배열을 만들어서 문자열을 만드는 것입니다. 기초적인 문법은 배열과 같으나 약간의 특징이 있습니다.

char (배열이름)[문자 수 + 1];

char형의 배열이라면 배열에 문자열을 입력, 출력하기 위해서 반복문이 필요하고, 매번 입력 출력할 때마다 반복문을 사용해야 할 것입니다. C언어는 이런 불편함을 해결하기 위해 몇 가지 규칙을 만듭니다.

첫 번째는 널(NULL) 문자를 사용하여 문자열의 끝을 지정합니다. char형의 배열에 [문자 수 +1]이 들어가는 이유입니다. NULL 문자는 아스키코드의 값이 0인 문자입니다. 숫자 0은 아스키코드값이 48입니다. 숫자 0과 혼동하면 안 됩니다. ‘\0’ 혹은 작은따옴표 없는 0 또는 NULL로 써주면 됩니다.

char str[6] = {‘a’,’p’,’p’,’l’,’e’,’\0’};
char str[6] = {‘a’,’p’,’p’,’l’,’e’,0};
char str[6] = {‘a’,’p’,’p’,’l’,’e’,NULL};

두 번째는 각각 써줘야 하는 배열의 원소를 큰따옴표로 줄여 쓸 수 있게 했습니다. 끝자리에는 자동으로 널 문자가 들어갑니다. 문자 수 + 1은 꼭 해줘야 합니다.

char str[6] = {“apple”};

char형의 배열도 정수의 배열과 마찬가지로 원소의 수가 정해져 있다면 선언 시 문자 수를 생략해도 컴파일러가 계산해서 컴파일 해줍니다.

char str[] = “apple”;

세 번째는 입력(scanf), 출력(printf)을 반복문 없이 할 수 있도록 %s를 만듭니다. string 서식문자입니다.

/*
 example 012-01
 C language string
*/

#include <stdio.h>

int main() {
          
          char str1[9] = {'h','i',' ','s','e','o','u','l'};
          char str2[10] = {"hi london"};
          char str3[] = "hi newyork";
          char str4[31];
          printf("단어를 입력하세요(30자 이하) :");
          scanf("%s",str4);
          
          printf("%s\n",str1);
          printf("%s\n",str2);
          printf("%s\n",str3);
          printf("입력하신 단어는 %s입니다.\n\n",str4);

          return 0;
          
}

사용자가 입력할 단어의 크기를 알 수 없으므로 30글자로 제한하고 31개의 원소를 가지는 배열을 선언합니다. 마지막에는 널 문자가 들어가야 합니다. scanf는 띄어쓰기를 지원하지 않습니다. 띄어쓰기를 만나면 널 문자로 인지하고 더 이상 입력을 받지 않습니다.

012-02 // BUFFER (STDIN)

scanf 혹은 다른 표준 함수를 통해 키보드로 입력받은 데이터는 바로 우리의 결과로 전달되지 않습니다. scanf 함수가 입력을 기다리는 것은 키보드에서 전달받기를 기다리는 것이 아니라 입력 버퍼 (stdin)에 원하는 형태의 데이터가 입력되기를 기다립니다. %d는 입력 버퍼에서 정수만 가져갑니다. %s는 문자열만 가져갑니다. 스페이스 공간, 혹은 엔터를 만날 때 그리고 다른 자료형이 등장 할 때까지 가져갑니다. 그러나 %c는 다릅니다. 엔터(\n)도 문자로 인식하여 가져가고 스페이스 공간도 문자로 인식하여 가져갑니다.

/*
 example 012-02
 C language string
*/

#include <stdio.h>

int main() {

          char cha, str[30];
          int num;
          
          printf("정수를 입력하세요! :");
          scanf("%d",&num);
          printf("문자를 입력하세요! :");
          scanf("%c",&cha);
          printf("단어를 입력하세요! :");
          scanf("%s",str);
          
          printf("\n입력하신 결과는 정수 : %d, 문자 : %c, 단어 : %s입니다.\n\n",num,cha,str);
          
          return 0;
          
}

example 012-02를 실행해보면 문자에는 엔터(\n)가 입력됩니다. 정수를 입력할때 123 abc를 입력하면 문자에는 스페이스 공간이 들어가고 문자열은 abc가 들어갑니다. 버퍼에 남아있는 데이터를 다음에 실행되는 scanf 함수가 차례차례 가져갑니다.

이 문제는 문자를 입력받을 경우에도 %s를 사용하면 해결됩니다. 또한 띄어쓰기가 포함된 문자열을 입력받고 싶다면 문자열 관련된 다른 표준함수를 사용해도 됩니다.

ex)
fflush(stdin); //버퍼(stdin)을 비워줍니다.
gets(); //문자열을 입력받습니다. 띄어쓰기 포함 엔터(\n)까지.
puts(); //문자열을 출력합니다.

/*
 example 012-03
 C language string
*/

#include <stdio.h>

int main() {
          
          char string[30];

          printf("문자열을 입력하세요 : ");
          gets(string);
          printf("입력한 문자는 ");
          puts(string);
          
          return 0;
          
}

fgets(); // 정해진 크기만큼 문자열을 입력받습니다. 띄어쓰기 포함 엔터(\n)까지. 사이즈 이외의 문자는 버퍼에 남습니다.
fputs(); //문자열을 출력합니다.

/*
 example 012-04
 C language string
*/

#include <stdio.h>

int main() {
          
          char string[30];

          printf("문자열을 입력하세요 : ");
          fgets(string, sizeof(string), stdin);
          printf("입력한 문자는 ");
          fputs(string, stdout);
          
          return 0;
          
}

012-03 // POINTER STRING

코드에 큰따옴표로 감싼 문자열이 등장한다면 그 문자열은 메모리의 어딘가 저장됩니다. 문자열 리터럴이 됩니다. 문자열 리터럴은 상수라서 메모리의 읽기 전용 공간에 저장됩니다. 그리고 문자열 리터럴은 특이하게 문자열이 시작되는 주소를 가지고 있습니다

/*
 example 012-05
 C language string
*/

#include <stdio.h>

int main() {
          
          printf("%s\n","apple");
          printf("%s\n","apple"+1);
          printf("%s\n","apple"+2);
          printf("%s\n","apple"+3);
          printf("%s\n","apple"+4);

          return 0;
          
}

주소를 이동하는 연산도 가능합니다. 그러면 포인터에 주소를 저장할 수 있습니다. 문자열 리터럴은 상수라서 수정은 안됩니다.

/*
 example 012-06
 C language string
*/

#include <stdio.h>

void view();

int main() {
          
          char* ch = "abcdefghijklmnopqrstuvwxyz";
          
          while (*ch != '\0'){
                    
                    printf("%s\n",ch);
                    ch++;
                    
          }

          return 0;
          
}

012-04 // STRING FUNCTIONS

문자열은 연산할 수 없습니다. +를 사용하여 합칠 수 없으며, -를 사용하여 뺄 수도 없습니다. 같은지 다른지 비교도 불가능합니다. 문자열의 길이를 리턴하고 같은 문자열인지 비교하며, 문자열을 합치고 복사하는 함수를 만들어 두면 유용하게 사용할 수 있습니다.

001. 문자열의 길이를 리턴하는 함수

/*
 example 012-07
 C language string
*/

#include <stdio.h>

int string_length(char* str);

int main(){
          
          char string[30] = "apple and potato";
          
          printf("%s\n",string);
          printf("string length = %d\n",string_length(string));
          
          return 0;
          
}

int string_length(char* str){
          
          int i=0;
          
          while(*str!='\0') {
                    
                    ++i;
                    ++str;
                    
          }

          return i;
          
}

REVIEW EXERCISES

1. 두 개의 문자열이 같은지 비교하는 함수를 정의하세요.

2. 문자열을 복사하는 함수를 정의하세요.

3. 문자열을 합치는 함수를 정의하세요.

4. 팔린드롬을 구별하는 함수를 제작하세요.

단어를 입력하세요 : sos
회문이 맞습니다.

5. 단어를 입력받아 2자리씩 출력하세요. (N-gram)

단어를 입력하세요 : apple
ap
pp
pl
le

Leave a Reply