C언어에서 문자열의 공백 제거는 데이터 전처리와 문자열 조작에서 필수적인 작업입니다. 공백이 포함된 문자열은 데이터 비교, 검색, 변환 과정에서 문제를 일으킬 수 있습니다. 본 기사에서는 기본적인 반복문 활용 방법부터 고급 라이브러리와 정규표현식까지 다양한 공백 제거 방법을 구체적인 코드 예제와 함께 다룹니다. 이로써 효율적이고 간단하게 공백 제거를 구현할 수 있는 실질적인 팁을 제공합니다.
공백 제거의 기본 개념
문자열에서 공백 제거는 데이터를 깔끔하게 정리하고 처리하기 위해 자주 필요한 작업입니다. 공백은 데이터 비교나 검색 과정에서 의도치 않은 오류를 일으킬 수 있기 때문에, 이를 적절히 처리하는 것이 중요합니다.
문자열에서 공백의 역할
공백은 문자열을 구분하거나 가독성을 높이는 데 유용하지만, 다음과 같은 문제를 유발할 수 있습니다.
- 데이터 비교 시 일치하지 않는 결과 발생
- 불필요한 공백으로 데이터 처리 속도 저하
- 입력값 유효성 검사 오류
공백 제거의 기본 원리
공백 제거의 핵심은 문자열 내 공백 문자를 식별하고 제거하여 새 문자열을 생성하는 것입니다.
- 순회 방식: 문자열의 각 문자를 확인하여 공백이 아닌 문자를 새로운 위치로 이동
- 문자열 분리 방식: 문자열을 공백 기준으로 분리한 뒤 재조합
이러한 방법을 활용하면 문자열을 효율적으로 정리하고 처리할 수 있습니다.
반복문을 활용한 공백 제거
반복문은 공백 제거를 구현하는 가장 기본적이고 직관적인 방법입니다. for문 또는 while문을 사용해 문자열을 순회하며 공백을 필터링합니다.
기본 알고리즘
- 원본 문자열을 한 글자씩 순회합니다.
- 공백이 아닌 문자를 새로운 문자열에 추가합니다.
- 순회가 끝나면 공백이 제거된 새 문자열이 완성됩니다.
코드 예제
#include <stdio.h>
#include <string.h>
void removeSpaces(char* source) {
int i, j = 0;
int len = strlen(source);
char result[len + 1]; // 공백 제거된 문자열 저장
for (i = 0; source[i] != '\0'; i++) {
if (source[i] != ' ') { // 공백이 아니면
result[j++] = source[i];
}
}
result[j] = '\0'; // 문자열 종료
strcpy(source, result); // 원본 문자열에 결과 복사
}
int main() {
char str[] = "C programming is fun!";
printf("Original: '%s'\n", str);
removeSpaces(str);
printf("Without spaces: '%s'\n", str);
return 0;
}
코드 설명
removeSpaces
함수는 문자열을 순회하며 공백이 아닌 문자를 새로운 배열에 저장합니다.- 순회가 끝난 후 결과를 원본 문자열에 복사합니다.
main
함수에서 테스트 문자열의 공백을 제거하여 결과를 출력합니다.
장점과 단점
- 장점: 간단하고 가볍게 구현 가능
- 단점: 문자열을 순회하며 새 배열을 생성하므로 메모리 사용량 증가
반복문을 활용한 공백 제거는 간단한 작업에 적합하며, 초보자에게도 이해하기 쉬운 방법입니다.
strtok() 함수의 활용
C언어의 표준 라이브러리 함수인 strtok()
를 사용하면 문자열을 공백을 기준으로 분리하고 재조합하여 공백을 제거할 수 있습니다. 이 방법은 간단하면서도 효율적으로 문자열 처리를 가능하게 합니다.
strtok() 함수 개요
strtok()
함수는 문자열을 특정 구분자로 나누는 데 사용됩니다. 구분자를 공백으로 설정하면 공백을 기준으로 문자열을 나눌 수 있습니다.
함수 선언:
char *strtok(char *str, const char *delim);
str
: 나눌 대상 문자열delim
: 구분자로 사용할 문자 집합
코드 예제
#include <stdio.h>
#include <string.h>
void removeSpaces(char* source) {
char* token;
char result[100] = ""; // 공백 제거된 문자열 저장
const char delim[2] = " "; // 공백 구분자
// 첫 번째 토큰 가져오기
token = strtok(source, delim);
while (token != NULL) {
strcat(result, token); // 결과 문자열에 추가
token = strtok(NULL, delim); // 다음 토큰 가져오기
}
strcpy(source, result); // 원본 문자열에 결과 복사
}
int main() {
char str[] = "C programming is fun!";
printf("Original: '%s'\n", str);
removeSpaces(str);
printf("Without spaces: '%s'\n", str);
return 0;
}
코드 설명
strtok
함수로 문자열을 공백 기준으로 나누어 각 토큰을 순차적으로 가져옵니다.- 각 토큰을 결과 문자열에 추가하여 공백 없이 재조합합니다.
- 결과를 원본 문자열에 복사하여 공백 제거 작업을 완료합니다.
장점과 단점
- 장점: 구현이 간단하며 라이브러리 함수로 처리 속도가 빠릅니다.
- 단점: 원본 문자열이 변경되며, 다중 스레드 환경에서는 사용하기 부적합합니다.
strtok()
를 활용한 공백 제거는 문자열을 재구성하는 데 효과적이며, 간단한 구현을 통해 빠르게 결과를 얻을 수 있는 방법입니다.
정규표현식과 외부 라이브러리 사용
정규표현식과 외부 라이브러리를 사용하면 문자열 공백 제거를 더욱 효율적이고 유연하게 처리할 수 있습니다. 이 방법은 대규모 데이터 처리나 복잡한 문자열 패턴 처리에 적합합니다.
정규표현식 활용의 이점
정규표현식은 특정 패턴을 탐지하고 대체하는 데 강력한 도구로, 문자열 내 모든 공백(연속 공백 포함)을 한 번에 처리할 수 있습니다.
PCRE 라이브러리를 활용한 예제
PCRE(Perl Compatible Regular Expressions) 라이브러리는 C언어에서 정규표현식을 사용할 수 있도록 지원합니다.
예제 코드
#include <stdio.h>
#include <string.h>
#include <pcre.h>
void removeSpacesWithRegex(char* source) {
const char* pattern = "\\s+"; // 모든 공백(스페이스, 탭 등)
const char* error;
int erroffset, ovector[30];
pcre* re;
re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
if (!re) {
printf("Regex compilation failed at offset %d: %s\n", erroffset, error);
return;
}
int rc = pcre_exec(re, NULL, source, strlen(source), 0, 0, ovector, 30);
if (rc >= 0) {
char result[100] = "";
int last_pos = 0;
for (int i = 0; i < rc; i++) {
int start = ovector[2 * i];
int end = ovector[2 * i + 1];
strncat(result, source + last_pos, start - last_pos);
last_pos = end;
}
strcat(result, source + last_pos);
strcpy(source, result);
}
pcre_free(re);
}
int main() {
char str[] = "C programming is fun!";
printf("Original: '%s'\n", str);
removeSpacesWithRegex(str);
printf("Without spaces: '%s'\n", str);
return 0;
}
코드 설명
- 정규표현식 정의:
\\s+
패턴은 하나 이상의 공백(스페이스, 탭 등)을 탐지합니다. - PCRE 컴파일: 정규표현식을 컴파일하여 실행 가능한 객체를 생성합니다.
- 공백 제거: 탐지된 공백 부분을 제외하고 문자열을 재구성합니다.
- 결과 출력: 공백이 제거된 문자열을 원본에 복사합니다.
장점과 단점
- 장점: 복잡한 문자열 패턴 처리 가능, 연속 공백 및 다양한 공백 문자 한 번에 처리
- 단점: PCRE와 같은 외부 라이브러리 설치 및 링크 필요, 초기 설정 복잡
정규표현식과 외부 라이브러리는 공백 제거뿐만 아니라 고급 문자열 조작에도 유용하며, 대규모 프로젝트에서 강력한 도구로 활용될 수 있습니다.
응용 예제: 파일 입출력에서의 공백 제거
파일 입출력 작업에서는 데이터를 읽어오고, 처리한 뒤 다시 저장하는 과정이 자주 필요합니다. 이 과정에서 공백 제거는 데이터 정리와 전처리 단계의 중요한 작업입니다. 아래 예제에서는 파일의 내용을 읽어와 공백을 제거하고, 결과를 새로운 파일에 저장하는 방법을 다룹니다.
코드 예제
#include <stdio.h>
#include <string.h>
void removeSpaces(char* source) {
int i, j = 0;
int len = strlen(source);
char result[len + 1]; // 공백 제거된 문자열 저장
for (i = 0; source[i] != '\0'; i++) {
if (source[i] != ' ') { // 공백이 아니면
result[j++] = source[i];
}
}
result[j] = '\0'; // 문자열 종료
strcpy(source, result); // 원본 문자열에 결과 복사
}
int main() {
FILE *inputFile, *outputFile;
char buffer[256];
// 입력 파일 열기
inputFile = fopen("input.txt", "r");
if (inputFile == NULL) {
printf("Error: Could not open input file.\n");
return 1;
}
// 출력 파일 열기
outputFile = fopen("output.txt", "w");
if (outputFile == NULL) {
printf("Error: Could not open output file.\n");
fclose(inputFile);
return 1;
}
// 파일 읽기, 공백 제거, 쓰기
while (fgets(buffer, sizeof(buffer), inputFile)) {
removeSpaces(buffer); // 공백 제거
fprintf(outputFile, "%s", buffer); // 결과 쓰기
}
// 파일 닫기
fclose(inputFile);
fclose(outputFile);
printf("File processed successfully. Check 'output.txt'.\n");
return 0;
}
코드 설명
- 파일 열기:
fopen()
을 사용해 입력 파일과 출력 파일을 엽니다. - 버퍼 읽기:
fgets()
로 파일에서 한 줄씩 데이터를 읽습니다. - 공백 제거:
removeSpaces
함수를 호출하여 읽어온 문자열의 공백을 제거합니다. - 결과 쓰기:
fprintf()
를 사용해 공백이 제거된 데이터를 출력 파일에 저장합니다. - 파일 닫기: 모든 파일을 닫아 메모리 누수를 방지합니다.
응용 가능성
- 데이터 정리: 로그 파일, 데이터 파일 등에서 불필요한 공백을 제거하여 처리 용이성 증가
- 포맷 통일: 데이터 형식 표준화
- 효율성 향상: 데이터 비교 및 검색 속도 개선
파일 입출력과 공백 제거를 결합한 이 예제는 실무에서 자주 활용되며, 텍스트 데이터의 품질을 높이는 데 매우 유용합니다.
요약
C언어에서 문자열의 공백 제거는 데이터를 정리하고 처리하기 위한 필수 기술입니다. 본 기사에서는 반복문, strtok()
함수, 정규표현식 및 외부 라이브러리 활용 방법을 다루었으며, 파일 입출력과의 응용 예제도 제시했습니다. 이러한 다양한 접근법을 통해 문자열 공백 제거 문제를 효율적으로 해결할 수 있습니다.