문자열(String)이란, 여러 개의 문자를 나열한 데이터이다.
C언어에서는 문자열 전용 자료형이 따로 존재하지 않는다.
그렇다면 어떻게 문자열을 나타낼까?
이전에 배운 것들을 잘 생각해보면 쉽게 답을 찾을 수 있다.
문자를 나타낼 때 사용하는 자료형은 바로.... char이다.
그렇다면 '단일 문자'를 나열하면 될텐데...
그렇다. 바로 '배열'을 사용하면 된다.

예시로 str이라는 이름의 배열에 Hello 문자열을 대입한 코드를 작성했다 (문자열에는 큰따옴표를 사용해야 한다)
메모리 구조를 살펴보면
| index | str[0] | str[1] | str[2] | str[3] | str[4] | str[5] |
| 값 | H | e | l | l | o | \0 |
index 0~4까지 H,e,l,l,o가 저장되어있고 5번째 index에 \0이 저장되어 있는 것을 알 수 있다.
이것은 문자열의 특징 중 하나인데, 문자열 끝에는 자동으로 \0이 저장된다. 이를 NULL 문자 라고 한다.
컴퓨터가 문자열을 인식할 때 얼마만큼의 길이인지 알려주는 역할을 한다
따라서 문자 개수 + 1 만큼 배열의 크기가 필요하다
또한 숫자 배열처럼 문자 하나씩 저장하는 것도 가능하다

문자 하나씩 저장하는 경우는 직접 문자열의 끝에 종료문자를 넣어주어야 한다.

만약 종료문자를 넣어주지 않으면

컴파일러는 문자열의 끝이 어디인지 모르고 쓰레기 값을 출력할 것이다.
문자열에 값을 입력받을 때가 아니라면 항상 선언할 때 값을 바로 넣어주어야 한다.
만약 선언 이후에 값을 대입한다면 str[0] = 'a'; str[1] = 'b' 등과 같이 하나하나 대입해야 한다

배열의 크기가 6인 문자열 str을 선언하고, 반복문을 사용하여 각 index에 하나씩 총 5자리 문자를 입력받도록 하였다.
0~4번째에 문자 입력, 5번째는 직접 종료문자를 넣어서 문자열의 끝을 알려주었다.
여기서 만약 happy라고 입력한 후 엔터를 누르면 h만 인식하고 4번 더 입력을 유도할 것 같지만, 실제로는 바로 happy가 출력된다.
scanf( )함수는 사용자가 콘솔 창에 입력한 내용 전체를 입력 버퍼에 넣고 for문이 작동되기 때문이다.
이러한 특징은 C언어 기초-9 <변수 입력하기 scanf( )> 글에서도 잠깐 다루긴 했지만 다시 살펴보자.
for문이 작동되어 int i=0일 때, 즉 str[0]에 'happy'라는 값을 넣었다고 가정해보자. 그러면 str[1]은 h만 저장될 것이다.
i=1일 때, 입력을 받으려고 했지만 이미 str[1]에 a라는 데이터가 존재한다. 따라서 사용자의 입력을 기다리지 않는다.
i=2일 때, 입력을 받으려고 했지만 이미 str[2]에 p라는 데이터가 존재한다. 따라서 사용자의 입력을 기다리지 않는다.
이런 식으로 계속 scanf가 버퍼를 소비하여 결국 5글자의 문자를 입력하면 따로 입력할 필요 없이 str 배열에는 happy가 저장될 것이다.

예를 들어 첫 입력에 hap을 치고 엔터를 누르면 위와 마찬가지로 index 0~2까지는 추가로 입력 받을 필요 없이 hap이 저장되고,
남은 버퍼가 없으므로 i=3일때 컴파일러는 다시 입력을 요구할 것이다.
그리고 나머지 py를 입력하고 엔터를 누르면 index 3에는 p가 대입, index 4는 버퍼에 y가 있으므로 입력을 받지 않을 것이다.
마지막 str[5]에서 종료문자가 만나 문자열이 끝나고 최종적으로 happy가 출력된다.

그리고 한 글자 씩이 아니라 문자열을 한번에 입력 받는다고 했을 때는 &를 붙이지 않아도 된다
-> 문자열 변수 이름이 곧 주소를 담고 있기 때문이다
scanf( )에는 문자열을 사용할 때도 다양한 기능들을 제공하고 있다.
첫번째는 특정 문자 집합부터 입력받을 수 있도록 하는 기능이다.


%[ ]를 사용하여 숫자부터 입력받도록 코드를 작성하였다. (0에서 9까지)
만약 숫자가 아닌 다른 문자부터 입력을 받으면 쓰레기 값이 도출된다.
버퍼에서 문자를 만날 시 프로그램은 즉시 종료된다.


물론 알파벳부터 입력하도록 하는 것도 가능하다 (소문자와 대문자)
만약 알파벳이 아닌 다른 문자부터 입력을 받으면 쓰레기 값이 도출된다.
버퍼에서 숫자를 만날 시 프로그램은 즉시 종료된다.
다섯번째는 부정문자(^)로 공백을 포함하여 문자열을 입력받는 기능이다.


기존에는 공백이 포함되지 않고 직전까지만 입력이 되었다.


하지만 ^(부정 문자)를 이용하여 \n (엔터)를 만나기 전까지 모두 입력한다는 명령을 내리면 공백도 모두 포함시킬 수 있다.


부정문자를 사용하여 숫자가 나오기 전까지 입력하도록 할 수도 있다.
다음은 읽은 문자 개수를 저장하는 기능이다.

여기에는 %n 특수 기능을 사용하면 된다.

문자를 입력했을 때 이 문자가 몇 글자인지 확인할 수 있다.
마지막으로 문자열을 변경하는 방법에 대해 알아보자

str 문자열 배열을 초기화 하고 나중에 그 값을 변경하면 어떻게 될까?

문자열의 값을 직접 변경하면 오류가 발생한다.
사실 C언어에서 배열 형태의 문자열은 선언할 때를 제외하고는 = 연산자로 직접 값을 대입할 수 없다.
문자열을 변경하는 방법은 크게 4가지가 있는데,
1. strcpy( )함수 사용하기
2. sprintf( )함수 사용하기
3. 배열 포인터 선언하기
4. 한글자씩 변경하기
간단하게 알아보자면


strcpy(문자열 이름, "추가할 문자열");의 형태로 작성하면 된다.
이 함수를 사용하기 위해서는 string.h 이름의 헤더파일을 추가해야 한다.
다음은 sprintf( )함수를 사용하는 것인데,


sprintf(배열 이름, "변경할 문장", (변수 출력)); 로 사용하면 된다.
[printf( )함수처럼 문자열만 출력해도 되고, 필요한 경우 형식지정자를 사용해서 변수를 추가해도 된다]
배열 포인터 등 변수를 추가하는 나머지 방법들은 나중에 천천히 알아보자
scanf( )함수는 C언어에서 단순 입력부터 형식화 된 데티어 처리까지 가능한 강력한 함수이지만, 버퍼와 형식지정자의 동작 방식을 제대로 이해하지 못하면 오류가 발생하기 쉽다. 따라서 다양한 예제를 직접 실행해 보면서 입력 과정과 버퍼의 변화를 확인해 보는 것이 가장 좋은 학습 방법이라고 생각한다.
VR게임 개발을 위한 언리얼엔진/C++ 공부한 내용 끄적이기...
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!