컴퓨터 공부/© C

[C언어] 9. 문자열

letzgorats 2021. 2. 13. 20:01

9. 문자열

 

<문자열>

 

- 말 그대로 문자들의 배열이다

- 문자열은 컴퓨터 메모리 구조상에서 마지막에 널(NULL)값을 포함한다.(NULL: 컴퓨터상에서 존재하지 않는다. , 어떠한 값도,의미 있는 값이 들어가 있지 않다.)

- NULL값이 들어가는 이유는 문자열의 끝을 알리는 목적으로 사용된다.(\0)

- printf을 실행하면 컴퓨터는 내부적으로 NULL값을 만날 때 까지 출력한다.

 

 

<문자열과 포인터>

 

- 문자열 형태로 포인터를 사용하면 포인터에 특정한 문자열의 주소를 넣게 된다.

- 문자열을 읽기 전용으로 메모리 공간에 넣은 뒤에 그 위치를 처리한다.

- 문자열 리터럴(“”큰 따옴표 안에 어떠한 문자열이 들어가는 구조) 자체는 변경이 불가능하다. 문자열을 바꾸고 싶으면 포인터가 가리키고 있는 문자를 바꾸면 된다.

 

(예제1)포인터를 통한 문자열 표현 가능(문자열 리터럴)

#include <stdio.h>

void main(void) {

        char *a = "Hello World";

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

        system("pause");

        return 0;
}

(해설) 포인터를 통해서 특정한 문자열의 주소를 넣어주게 되고 이러한 문자열을 문자열 리터럴이라고 한다. 이는 컴파일러가 알아서 메모리 주소를 결정하는 것이다(포인터가 알아서 주소처리해준다!^__^)

 

(예제2) 포인터로 문자열을 선언했다고 하더라도 기존의 배열처럼 처리 가능

#include <stdio.h>

void main(void) {

        char* a = "Hello World";

        printf("%c\n",a[0]);

        printf("%c\n", a[3]);

        printf("%c\n", a[5]);

        system("pause");

        return 0;
}

(해설) 포인터를 사용해 문자열을 선언했다고 하더라도 기존 문자파트에서의 배열처럼 사용할 수 있다. 여기서 주의할 점은 printf문에서 %s가아니라 기존 배열에서 활용했던 것처럼 %c가 와야 한다는 점이다. 포인터와 배열은 사실 동일하다고 말했었다.

 

<문자 입출력 함수>

 

- scanf()함수는 공백을 만날 때 까지 입력을 받지만, gets()함수는 공백까지 포함하여 한 줄을 입력 받는다.

- gets()함수는 버퍼의 크기를 벗어나도 입력을 받아버린다.

- C11표준부터는 버퍼의 크기를 철저히 지키는 gets_s()함수가 추가되었다.

 

(예제3)

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
 
void main(void) {

        char a[100];

        gets(a);

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

        system("pause");

        return 0;
}

(해설) 우선, char[100] 100자까지 들어갈 수 있는 문자를 만든 것이다. gets()함수에 매개변수 a를 넣어주고 출력해보면, 사용자가 hello world 이런 식으로 중간에 공백이 포함된 형태로 문자열을 입력하더라도 공백도 문자열의 일부로 인식한다. gets()함수가 아닌 scanf()함수를 쓰면 사용자가 hello world라고 입력하면 공백 전까지, hello 만 출력된다.

나중에 공부하게 되겠지만 gets()함수 이 배열의 전체 범위를 고려하지 않는다는 점에서 보안상의 취약성이 있다고 알려져 있다. 공부는 gets()로 먼저 하겠지만 나중에 실무에서는 프로그램을 개발하게 될 때는 gets_s()를 사용하게 될 것이다. gets_s()함수매개변수가 2 들어가는데, 특정한 범위만큼만 정확히 문자열을 입력 받는다는 점에서 다소 안정적인 함수라고 할 수 있다.

 

(예제4) gets_s()함수는 버퍼의 크기를 철저히 지킨다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void main(void) {

        char a[100];

        gets_s(a,sizeof(a));

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

        system("pause");

        return 0;
}

(해설) gets_s함수는 버퍼의 크기를 철저히 지키기 때문에 사용자가 100자를 초과하게 입력해버리면 오류메시지가 뜨면서 실행되지않는다.(gets_s()함수를 이용하는 경우 범위를 넘으면 그 즉시 런타임(Runtime)오류가 발생한다) gets_s()함수는 매개변수를 2 받는데,  sizeof()함수 C언어에서 기본적으로 제공하는 함수로서 특정한 배열의 전체 크기가 얼마인지를 알려주는 함수이다. 

 

<문자열 처리를 위한 다양한 함수>

 

