[C] 문자열
파이썬과 많이 다른 느낌의 C에서의 문자열.
C를 배우면서 특이한 점을 느낀다면, C언어는 문자열이라는 개념보다는 주소와 길이의 개념이 있다.
#include <stdio.h>
#pragma warning (disable :4996)
int main() {
printf("%s\n", "Happy"); // %s : 주소(H, 문자열의 맨 앞)부터 널문자('\0')이전까지 출력한다.
printf("%s\n", "Happy" + 3); // 연산결과 : py (H에서 3번 건너뛴 주소부터 끝까지)
return 0;
}
위와 같은 코드가 있다고 해보자.
Happy라는 문자열을 출력하면, “Happy\0”이라는 문자열이 메모리에 할당되며,
포인터를 이용하여 맨 앞의 문자의 메모리로 부터 null값을 가리키는 \0까지
메모리에 저장된 문자들이 쭈욱 호출되는 방식이다.
그래서 위의 코드를 실행하면 결과는 아래와 같다.
Happy
py
그러면 포인터 변수를 활용한다면?
#include <stdio.h>
#pragma warning (disable :4996)
int main() {
char* p; // p는 char형의 주소를 저장하는 포인터.
p = "boys, be ambitious"; // 이것도 가능하다! 여기다가는 boys의 맨 앞의 b의 주소가 저장된다.
printf("%s\n", p); // 그러므로 출력을 하려면 주소값 변수인 p를 넣어줘야 한다.
printf("%c\n", *p); // 그리고 *p는 가리키는 값을 말하며, 맨 앞의 문자 하나를 출력한다. 여기서는 b가 나온다.
printf("%s\n", p + 3); // s, be ambitious (s부터 null문자 이전까지 출력)
printf("%c\n", *(p + 3)); // s
printf("%c\n", p[3]); // s
return 0;
}
다시 한번 언급하면,
문자열을 저장하는 것은 문자열 첫번째부터 널문자가 나오는 곳 까지 쭉 출력하는 개념이므로,
저장되는 데이터는 포인터, 즉 주소이다.
여기서 만약에 *p를 출력하면 문자열의 첫번째 주소가 가지고 있는 값을 출력하게 되므로
b가 출력이 되는 것이다.
한편, p + 3은 p로부터 3만큼 떨어진 s를 가리키게 되므로
그 지점부터 null문자 값이 있는 지점까지 쭉 출력되는 형태이다.
포인터와 문자열
#include <stdio.h>
#pragma warning (disable :4996)
int main() {
char *p = "Time and tide wait fo no man"; // 맨 앞에 있는 문자인 T의 위치가 저장됨.
char str[8] = "process"; // 주소부터 널문자까지 배열에 복사
printf("%s\n", p); // 출력 결과 : Time and tide wait fo no man
printf("%s\n", str); // 출력 결과 : process
str[0] = 'X';
printf("%s\n", str); // 결과 : Xrocess 이거는 유효함!
//p[0] = 'X'; 결과 : 에러 or 다운 (p[0]은 문자열 상수이므로 변경이 불가능하다.)
return 0;
}
포인터에 문자열을 저장한다?
이 경우는 읽기 전용으로, 변경, 쓰기는 불가능하다.
문자열 상수의 주소를 포인터를 저자앟는 형태이며,
포인터가 가리키는 데이터는 문자열 상수이다.
때문에 포인터로 문자열에 접근해서 수정(변경)이 불가능하다.
배열에 문자열을 저장하기
이 경우는 읽기와 쓰기가 모두 가능하다.
문자열 상수와 똑같은 문자열이 배결에 저장되는 형태로,
문자열 상수와 같은 크기의 배열이 필요하다.
이 경우 문자열 상수(원본)와 배열(복사본)이 생성된다.
따라서 이 경우 생성되는 문자열은 총 2개이다.
때문에 배열에 복사 된 문자열은 수정이나 변경이 가능하다.
배열의 크기 생략할때?
char str[] = "Process rather than result"
배열의 크기와 초기화의 개수가 같은 경우는 배열의 크기가 생략이 가능하다.
문자열이 null(\0)으로 끝나는 것을 명심하기.
#include <stdio.h>
#pragma warning (disable: 4996)
int main() {
char c[255];
printf("문자열 입력: ");
//scanf("%s", c); 주소부터 저장한 후 끝에 널문자 추가하기.
//공백을 포함한 문자열은 받을 수 없다.
fgets(c, 254, stdin)
// 마지막에 널 문자를 받아야 하므로 배열의 크기 - 1을 입력!
// gets_s(str, len)와 fgets(str, len, stdin)는 내장함수이다!
printf("\n입력 문자열 : %s\n", c); //주소부터 널 문자까지 출력하기.
}