[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); //주소부터 널 문자까지 출력하기.
}

© 2022.07. by Wookey_Kim

Powered by Hydejack v7.5.2