문자열
문자열은 쉽게 말하면 문자들의 연속, 즉 문자 배열이다.
예를 들어 Hello라는 문자열을 문자 배열로 표현하면
H | E | L | L | O | \0 |
이다.
이때 주의할 점은 문자열의 끝에는 항상 널 문자(\0)가 붙는다는 것이다. 그렇기 때문에 문자형 배열에 문자열을 입력할 때는 배열의 크기가 항상 문자 개수 + 1 이상이여야 한다.
간단한 예제를 하나 살펴보자
#include <stdio.h>
int main(void)
{
char ss[8] = "Basic-C"; // 문자형 배열
int i;
ss[5] = '\0'; // '-'를 널문자로 바꿈
printf("문자열 배열 ss => %s \n", ss);
return 0;
}
5번 줄을 살펴보자. 5번 줄의 코드는 크기가 8인 문자형 배열 ss을 "Basic-C"라는 문자열로 초기화한다.
이때 "Basic-C"는 글자의 수가 7개인데, 배열의 크기는 8이다. 이는 널문자를 고려했기 때문이다.
B | a | s | i | c | - | C | \0 |
이제 8번 줄을 살펴보자. 8번 줄의 코드는 ss의 5번째 원소인 '-'를 널문자로 바꾼다. 그러고 나서 %s를 통해 문자열 ss를 출력하면 "Basic"만 나오게 된다. 이것은 %s의 특성때문인데, %s는 널문자를 만나면 문자열이 끝났다고 판단한다. 정리하면 %s는 널문자를 만나면 출력을 멈춘다.
문자열 관련 함수
문자열을 처리하는 함수는 string.h 헤더파일에 정의되어있다. 그러므로 문자열 함수들을 사용하려면 string.h 헤더파일을 include 해야한다. 그럼 문자열을 처리하는 함수 몇 가지를 살펴보자
- strlen(문자열 A) -- string length
strlen함수는 문자열의 길이를 정수로 리턴하는 함수다. 이때 기억해야 할 점은 strlen 함수는 널 문자를 제외한 문자의 개수만 센다는 것이다.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[12] = "Hello World";
printf("Length of Sentence : %lu\n", strlen(str)); // 널 문자를 제외 -> 11
printf("Length of Array : %lu\n", sizeof(str)/sizeof(char)); // 배열의 길이(널문자 포함) -> 12
return 0;
}
sizeof를 이용해 도출한 배열 str의 길이는 널문자를 포함하기 때문에 12지만, strlen 함수를 이용해 도출한 문자열의 길이는 11가 나온다. 이를 통해 strlen 함수는 널 문자를 제외한 문자열의 길이를 반환한다는 것을 알 수 있다.
이때 주의할 점은 배열 중간에 널문자가 있으면 중간까지만 출력한다는 점이다.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[12] = "Hello World";
str[2] = '\0'; // l -> \0
printf("Length of Sentence : %lu\n", strlen(str)); // He\0lo World\0이기 때문에 He만 출력
return 0;
}
8번 줄에서 l을 널문자로 바꿨기 때문에 strlen은 문자열이 He로 끝난다고 판단하고 2를 반환한다.
- strcpy(문자열 배열 A, 문자열 B) -- string copy
strcpy는 A에 B를 복사(덮어쓰기)하는 함수다. 이때 A는 항상 변수(배열)여야하고, B는 변수(배열) 또는 문자열("ABCD")이여야한다.
주의해야할 점 세 가지를 살펴보자.
첫 번째는 A의 크기는 무조건 B의 문자개수 + 1 이상이여야 한다는 것이다.
두 번째는 위의 strlen과 마찬가지로 널문자를 문자열 B에서 널문자가 있는 곳 까지만 덮어쓰기를 한다는 것이다.
세 번째는 A에 B를 덮어쓴 후 마지막에 자동으로 널 문자가 삽입된다.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[6] = "Hello";
printf("%s\n", str); // Hello 출력
strcpy(str, "ABC");
printf("%s\n", str); // ABC 출력
strcpy(str, "X\0Z"); // 중간에 널 문자가 있다.
printf("%s\n", str); // X만 출력
return 0;
}
배열 str을 "Hello"로 초기화 한 후, 출력하면 Hello가 출력된다. 그 다음에 strcpy 함수를 이용해 배열 str의 내용을 ABC로 덮어쓴다. 출력하면 ABC가 출력된다. 그 다음 널 문자가 있는 문자열(X\0Z)을 덮어쓴다. 이때 strcpy 함수는 널 문자 앞까지의 문자열만 덮어쓰기 때문에(뒤의 Z는 무시) str의 값은 X가 된다.
💬 strcpy 함수를 쓰는 대신 배열에 직접 문자열을 대입하면 안 될까?
문자열을 배열에 직접 대입하는 것은 처음 배열을 선언하면서 초기화할 때만 가능하고 그 이후에는 문자열을 대입해 배열의 값을 바꿀 수 없다. 선언 후 배열의 값을 바꾸고싶다면 원소 하나하나씩 바꿔주거나, strcpy 함수를 사용해야 한다.
- strcat(문자열 배열 A, 문자열 B) -- string concatenate
strcat 함수는 A에 B를 이어붙인 후 다시 A에 집어넣는다. 쉽게 말해서 문자열 두 개를 이어 붙인다고 생각하면 된다.
주의해야할 점 두 가지를 살펴보자.
첫 번째는 B는 A의 널 문자 자리부터 이어 붙인다는 것이다.
두 번째는 배열 A의 길이는 'A + B 문자열 길이 + 1' 이상이어야 한다.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[9] = "Hello";
printf("%s\n", str);
strcat(str, "ABC");
printf("%s\n", str);
return 0;
}
- strcmp(문자열 A, 문자열 B) -- string compare
두 문자열이 같은지 비교하는 함수다. 원리는 각각 원소의 아스키코드 값을 서로 뺀 후, 결과값에 따라 같은지 다른지 정하는 것이다. 결과가 0이면 두 문자열이 같은 문자열이고, 그 외의 값은 두 문자열이 다르다는 것이다.
문자열을 직접 수정하는 함수 이외에, 문자열을 입력하거나 출력하는 함수 또한 존재한다.
- gets(문자열)
gets 함수는 문자열을 입력받는 함수다. scanf와 기능은 비슷하지만 문자열 입력 시 더 유용하다.
gets 함수는 scanf 함수와 다른 점이 있는데, scanf 함수는 공백을 입력할 수 없지만 gets 함수는 공백을 입력할 수 있다는 점이다.
gets 함수는 널 문자까지 고려해 최대 '배열크기 - 1'개의 문자를 입력할 수 있다.
- puts(문자열 or 문자 배열)
puts 함수는 문자열을 출력하는 함수다. printf와 기능은 비슷하지만 문자열 입력 시 더 유용하다.
puts 함수는 printf 함수와 다른 점이 있는데, '\n'를 입력하지 않아도 출력 후 자동으로 줄 넘김을 한다는 것이다.
'Programming > C' 카테고리의 다른 글
포인터 (0) | 2021.06.16 |
---|---|
메모리 할당과 주소 (2) | 2021.05.09 |