C언어 알고리즘
C언어 포인터를 활용한 문자열 관련 함수(strcpy, strcat, strcmp, strncmp, strlen) 직접 구현하기
C's everything!
2022. 5. 20. 14:01
반응형
<string.h> 헤더 파일에 내장되어 있는 함수이지만, 포인터를 활용해보기 위해서 문자열 함수들을 직접 구현했습니다. 포인터에 대한 깊은 이해를 원하시는 분은 제 소스를 기반으로 본인만의 코드 스타일로 바꿔보시면 좋을 것 같습니다.
소스를 보시다가 scanf 함수 안에 ^'\n' 이라는 생소한 문법이 있습니다. 이것은 '개행문자를 만날 때까지 문자를 입력받겠다' 라는 뜻입니다. scanf 함수는 공백문자나 개행문자를 입력 받으면 입력이 종료되는 방식인데, ^'\n' 속성을 지정해주면 공백문자도 입력으로 취급해서 문자열에 공백 입력이 가능하게 됩니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
void strcopy(char* origin, char* task) { // 문자열 복사 함수
int i = 0; // origin과 task배열의 인덱스
while (*(task + i) != '\0') { // task배열의 마지막 원소인 null문자를 만날 때까지 반복
*(origin + i) = *(task + i); // task배열의 i번째 요소의 값을 origin배열의 i번째 요소에 복사한다.
i++; // 다음 요소의 복사를 위해 인덱스를 1 증가시킨다.
}
*(origin + i) = '\0'; // 반복이 끝나고 origin배열의 끝에 null문자를 넣어준다.
}
void strcate(char* origin, char* task) { // 문자열 연결 함수
int i = 0; // 원본 배열의 인덱스
while (*(origin + i) != 0) // origin배열의 마지막 원소인 null문자를 만날 때까지 반복
i++;
int j = 0; // 원본 배열과 연결할 배열의 인덱스
while (*(task + j) != 0) { // task배열의 마지막 원소인 null문자를 만날 때까지 반복
*(origin + i) = *(task + j); // task배열의 j번째 요소의 값을 origin배열의 i번째 요소에 이어서 연결한다.
j++, i++; // 다음 요소의 복사를 위해 인덱스를 1 증가시킨다.
}
*(origin + i) = '\0'; // 반복이 끝나고 origin배열의 끝에 null문자를 넣어준다.
}
int strcompare(char* origin, char* task) { // 문자열 비교 함수
int i = 0, j = 0; // 원본 배열 인덱스, task 배열 인덱스
while (1) {
if (*(origin + i) != *(task + j)) // 두 요소가 같지 않을 때
return *(origin + i) > *(task + j) ? 1 : -1; // 왼쪽이 더 크면 1 , 오른쪽이 더 크면 -1을 리턴한다.
if (!(*(origin + i))) // 널 문자를 만날 때까지 문자열이 같다면 0을 리턴한다.
return 0;
i++, j++; // 다음 요소도 같은지 비교하기 위해 인덱스를 1 증가시킨다.
}//while
}
int strNcompare(char* origin, char* task, int n) { // 길이 n까지 문자열 비교 함수
int j = 0; // task배열 인덱스
for (int i = 0; i < n; i++) {
if (*(origin + i) != *(task + j)) // 두 요소가 같지 않을 때
return *(origin + i) > *(task + j) ? 1 : -1; // 왼쪽이 더 크면 1 , 오른쪽이 더 크면 -1을 리턴한다.
j++; // task배열 인덱스도 증가시켜준다.
}
return 0; // 두 요소가 모두 일치해서 for문을 모두 반복하고 나왔다면 0을 리턴한다.
}
int strLen(char* origin) {
int len = 0; // 길이 추출을 위한 변수
int i = 0; // origin배열 인덱스
while (*(origin + i) != '\0') { // origin이 null문자를 만날 때까지 반복
if (*(origin + i) >= 0 && *(origin + i) <= 127) // 아스키코드 값 범위 내에 있으면 길이 1증가
len++, i++;
else // 특수문자 범위에 속하면 길이 2증가
len += 2, i += 2; // 2바이트이므로 배열 인덱스 2개를 차지한다.
}
return len; // 추출된 문자열 길이를 리턴한다.
}
int main() {
char origin[60]; // 원본 문자열
char task[30]; // 원본 문자열과 연결 or 복사 or 비교할 문자열
// 문자열 복사 부분
printf(" origin에 복사될 문자열: ");
scanf("%[^'\n']s", task); // 복사할 문자열을 입력
strcopy(origin, task); // task -> origin으로 복사
printf(" origin배열: %s \t task배열: %s\n\n\n", origin, task); // 복사된 결과
//
// 문자열 연결 부분
printf(" task와 연결할 문자열: ");
scanf(" %[^'\n']s", origin); // 원본 문자열에 값을 입력( 개행문자를 만날 때까지 입력받음.) 공백도 입력받게 했습니다.
printf("\n 연결 전 origin배열: %s \t", origin);
strcate(origin, task); // task를 origin에 연결
printf("\n 연결 후 origin배열: %s\n\n\n", origin);
//
// 문자열 비교 부분
int len; // 기존 origin문자열 길이
len = strLen(origin);
for (int i = 0; i < len; i++) {
origin[i] = 0; // 모두 0으로 초기화
}
puts(" 비교할 문자열");
printf(" origin: ");
scanf(" %[^'\n']s", origin);// origin에 값을 입력
printf(" task: ");
scanf(" %[^'\n']s", task);// task에 값을 입력
if (strcompare(origin, task) == 1) {
printf(" origin이 더 큽니다.\n\n\n");
}
else if (strcompare(origin, task) == -1) {
printf(" task가 더 큽니다.\n\n\n");
}
else
printf(" 같습니다.\n\n");
//
// 문자열 길이 N까지 비교 부분
int n; // 문자열 길이
puts(" 비교할 문자열 길이: ");
scanf(" %d", &n);
if (strNcompare(origin, task, n) == 1) {
printf(" origin이 더 큽니다.\n\n\n");
}
else if (strNcompare(origin, task, n) == -1) {
printf(" task가 더 큽니다.\n\n\n");
}
else
printf(" 같습니다.\n\n");
//
// 문자열 길이 추출
puts(" 길이 추출할 문자열");
printf(" origin: ");
len = strLen(origin); // 이전 문자열 길이 저장
for (int i = 0; i < len; i++) {
origin[i] = 0; // 새로 입력을 위해 0으로 초기화
}
scanf(" %[^'\n']s", origin);
printf(" origin배열의 문자열 길이는 %d입니다.\n\n", strLen(origin));
//
Sleep(2000); // .exe 실행파일에서는 프로그램이 바로 종료되므로 2초 대기후 종료
return 0;
}
반응형