C언어에는 문자열과 관련된 다양한 함수가 있다.
string.h
헤더파일에 선언된 문자열 관련 함수 중 사용 빈도가 높은 함수를 알아보자
가장 많이 사용되는 문자열 길이 반환 함수이다.
#include <stdio.h>
size_t strlen(const char * s);
// 전달된 문자열의 길이를 반환하되, 널 문자는 길이에 포함하지 않음
처음보는게 나왔다 size_t
는 typedef unsigned int size_t;
와 같이 선언되어 있다.
쉽게 설명하면 typedef
선언으로 인해서 size_t
가 unsigned int
를 대신할 수 있게 된다.
size_t len;
unsigned int len;
위 두 선언은 동일하다
int main() {
char str[] = "1234567";
printf("%u \n", strlen(str));
}
strlen 함수의 반환형은 size_t이니 반환 값을 unsigned int형 변수에 저장하고 서식문자 %u로 출력하는 것이 맞다.
하지만 int형 변수에도 저장이 가능하기 때문에, strlen 함수의 반환 값을 int형 변수에 저장하고, 서식문자 %d로 출력하는 것도 가능하다 (오히려 더 많이 사용된다)
#include <stdio.h>
#include <string.h>
void RemoveBSN(char str[])
{
int len = strlen(str);
str[len - 1] = 0;
}
int main()
{
char str[100];
printf("문자열 입력 : ");
fgets(str, sizeof(str), stdin);
printf("길이 : %d, 내용 : %s \n", strlen(str), str);
RemoveBSN(str);
printf("길이 : %d, 내용 : %s \n", strlen(str), str);
return 0;
}
결과
문자열 입력 : hello
길이 : 6, 내용 : hello
길이 : 5, 내용 : hello
출력 결과를 보면 같은 것 같지만 개행을 보면 알 수 있다
첫 번째 출력에서는 아래에 개행이 두 번 이루어졌지만, 두 번째 출력에서는 개행이 한 번 이루어졌다.
이로써 \n
이 사라졌다는 것을 알 수 있다.
문자열을 복사하는 함수는 2개가 있다.
#include <stdio.h>
char * strcpy(char * dest, const char * src);
char * strncpy(char * dest, const char * src, size_t n);
// 복사된 문자열의 주소 값 반환
int main() {
char str1[30] = "Simple String";
char str2[30];
strcpy(str2, str1);
}
str1의 문자열을 str2에 복사된다.
int main() {
char str1[30] = "Simple String";
char str2[30];
strncpy(str2, str1, sizeof(str2));
}
strncpy는 앞에 strcpy보다 조금 의미가 길다.
str1의 문자열을 str2에 복사하는 것은 같지만, str1의 길이가 길다면 sizeof(str2)가 반환한 값에 해당하는 문자의 수 만큼만 복사를 진행한다.
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "1234567890";
char str2[20];
char str3[5];
// case 1
strcpy(str2, str1);
puts(str2);
// case 2
strncpy(str3, str1, sizeof(str3));
puts(str3);
// case 3
strncpy(str3, str1, sizeof(str3) - 1);
str3[sizeof(str3) - 1] = 0;
puts(str3);
return 0;
}
결과
1234567890
123451234567890
1234
결과를 보면 중간에 출력결과가 이상하다
case 2의 코드를 보면 str3의 길이만큼 5개의 문자(1,2,3,4,5)가 복사된다.
여기서 문제가 출력할때 널 문자가 있어야 널 문자 이전까지 출력하는데 널 문자가 없기 때문에 이상한 영역까지 출력하는 것이다.
그래서 strncpy는 case 3와 같이 사용해야 한다.
case 3를 보면 배열의 실제 길이보다 하나 작은 값을 전달해 널 문자가 삽입될 공간을 남겨두고 복사한 이후, 배열 끝에 널 문자를 삽입해야 한다.
위 두 함수는 문자열 뒤에 다른 문자열을 붙여넣는 기능을 한다.
#inlcude <stdio.h>
char * strcat(char * dest, const char * src);
char * strncat(char * dest, const char * src, size_t n);
// 덧붙여진 문자열의 주소 값 반환
int main() {
char str1[30] = "First~";
char str2[30] = "Second";
strcat(str1, str2);
}
함수를 호출하면 str1 뒤에 str2 문자열 뒤에 덧붙여진다
항상 문자열에는 널 문자가 있다. 덧붙이는 위치는 널 문자가 저장된 위치부터 붙여넣어진다
str1 : First~\0
str2 : Second\0
-----strcat-----
str1 : First~Second\0
strncat(str1, str2, 8);
str2의 문자열 중 최대 8개를 str1 뒤에 붙인다.
앞의 strncpy에서 봤듯이 길이가 길면 문자 8개에 널 문자는 포함되지 않는다.
하지만 strncat은 자동으로 널 문자를 입력해준다.
따라서 8개라고 설정했지만 실제로는 9개의 문자가 덧붙여지는 것이다.
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "First~";
char str2[20] = "Second";
char str3[20] = "Simple num : ";
char str4[20] = "1234567890";
// case 1
strcat(str1, str2);
puts(str1);
// case 2
strncat(str3, str4, 7);
puts(str3);
return 0;
}
결과
First~Second
Simple num : 1234567
위 함수를 설명하기 전에 아래 코드를 먼저 보자
int main() {
char str1[] = "My String";
char str2[] = "My String";
if (str1==str2)
puts("equal");
else
puts("not equal");
return 0;
}
위 코드는 배열 두 개를 서로 비교하고 있다.
겉 보기에는 문자열을 비교하는 것이기 때문에 equal
이 나올 것이라고 생각할 수 있다
하지만 배열의 이름은 배열의 주소를 의미하기 때문에, 위 코드는 배열의 내용이 아닌 주소를 비교하고, 주소값은 다르기 때문에 not equal
이 출력된다.
#include <stdio.h>
int strcmp(const cahr * s1, const char * s2);
int strncmp(const char * s1, const char * s2, size_t n);
// 두 문자열의 내용이 같으면 O, 같지 않으면 O가 아닌 값을 반환
두 함수는 모두 문자열의 내용을 비교해 다음 결과를 반환한다. 차이점이 있다면 strncmp 함수는 세 번째 매개변수로 주어진 길이 만큼만 문자를 비교한다.
크기는 아스키 코드를 기준으로 결정된다.
예를 들어
"ABCD"
"ABCC"
두 문자열이 있다면 'C'까지는 아스키 코드가 동일하지만 4번째 문자의 크기가 서로 다르다. 앞의 문자열이 더 크기 때문에 양수가 반환된다.
단, 여기서 양수와 음수가 반환되는 것만 정해져 있을 뿐 어떤 값이 반환되는지는 알 수 없다.
예시 코드를 보자
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20];
char str2[20];
printf("첫 번째 문자열 입력 : ");
scanf("%s", str1);
printf("두 번째 문자열 입력 : ");
scanf("%s", str2);
if (!strcmp(str1, str2))
{
puts("두 문자열은 동일하다");
}
else
{
puts("두 문자열은 다르다");
if (!strncmp(str1, str2, 3))
{
puts("버뜨 앞 세 글자는 동일");
}
}
return 0;
}
결과
첫 번째 문자열 입력 : Simple
두 번째 문자열 입력 : Simon
두 문자열은 다르다
버뜨 앞 세 글자는 동일
알아두면 나중에 쓸만한 함수들이다
이는 <stdlib.h>
헤더파일에 선언되어 있다.
int atoi(const char * str); // 문자열 int 변환
int atol(const char * str); // 문자열 long 변환
int atof(const char * str); // 문자열 double 변환
문자열로 표현된 정수나 실수를 사용할때 유용하게 쓸 수 있다.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[20];
printf("정수 입력 : ");
scanf("%s", str);
printf("%d \n", atoi(str));
printf("실수 입력 : ");
scanf("%s", str);
printf("%g \n", atof(str));
return 0;
}
결과
정수 입력 : 15
15
실수 입력 : 3.14
3.14
아주 간단하게 정수, 실수 변환을 할 수 있다.