- C언어의 문자열처리와 관련해서는 기본적인 문자열 함수를 알고 있자!

- C++을 이용하면 더욱 간편하고 다양한 함수를 사용할 수 있다.

- C언어에서의 문자열 함수는 <stdio.h> 라이브러리에 포함되어 있다.

 

 ※ strlen(): 문자열의 길이를 반환(string length)

(예제5) strlen()

 

#include <stdio.h>

void main(void) {

        char a[20]="JeonYeop Kim";

        printf("문자열의 길이=%d\n",strlen(a));

        system("pause");

        return 0;

}

 

 

strcmp(): 문자열 1이 문자열 2보다 사전적으로 앞에 있으면 -1, 뒤에 있으면 1을 반환(string compare)

(예제6) strcmp()

#include <stdio.h>

void main(void) {

        char a[20]="JeonYeop Kim";

        char b[20] = "Salomon Aloo";

        printf("두 배열의 사전 순 비교=%d\n",strcmp(a,b));

        system("pause");

        return 0;

}

(해설) strcmp(문자열1변수,문자열2변수) 를 써주면 되고, 사전적으로 문자열 1이 앞에 있으면 -1, 뒤에 있으면 1을 반환한다. %d는 잊지마라.

 

strcpy(): 문자열을 복사(C언어에서는 기본적으로 ‘a=b’와 같은 간단한 방식으로는 복사가 안된다.)(string copy)

(예제7) strcpy()

#include <stdio.h>

void main(void) {

        char a[20]="JeonYeop Kim";

        char b[20] = "Salomon Aloo";

        strcpy(a, b);

        printf("복사된 문자열:%s\n",a);

        system("pause");

        return 0;

}

(해설) strcpy(a,b);ab를 복사하는 뜻이므로 a를 출력하면 “Salomon Aloo”가 나오는 것을 확인 할 수 있다.

 

 strcat(): 문자열 1 + 문자열 2 (문자열1에 문자열2를 더해줌)(string concatenate)

(예제8) strcat()

#include <stdio.h>

void main(void) {

        char a[20]="My pet name is ";

        char b[20] = "Salomon Aloo";

        strcat(a, b);

        printf("합쳐진 문자열:%s\n",a);

        system("pause");

        return 0;
}

(해설) 실행은 되긴 된다. 출력도 원하는 대로 되긴 하는데, Run-Time Check Failure #2 - Stack around the variable 'a' was corrupted. 라는 오류가 뜬다. 원인은 바로 포인터에 있다. 지역변수(배열 변수나 클래스 변수나 관계없음)의 주소(포인터)를 이용해서 그 변수의 값 등을 기록하려 할 때, 실제로 선언된 크기(할당된 크기)보다 더 큰 타입으로 기록하려고 할 때 발생한다. 쉽게 말해, a[20]인데 b를 더해버리면 a20보다 커지기 때문에 그렇다고 이해하면 된다. 그래서 보통 합쳐지는 걸 감안해서 첫 문자 배열크기를 a[30],a[40]등으로 더 늘려줘야 한다.

 

 strstr(): 문자열 1에 문자열 2가 어떻게 포함되어 있는지를 반환(string string)

(예제9)strstr()

#include <stdio.h>

void main(void) {

        char a[20]="Aloo likes you ";

        char b[20] = "like ";

        printf("찾은 문자열:%s\n",strstr(a,b));

        system("pause");

        return 0;
}

(해설) strstr()긴 문자열에서 짧은 문자열을 찾아 그 위치를 반환한다. 짧은 문자열을 찾은 주소 값 자체를 반환하므로 단순히 출력하도록 하면, 찾은 이후의모든 문자열이 반환된다! , 위 예제에선,like를 찾고 싶은 것이므로 프로그램을 돌려보면 likes you가 출력된다. like라는 문자열을 찾은 후 그 이후의 모든 문자열이 반환되기 때문이다. ‘Aloo’는 출력이 안된다. 그리고 strstr(a,b)라는 뜻은 a에서b를 찾고 싶은 거니까 저렇게 표현하는게 맞다.

 

(정리)

1) C언어에서 문자열은 내부적으로는 배열이므로 포인터 형태로 사용할 수 있다.

2) C언어에서 문자열 비교, 연산, 탐색 등의 알고리즘의 사용방법은 각각 함수 형태로 제공된다.

반응형

'컴퓨터 공부 > © C' 카테고리의 다른 글

[C언어] 11. 다차원 배열과 포인터 배열  (0) 2021.02.14
[C언어] 10. 컴퓨터가 변수를 처리하는 방법  (0) 2021.02.14
[C언어] 8. 문자  (0) 2021.02.13
[C언어] 7. 포인터  (0) 2021.01.28
[C언어] 6. 배열  (0) 2021.01.28