문자열 관련 함수

ROK·2022년 7월 22일
0

C언어에는 문자열과 관련된 다양한 함수가 있다.

string.h 헤더파일에 선언된 문자열 관련 함수 중 사용 빈도가 높은 함수를 알아보자

문자열 길이 반환 함수 : strlen

가장 많이 사용되는 문자열 길이 반환 함수이다.

#include <stdio.h>
size_t strlen(const char * s);
// 전달된 문자열의 길이를 반환하되, 널 문자는 길이에 포함하지 않음

처음보는게 나왔다 size_ttypedef unsigned int size_t;와 같이 선언되어 있다.

쉽게 설명하면 typedef 선언으로 인해서 size_tunsigned int를 대신할 수 있게 된다.

size_t len;
unsigned int len;

위 두 선언은 동일하다

strlen의 호출 방법

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이 사라졌다는 것을 알 수 있다.

문자열을 복사하는 함수들 : strcpy, strncpy

문자열을 복사하는 함수는 2개가 있다.

#include <stdio.h>
char * strcpy(char * dest, const char * src);
char * strncpy(char * dest, const char * src, size_t n);
// 복사된 문자열의 주소 값 반환

함수 호출 방법 : strcpy

int main() {
	char str1[30] = "Simple String";
    char str2[30];
    strcpy(str2, str1);
}

str1의 문자열을 str2에 복사된다.

함수 호출 방법 : strncpy

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를 보면 배열의 실제 길이보다 하나 작은 값을 전달해 널 문자가 삽입될 공간을 남겨두고 복사한 이후, 배열 끝에 널 문자를 삽입해야 한다.

문자열을 덧붙이는 함수들 : strcat, strncat

위 두 함수는 문자열 뒤에 다른 문자열을 붙여넣는 기능을 한다.

#inlcude <stdio.h>
char * strcat(char * dest, const char * src);
char * strncat(char * dest, const char * src, size_t n);
// 덧붙여진 문자열의 주소 값 반환

함수를 호출 방법 : strcat

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

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

문자열을 비교하는 함수들 : strcmp, strncmp

위 함수를 설명하기 전에 아래 코드를 먼저 보자

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 함수는 세 번째 매개변수로 주어진 길이 만큼만 문자를 비교한다.

  • s1이 더 크면 0보다 큰 값 반환 // 양수 반환
  • s2가 더 크면 0보다 작은 값 반환 // 음수 반환
  • s1, s2 같으면 0 반환

크기는 아스키 코드를 기준으로 결정된다.

예를 들어
"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
두 문자열은 다르다
버뜨 앞 세 글자는 동일

변환 함수 etc

알아두면 나중에 쓸만한 함수들이다
이는 <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 

아주 간단하게 정수, 실수 변환을 할 수 있다.

profile
하루에 집중하자

0개의 댓글