프로그래밍에서 문자는 단순한 기호 이상의 의미를 가진다. 특히 C 언어에서는 문자를 다룰 때 개별 문자와 문자열을 명확히 구분해야 한다. 이번 글에서는 C에서 문자와 문자열을 처리하는 방법을 알아보고, 포인터를 활용한 문자열 조작 기법까지 살펴본다.
1. 문자(Character)와 문자열(String)의 차이
C 언어에서는 개별 문자를 char형으로 다루고, 여러 개의 문자가 연속된 형태를 문자열이라고 한다.
char c = 'A'; // 하나의 문자
char str[] = "Hello"; // 문자열
위 예제에서 c는 단일 문자 'A'를 저장하는 변수이고, str은 "Hello"라는 문자열을 저장하는 문자 배열이다. 중요한 점은 문자열의 끝에는 항상 NULL 문자(``) 가 포함되어 있어야 한다는 것이다.
A. 문자열 저장 방식과 메모리 배치
문자는 메모리에 개별적으로 저장되지만, 문자열은 문자들이 연속된 형태로 저장된다.
char str1[] = "Hello";
char *str2 = "Hello";
- str1은 문자 배열로 선언되었기 때문에 배열의 각 요소를 개별적으로 변경할 수 있다.
- str2는 문자열 상수를 가리키는 포인터이며, 문자열 상수는 읽기 전용 영역(텍스트 세그먼트) 에 저장된다.
- 따라서 str1[0] = 'W';는 가능하지만, str2[0] = 'W';는 런타임 오류를 발생시킨다.
메모리 배치를 그림으로 나타내면 다음과 같다.
str1: | H | e | l | l | o | \0 | (데이터 세그먼트, 값 변경 가능)
str2: 주소 → "Hello" (텍스트 세그먼트, 읽기 전용)
문자열을 포인터로 다룰 때 이러한 차이를 반드시 이해해야 한다.
B. NULL 문자와 문자열 종료
C 언어에서 문자열의 끝을 나타내기 위해 NULL 문자(``) 가 필요하다. 이는 문자열을 올바르게 처리하기 위한 중요한 개념이다.
char str[] = {'H', 'e', 'l', 'l', 'o', '\0'};
- str의 마지막에는 반드시 \0이 포함되어야 문자열로 인식된다.
- printf("%s", str);을 사용하면 NULL 문자를 만날 때까지 출력된다.
- 만약 \0이 없다면 쓰레기 값이 포함될 수 있다.
C. 문자열 조작 함수
C에서는 문자열을 다룰 수 있는 다양한 표준 라이브러리 함수를 제공한다.
1) 문자열 복사 (strcpy)
char str1[10] = "Hello";
char str2[10];
strcpy(str2, str1); // str2에 str1의 내용 복사
2) 문자열 연결 (strcat)
char str1[20] = "Hello, ";
char str2[] = "World!";
strcat(str1, str2); // str1에 str2의 내용을 이어 붙임
3) 문자열 길이 (strlen)
char str[] = "Hello";
printf("문자열 길이: %d", strlen(str));
4) 문자열 비교 (strcmp)
char str1[] = "abc";
char str2[] = "def";
if (strcmp(str1, str2) == 0) {
printf("문자열이 같습니다.");
} else {
printf("문자열이 다릅니다.");
}
D. 포인터와 문자열
문자열을 처리할 때 포인터를 사용하면 보다 효율적인 코드를 작성할 수 있다.
char *str = "Hello";
printf("%s", str);
포인터를 활용하면 문자열을 동적으로 할당할 수도 있다.
char *str = (char*)malloc(20);
strcpy(str, "Dynamic String");
printf("%s", str);
free(str);
이처럼 문자열을 다룰 때는 배열과 포인터의 차이를 이해하고, 적절한 방식으로 데이터를 관리하는 것이 중요하다.
2. C 언어 문자 및 문자열 입출력 라이브러리 정리
A. 문자 입출력 라이브러리
1) 문자 입력 함수
C 언어에서는 기본적으로 scanf()와 같은 함수를 이용하여 문자를 입력받을 수 있지만, 더 간단하고 직관적인 입력 함수들이 제공된다.
함수 | 설명 |
int getchar(void) | 한 개의 문자를 입력받아 반환한다 (버퍼 사용). |
void putchar(int c) | 한 개의 문자를 출력한다. |
int _getch(void) | 입력된 문자를 버퍼 없이 즉시 반환한다. |
void _putch(int c) | 버퍼 없이 한 개의 문자를 출력한다. |
2) getchar()와 putchar() 사용 예제
#include <stdio.h>
int main() {
char ch;
printf("문자 입력: ");
ch = getchar();
printf("입력한 문자: ");
putchar(ch);
return 0;
}
getchar()는 엔터를 입력해야 동작하지만, _getch()는 입력 즉시 동작하여 키보드 입력을 실시간으로 처리할 때 유용하다.
B. 문자열 입출력 라이브러리
1) 문자열 입력 및 출력 함수
함수 | 설명 |
int scanf("%s", str); | 공백을 기준으로 한 단어를 입력받아 저장. |
int printf("%s", str); | 문자열을 출력. |
char *gets_s(char *str, int size); | 한 줄 전체를 입력받아 저장. |
int puts(const char *str); | 문자열을 출력하고 개행 문자 추가. |
2) scanf()와 gets_s() 비교
#include <stdio.h>
int main() {
char name[100];
printf("이름을 입력하세요: ");
gets_s(name, sizeof(name));
printf("안녕하세요, %s님!\n", name);
return 0;
}
gets_s()는 공백을 포함한 전체 입력을 받을 수 있지만, scanf("%s", str)는 공백을 기준으로 잘린다.
C. 문자 처리 라이브러리
1) 문자 검사 함수
C 언어에서는 특정 문자들이 대문자인지, 숫자인지 등을 검사하는 함수를 제공한다.
함수 | 설명 |
isalpha(c) | 영문자 여부 (A-Z, a-z) 확인 |
isdigit(c) | 숫자인지 확인 (0-9) |
isspace(c) | 공백 문자 여부 확인 |
isupper(c) | 대문자 여부 확인 |
islower(c) | 소문자 여부 확인 |
2) 문자 변환 함수
함수 | 설명 |
toupper(c) | 소문자를 대문자로 변환 |
tolower(c) | 대문자를 소문자로 변환 |
3) 문자 검사 및 변환 예제
#include <stdio.h>
#include <ctype.h>
int main() {
char ch;
printf("문자 입력: ");
ch = getchar();
if (islower(ch)) {
ch = toupper(ch);
}
printf("변환된 문자: %c\n", ch);
return 0;
}
이 코드는 사용자가 소문자를 입력하면 대문자로 변환하여 출력하는 프로그램이다.
D. 문자열 처리 응용
1) 단어 개수 세기 프로그램
#include <stdio.h>
#include <ctype.h>
int count_words(char *s) {
int i, wc = 0, waiting = 1;
for (i = 0; s[i] != '\0'; i++) {
if (isalpha(s[i]) && waiting) {
wc++;
waiting = 0;
} else if (!isalpha(s[i])) {
waiting = 1;
}
}
return wc;
}
int main() {
char str[] = "Hello world, this is C programming!";
printf("단어 개수: %d\n", count_words(str));
return 0;
}
이 프로그램은 공백이나 특수 문자를 기준으로 문자열 속 단어 개수를 세는 기능을 한다.
3. C 언어 문자열 처리 라이브러리 함수 정리
A. 문자열 처리의 중요성
C 언어에서 문자열은 단순한 문자들의 집합이 아니라, 프로그램의 데이터 처리와 입력/출력에서 중요한 역할을 한다. 하지만 C 언어에서는 기본적으로 문자열을 다루는 전용 자료형이 없으며, 대신 char 배열과 포인터를 이용해야 한다. 이를 효율적으로 처리하기 위해 표준 라이브러리에서 문자열을 다루는 다양한 함수들을 제공한다.
B. 문자열 관련 라이브러리 string.h
C 언어에서 문자열을 다루려면 반드시 string.h 헤더 파일을 포함해야 합니다. string.h에는 문자열의 길이 계산, 복사, 연결, 비교, 검색, 토큰 분리 등 여러 기능을 수행하는 함수들이 포함되어 있습니다.
#include <string.h>
C. 문자열 길이 계산
strlen() 함수
문자열의 길이를 구할 때 사용됩니다. NULL(\0) 문자를 제외한 문자 개수를 반환합니다.
int length = strlen("Hello"); // 결과: 5
D. 문자열 복사 및 연결
strcpy() 함수
문자열을 다른 문자열로 복사할 때 사용됩니다. 복사할 대상(dst)이 충분한 크기를 가져야 합니다.
char dst[10];
strcpy(dst, "Hello");
strncpy() 함수
특정 개수의 문자만 복사하고 싶다면 strncpy()를 사용합니다.
char dst[10];
strncpy(dst, "Hello", 3); // dst에 "Hel"만 복사됨
strcat() 함수
두 개의 문자열을 하나로 연결할 때 사용됩니다. 기존 문자열의 끝에 새로운 문자열을 추가합니다.
char dst[20] = "Hello";
strcat(dst, " World");
// 결과: "Hello World"
strncat() 함수
특정 개수의 문자만 추가할 경우 사용됩니다.
char dst[20] = "Hello";
strncat(dst, " World", 3); // 결과: "Hello Wor"
E. 문자열 비교
strcmp() 함수
두 문자열을 비교하여 같은 경우 0, 첫 번째 문자열이 크면 양수, 두 번째 문자열이 크면 음수를 반환합니다.
int result = strcmp("apple", "banana"); // 결과: 음수
strncmp() 함수
문자열의 앞부분 일부만 비교할 경우 사용됩니다.
int result = strncmp("apple", "apricot", 3); // 결과: 0 (앞 3문자가 같음)
F. 문자열 검색
strchr() 함수
특정 문자가 문자열 내에서 처음 등장하는 위치를 찾습니다.
char *p = strchr("Hello", 'e'); // 결과: 'e'의 주소 반환
strstr() 함수
부분 문자열(서브스트링)을 검색하여 처음 등장하는 위치를 반환합니다.
char *p = strstr("Hello World", "World"); // "World"의 시작 주소 반환
G. 문자열 토큰 분리
strtok() 함수
문자열을 특정 구분자(delimiter)를 기준으로 나누는 함수입니다.
char str[] = "Hello,World";
char *token = strtok(str, ",");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ",");
}
// 결과:
// Hello
// World
4.C 언어의 문자열 및 문자 처리 라이브러리 활용
A. 문자 입출력 라이브러리
getchar()와 putchar()
C 언어에서 한 문자씩 입력받거나 출력할 때 getchar()와 putchar() 함수를 사용할 수 있다.
#include <stdio.h>
int main(void) {
int ch;
printf("문자를 입력하세요: ");
ch = getchar(); // 한 문자 입력
printf("입력한 문자: ");
putchar(ch); // 입력한 문자 출력
return 0;
}
getch()와 getche()
getch()와 getche() 함수는 <conio.h> 헤더 파일을 포함해야 하며, 버퍼를 사용하지 않아 입력한 문자가 바로 전달된다.
#include <conio.h>
#include <stdio.h>
int main(void) {
char ch;
printf("문자를 입력하세요: ");
ch = getch(); // 입력한 문자가 화면에 표시되지 않음
printf("\n입력한 문자: ");
putchar(ch);
return 0;
}
B. 문자열 입출력 라이브러리
scanf()와 printf()를 이용한 문자열 입출력
문자열을 입력받고 출력할 때 scanf()와 printf()를 사용할 수 있다.
#include <stdio.h>
int main(void) {
char name[50];
printf("이름을 입력하세요: ");
scanf("%s", name);
printf("안녕하세요, %s님!\n", name);
return 0;
}
하지만 scanf("%s", name);은 공백을 포함한 문자열을 입력받을 수 없기 때문에 gets_s()를 사용하는 것이 좋다.
#include <stdio.h>
int main(void) {
char sentence[100];
printf("한 줄의 문장을 입력하세요: ");
gets_s(sentence, sizeof(sentence));
printf("입력된 문장: %s\n", sentence);
return 0;
}
C. 문자열 처리 라이브러리
문자열 길이 계산: strlen()
strlen() 함수는 문자열의 길이를 계산할 때 사용된다.
#include <stdio.h>
#include <string.h>
int main(void) {
char str[] = "Hello, World!";
printf("문자열의 길이: %lu\n", strlen(str));
return 0;
}
문자열 복사와 연결: strcpy()와 strcat()
#include <stdio.h>
#include <string.h>
int main(void) {
char src[] = "C programming";
char dest[50];
strcpy(dest, src);
strcat(dest, " is fun!");
printf("%s\n", dest);
return 0;
}
문자열 비교: strcmp()
문자열을 비교할 때는 strcmp()를 사용하며, 사전순 정렬을 기준으로 값이 반환된다.
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[] = "apple";
char str2[] = "banana";
if (strcmp(str1, str2) < 0) {
printf("%s이 %s보다 앞에 있습니다.\n", str1, str2);
} else {
printf("%s이 %s보다 뒤에 있습니다.\n", str1, str2);
}
return 0;
}
D. 문자열을 숫자로 변환
문자열을 정수나 실수로 변환할 때는 atoi()와 atof()를 사용한다.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char numStr[] = "123";
int num = atoi(numStr);
printf("정수 변환: %d\n", num);
return 0;
}
E. 2차원 문자 배열과 문자열 저장
2차원 문자 배열을 이용한 문자열 저장
#include <stdio.h>
int main(void) {
char words[3][10] = {"Hello", "World", "C"};
for (int i = 0; i < 3; i++) {
printf("%s\n", words[i]);
}
return 0;
}
문자열 포인터 배열 사용
#include <stdio.h>
int main(void) {
char *words[] = {"Hello", "World", "C"};
for (int i = 0; i < 3; i++) {
printf("%s\n", words[i]);
}
return 0;
}
F. 간단한 사전 프로그램 (문자열 검색)
사전처럼 단어를 저장하고 검색하는 프로그램을 만들 수 있다.
#include <stdio.h>
#include <string.h>
#define WORDS 3
int main(void) {
char dic[WORDS][2][30] = {
{"apple", "사과"},
{"banana", "바나나"},
{"cherry", "체리"}
};
char word[30];
printf("단어를 입력하세요: ");
scanf("%s", word);
for (int i = 0; i < WORDS; i++) {
if (strcmp(dic[i][0], word) == 0) {
printf("%s: %s\n", word, dic[i][1]);
return 0;
}
}
printf("사전에 단어가 없습니다.\n");
return 0;
}
이처럼 C 언어에서는 다양한 문자열 및 문자 입출력 관련 라이브러리를 활용하여 효율적인 문자열 처리 프로그램을 만들 수 있다.
'XR개발 > C언어' 카테고리의 다른 글
C 오답노트02_산술연산자 & 선택제어문(조건문) (0) | 2025.03.19 |
---|---|
C오답노트01_출력과 입력 (0) | 2025.03.19 |
C언어 포인터 (0) | 2025.03.01 |
C언어 배열 (2) | 2025.02.28 |
10_Q&A 함수원형에 대한 물음.zip (0) | 2025.02.16 |