C언어 알고리즘

C언어 포인터를 활용한 문자열 관련 함수(strcpy, strcat, strcmp, strncmp, strlen) 직접 구현하기

C's everything! 2022. 5. 20. 14:01
반응형

<string.h> 헤더 파일에 내장되어 있는 함수이지만, 포인터를 활용해보기 위해서 문자열 함수들을 직접 구현했습니다. 포인터에 대한 깊은 이해를 원하시는 분은 제 소스를 기반으로 본인만의 코드 스타일로 바꿔보시면 좋을 것 같습니다.

소스를 보시다가 scanf 함수 안에 ^'\n' 이라는 생소한 문법이 있습니다. 이것은 '개행문자를 만날 때까지 문자를 입력받겠다' 라는 뜻입니다. scanf 함수는 공백문자나 개행문자를 입력 받으면 입력이 종료되는 방식인데, ^'\n' 속성을 지정해주면 공백문자도 입력으로 취급해서 문자열에 공백 입력이 가능하게 됩니다. 

string.exe
0.01MB

#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;
}

 

반응형