[P4C] C언어 코딩 도장 : UNIT 41 ~ UNIT 44
Unit 41. 문자열의 길이를 구하고 비교하기
41.1 문자열 길이 구하기
문자열의 길이는 strlen 함수로 구할 수 있다. (string.h 헤더 파일에 선언되어 있음).
- strlen(문자열포인터);
- strlen(문자배열);
#include <stdio.h>
#include <string.h> // strlen 함수가 선언된 헤더 파일
int main()
{
char *s1 = "Hello"; // 포인터에 문자열 Hello의 주소 저장
char s2[10] = "Hello"; // 크기가 10인 char형 배열을 선언하고 문자열 할당
printf("%d\n", strlen(s1)); // 5: strlen 함수로 문자열의 길이를 구함
printf("%d\n", strlen(s2)); // 5: strlen 함수로 문자열의 길이를 구함
return 0;
}
strlen(s1)와 같이 strlen 함수에 문자열 포인터를 넣으면 문자열의 길이가 반환된다.
strlen(s2)와 같이 strlen 함수에 문자열이 들어있는 배열을 넣으면 배열 안에 들어있는 문자열의 길이가 반환된다.
마찬가지로 strlen 함수는 순수하게 문자열의 길이만 구하며 NULL 부분은 포함하지 않는다. 특히 배열의 크기는 문자열의 길이와 전혀 상관이 없어, 배열의 크기가 크던 작던 문자열의 길이만 구한다.
41.2 문자열 비교하기
strcmp 함수를 사용하면 두 문자열이 같은지 비교할 수 있다. (string.h 헤더 파일에 선언되어 있음).
- strcmp(문자열1, 문자열2);
#include <stdio.h>
#include <string.h> // strcmp 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "Hello";
char *s2 = "Hello";
int ret = strcmp(s1, s2); // 두 문자열이 같은지 문자열 비교
printf("%d\n", ret); // 0: 두 문자열이 같으면 0
return 0;
}
strcmp(s1, s2);와 같이 strcmp 함수에 비교할 문자열을 넣어주면 결과를 정수로 반환한다(문자열을 비교할 때 대소문자를 구분함).
- -1: ASCII 코드 기준으로 문자열2(s2)가 클 때
- 0: ASCII 코드 기준으로 두 문자열이 같을 때
- 1: ASCII 코드 기준으로 문자열1(s1)이 클 때
여기서는 s1과 s2의 문자열이 같으므로 0을 반환한다. 그리고 배열 형태의 문자열, 문자열 포인터 등 문자열의 저장 방식은 문자열 비교에 영향을 주지 않는다.
※ strcmp 함수는 운영체제에 따라서 동작 방식이 조금 다르다. Windows(Visual Studio)에서는 문자열이 다르면 1과 -1을 반환하지만 리눅스와 OS X에서는 ASCII 코드값의 차이를 반환한다.
Unit 42. 문자열을 복사하고 붙이기
42.1 문자열 복사하기
문자열은 다른 배열이나 포인터(메모리)로 복사할 수 있다. strcpy 함수는 문자열을 다른 곳으로 복사한다(string.h 헤더 파일에 선언되어 있음).
- strcpy(대상문자열, 원본문자열);
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "Hello"; // 크기가 10인 char형 배열을 선언하고 문자열 할당
char s2[10]; // 크기가 10인 char형 배열을 선언
strcpy(s2, s1); // s1의 문자열을 s2로 복사
printf("%s\n", s2); // Hello
return 0;
}
먼저 "Hello" 문자열이 들어있는 배열 s1과 아무것도 들어있지 않은 배열 s2를 선언했다. 그리고 strcpy(s2, s1)와 같이 strcpy 함수에 복사된 결과가 저장될 문자열과 복사할 문자열을 넣는다. 이렇게 하면 s2에 s1의 문자열이 복사된다.
※ strcpy로 문자열 포인터에 복사할 경우 문자열 리터럴이 저장된 메모리는 읽기 전용 메모리이기 때문에 복사가 되지 않는다.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 정의된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char *s1 = "hello"; // 문자열 포인터
char *s2 = malloc(sizeof(char) * 10); // char 10개 크기만큼 동적 메모리 할당
strcpy(s2, s1); // s1의 문자열을 s2로 복사
printf("%s\n", s2); // Hello
free(s2); // 동적 메모리 해제
return 0;
}
문자열 포인터에 문자열을 복사하려면 문자열이 들어갈 공간을 따로 마련해야 된다. 따라서 다음과 같이 malloc 함수로 메모리를 할당한 뒤 문자열을 복사한다.
42.2 문자열 붙이기
문자열은 strcat 함수를 사용하여 서로 붙일 수 있으며 함수 이름은 문자열을 연결시키다(string concatenate)에서 따왔다(string.h 헤더 파일에 선언되어 있음).
- strcat(최종문자열, 붙일문자열);
#define _CRT_SECURE_NO_WARNINGS // strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcat 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "world";
char s2[20] = "Hello"; // s2 뒤에 붙일 것이므로 배열 크기를 크게 만듦
strcat(s2, s1); // s2 뒤에 s1를 붙임
printf("%s\n", s2); // Helloworld
return 0;
}
strcat(s2, s1)과 같이 strcat 함수에 최종 결과가 나올 문자열과 붙일 문자열을 넣는다. 이렇게 하면 s2 뒤에 s1를 붙여서 Helloworld가 나온다.
여기서 주의할 부분은 최종 결과가 나올 문자열의 배열 크기이다. 문자열을 붙이더라도 배열이 모자라지 않도록 크기를 넉넉하게 만든다(NULL까지 들어갈 수 있도록).
※ 문자열 포인터의 경우 포인터가 가르키는 문자열 리터럴이 읽기 전용 메모리이기 때문에 strcat 함수로 문자열을 붙일 수 없다.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcat 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char *s1 = "world"; // 문자열 포인터
char *s2 = malloc(sizeof(char) * 20); // char 20개 크기만큼 동적 메모리 할당
strcpy(s2, "Hello"); // s2에 Hello 문자열 복사
strcat(s2, s1); // s2 뒤에 s1을 붙임
printf("%s\n", s2); // Helloworld
free(s2); // 동적 메모리 해제
return 0;
}
-> 문자열을 붙이려면 s2에 쓰기가 가능하도록 malloc 함수로 동적 메모리를 할당하고, 문자열을 붙일 수 있도록 공간도 넉넉하게 20으로 설정해준다.
42.3 배열 형태의 문자열을 문자열 포인터에 복사하기
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "Hello"; // 크기가 10인 char형 배열을 선언하고 문자열 할당
char *s2 = malloc(sizeof(char) * 10); // char 10개 크기만큼 동적 메모리 할당
strcpy(s2, s1); // s1의 문자열을 s2로 복사
printf("%s\n", s2); // Hello
free(s2); // 동적 메모리 해제
return 0;
}
이번에는 배열 형태의 문자열을 문자열 포인터에 복사해보겠다.
먼저 malloc 함수로 s2에 메모리를 할당한다. 당연히 할당할 메모리 공간은 복사될 문자열보다 커야 할 것이다. 그리고 strcpy 함수로 s1의 문자열을 s2에 복사하면 된다.
42.4 배열 형태의 문자열을 문자열 포인터에 붙이기
#define _CRT_SECURE_NO_WARNINGS // strcpy, strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy, strcat 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "world"; // 크기가 10인 char형 배열을 선언하고 문자열 할당
char *s2 = malloc(sizeof(char) * 20); // char 20개 크기만큼 동적 메모리 할당
strcpy(s2, "Hello"); // s2에 Hello 문자열 복사
strcat(s2, s1); // s2 뒤에 s1을 붙임
printf("%s\n", s2); // Helloworld
free(s2); // 동적 메모리 해제
return 0;
}
이번에는 배열 형태의 문자열을 문자열 포인터에 붙여보겠다.
문자열 포인터 s2 뒤에 문자열을 붙일 것이므로 먼저 malloc 함수로 메모리를 할당한다. 문자열이 더 붙더라도 메모리가 모자라지 않도록 넉넉하게 할당한다. 그리고 strcpy 함수로 s2에 "Hello" 문자열을 복사해준다.
s2가 준비되었으면 strcat 함수로 문자열 포인터 s2 뒤에 문자열 포인터 s1을 붙이면 된다. 그리고 문자열 사용이 끝났다면 반드시 free 함수로 동적 할당한 메모리를 해제한다.
Unit 43. 문자열 만들기
43.1 서식을 지정하여 배열 형태로 문자열 만들기
지금까지 사용한 printf 함수로는 문자열을 화면에만 출력 할 수 있었다.
sprintf 함수를 사용하면 서식(format)을 지정하여 문자열을 만들고 저장할 수 있다(stdio.h 헤더 파일에 선언되어 있음).
- sprintf(배열, 서식, 값);
- sprintf(배열, 서식, 값1, 값2, ...);
#define _CRT_SECURE_NO_WARNINGS // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h> // sprintf 함수가 선언된 헤더 파일
int main()
{
char s1[20]; // 크기가 20인 char형 배열을 선언
sprintf(s1, "Hello, %s", "world!"); // "Hello, %s"로 서식을 지정하여 s1에 저장
printf("%s\n", s1); // Hello, world!: 문자열 s1 출력
return 0;
}
sprintf(s1, "Hello, %s", "world!");처럼 sprintf 함수에 문자열을 저장할 배열과 문자열을 만들 서식 그리고 문자열을 만들 값(문자열)을 순서대로 넣는다. 이렇게 하면 "Hello, %s"에서 서식 지정자 %s 부분이 "world!"로 바뀌면서 s1에 "Hello, world!"가 저장된다.
보통 s1과 같이 문자열을 저장할 빈 배열을 버퍼(buffer)라고 부른다.
서식 지정자를 사용할 수 있는 만큼 C 언어의 다양한 값(자료형)도 문자열로 만들 수 있을 것이다.
43.2 서식을 지정하여 문자열 포인터에 문자열 만들기
지금까지 배열 형태로 문자열을 만들었다. 이번에는 문자열 포인터에 문자열을 만들어보겠다. 문자열 포인터를 사용하려면 먼저 malloc 함수로 메모리를 할당한 뒤 sprintf 함수로 문자열을 만들면 된다.
- sprintf(문자열포인터, 서식, 값);
- sprintf(문자열포인터, 서식, 값1, 값2, …);
#define _CRT_SECURE_NO_WARNINGS // sprintf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h> // sprintf 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char *s1 = malloc(sizeof(char) * 20); // char 20개 크기만큼 동적 메모리 할당
sprintf(s1, "Hello, %s", "world!"); // "Hello, %s"로 서식을 지정하여 s1에 저장
printf("%s\n", s1); // Hello, world!: 문자열 s1 출력
free(s1); // 동적 메모리 해제
return 0;
}
char *s1 = malloc(sizeof(char) * 20);처럼 char 20개 크기만큼 동적으로 메모리를 할당했다. 그리고 sprintf 함수에 서식을 지정하여 문자열을 만들면 된다. 배열과 마찬가지로 s1과 같이 문자열을 생성할 메모리 공간도 버퍼이다.
문자열 사용이 끝났다면 반드시 free 함수로 동적 할당한 메모리를 해제한다. 즉, 문자열 포인터 사용은 항상 malloc, 사용, free 패턴이다.
Unit 44. 문자열 검색하기
44.1 문자열 안에서 문자로 검색하기
먼저 문자열에서 특정 문자로 검색하는 방법이다. strchr 함수를 사용하면 문자열에서 특정 문자로 검색할 수 있으며 함수 이름은 string character에서 따왔다(string.h 헤더 파일에 선언되어 있음).
- strchr(대상문자열, 검색할문자);
#include <stdio.h>
#include <string.h> // strchr 함수가 선언된 헤더 파일
int main()
{
char s1[30] = "A Garden Diary"; // 크기가 30인 char형 배열을 선언하고 문자열 할당
char *ptr = strchr(s1, 'a'); // 'a'로 시작하는 문자열 검색, 포인터 반환
while (ptr != NULL) // 검색된 문자열이 없을 때까지 반복
{
printf("%s\n", ptr); // 검색된 문자열 출력
ptr = strchr(ptr + 1, 'a'); // 포인터에 1을 더하여 a 다음부터 검색
}
return 0;
}
실행 결과는 다음과 같다.
arden Diary
ary
strchr 함수에 문자열과 검색할 문자를 넣어주면 해당 문자로 시작하는 문자열의 위치(포인터)를 반환한다.
문자열 안에 'a'로 시작하는 부분을 더 찾으려면 while 반복문을 사용하여 검색된 문자열의 포인터를 strchr 함수에 계속 넣어서 반복한다. NULL이 나오면 더 이상 검색된 문자열이 없으므로 반복을 끝낸다.
44.2 문자열의 오른쪽 끝부터 문자로 검색하기
strchr 함수는 문자열의 처음부터 문자를 검색해서 반환하지만 strrchr함수는 문자열의 끝에서부터 문자를 검색한다(string.h 헤더 파일에 선언되어 있음).
- strrchr(대상문자열, 검색할문자);
#include <stdio.h>
#include <string.h> // strrchr 함수가 선언된 헤더 파일
int main()
{
char s1[30] = "A Garden Diary"; // 크기가 30인 char형 배열을 선언하고 문자열 할당
char *ptr = strrchr(s1, 'a'); // 문자열 끝에서부터 'a'로 시작하는 문자열 검색. 포인터 반환
printf("%s\n", ptr); // ary
return 0;
}
char *ptr = strrchr(s1, 'a');와 같이 strrchr 함수에 문자열과 검색할 문자를 넣어주면 문자열 끝에서부터 검색하여 'a'로 시작하는 문자열의 포인터를 반환한다. "A Garden Diary"라면 "ary"의 포인터를 반환한다. 즉, 가장 마지막에 있는 문자열을 찾는다.
44.3 문자열 안에서 문자열로 검색하기
이번에는 문자열 안에서 문자열로 검색하는 방법을 알아보겠다. strstr 함수는 문자열 안에서 문자열을 검색한다(string.h 헤더 파일에 선언되어 있습니다).
- strstr(대상문자열, 검색할문자열);
#include <stdio.h>
#include <string.h> // strstr 함수가 선언된 헤더 파일
int main()
{
char s1[30] = "A Garden Diary"; // 크기가 30인 char형 배열을 선언하고 문자열 할당
char *ptr = strstr(s1, "den"); // den으로 시작하는 문자열 검색, 포인터 반환
printf("%s\n", ptr); // den Diary
return 0;
}
char *ptr = strstr(s1, "den");와 같이 strstr 함수에 문자열과 검색할 문자열을 넣어주면 해당 문자열로 시작하는 문자열의 위치(포인터)를 반환한다. 여기서는 "A Garden Diary"에서 "den"로 시작하는 문자열을 찾으므로 "den Diary"가 나온다. 즉, 검색한 문자 "den"만 나오지 않고 뒤에 오는 모든 문자열이 나온다(NULL이 나오기 전까지).
+ strchr 함수처럼 strstr 함수도 while 반복문을 사용하여 문자열을 계속 검색할 수 있다.
char s1[100] = "A Garden Diary A Garden Diary A Garden Diary";
char *ptr = strstr(s1, "den"); // den으로 시작하는 문자열 검색, 포인터 반환
while (ptr != NULL) // 검색된 문자열이 없을 때까지 반복
{
printf("%s\n", ptr); // 검색된 문자열 출력
ptr = strstr(ptr + 1, "den"); // den 포인터에 1을 더하여 e부터 검색
}
실행 결과는 다음과 같다.
den Diary A Garden Diary A Garden Diary
den Diary A Garden Diary
den Diary