본문 바로가기

윤성우의 C Programming

두 개의 텍스트 파일 비교하기

 

두 개의 텍스트 파일이 같은지 다른지를 확인하는 프로그램을 작성해 보자.

단순히 공백문자 하나가 차이를 보여도 두 텍스트 파일은 다른 것으로 판별이 나야 한다.

# 실행의 예

/*다음은 실행파일의 이름이 comp.exe 이고, 비교의 대상이 되는 
두 파일의 이름이 각각 d1.txt 와 d2.txt인 경우의 실행의 예이다.*/

C:\test>comp d1.txt d2.txt
두 개의 파일은 완전히 일치 합니다.

 

헤더 파일 포함하기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
  • #define _CRT_SECURE_NO_WARNINGS
    • scanf_s을 사용하고 싶지 않을 때 컴파일러가 보안 관련 경고를 발생시키지 않도록 할 수 있다. 
  • #include <stdio.h>
    • 표준 입출력 함수를 사용하기 위해 필요한 헤더 파일이다  
    • printf, fgets, fopen, fclose, scanf 등의 함수가 여기에 정의되어 있다. 
  • #include <string.h>
    • 문자열 처리 함수를 사용하기 위한 헤더 파일이다.
    • 이 예제에서는 strcmp 함수를 사용하여 두 문자열이 같은지를 비교한다. 

상수 정의하기 

const int SAME=1;
const int DIFF=2;
  • SAME과 DIFF는 프로그램 내에서 파일 비교 결과를 나타내는 상수이다. SAME은 두 파일이 같음을, DIFF는 두 파일이 다름을 나타낸다.

Main 함수

int main(int argc, char *argv[])
  • argc는 커맨드 라인에서 입력된 인자의 몇 개인지 세고 argv는 인자의 값들이 뭔지 보여주는 문자열 배열의 포인터이다.

변수 선언하기 

	FILE *sorc1;
	FILE *sorc2;

	char str1[100], str2[100];
	int state1, state2;
	int flag=SAME;    // same or diff
  • sorc1sorc2FILE 타입의 포인터 변수로, 두 개의 파일을 각각 가리키기 위해 사용된다. fopen 함수를 통해 이 변수들에 파일 스트림을 할당하고, 이후 fgets 등의 함수를 사용해 파일의 내용을 읽거나 처리할 수 있다.
  • str1str2는 각각 100개의 문자를 저장할 수 있는 문자 배열이다. 이 배열들은 sorc1sorc2에서 읽은 각 파일의 한 줄씩을 저장하는 데 사용된다. fgets 함수를 이용해 파일로부터 문자열을 읽어들일 때 이 배열들이 사용된다.
  • state1state2는 파일을 닫을 때 fclose 함수의 반환 값을 저장하기 위한 변수이다. fclose 함수는 성공적으로 파일을 닫았을 때 0을 반환하고, 실패했을 때 0이 아닌 값을 반환한다. 이 변수들을 통해 각 파일이 제대로 닫혔는지 여부를 확인할 수 있다.
  • flag는 두 파일의 비교 결과를 나타내는 변수이다. 초기값으로 SAME을 할당하여, 두 파일이 같다고 가정한다. 파일을 비교하는 과정 중에 두 파일의 내용이 다른 부분이 발견되면, 이 변수의 값을 DIFF로 변경한다. 프로그램의 마지막 부분에서 이 변수를 검사하여 두 파일이 같은지 다른지에 대한 결과를 사용자에게 알린다. 

인자 검사하기 

if(argc!=3) 
{
    puts("usage : comp source1 source2 \n");
    return 1;
}
  • 프로그램은 정확히 두 개의 파일 이름을 인자로 받아야 한다.  argc가 3이 아니면(프로그램 이름 포함이므로), 사용 방법을 안내하는 메시지를 출력하고, 1을 반환하여 오류와 함께 프로그램을 종료한다. 

파일 열기

sorc1=fopen(argv[1], "rt");
sorc2=fopen(argv[2], "rt");
  • fopen 함수를 사용하여 두 파일을 텍스트 읽기 모드("rt")로 연다.
  • argv[1]argv[2]는 사용자가 입력한 두 파일의 경로이다. 

파일 열기 오류 검사 

if(sorc1==NULL || sorc2==NULL)
{
    printf("file open error!\n");
    return 1;
}
  • 두 파일 중 하나라도 열기에 실패하면 오류 메시지를 출력하고, 프로그램을 종료한다. 

파일 내용 비교 

while(1)
{
    if(feof(sorc1)!=0 && feof(sorc2)!=0)
        break;
    fgets(str1, sizeof(str1), sorc1);
    fgets(str2, sizeof(str2), sorc2);
    if(strcmp(str1, str2)!=0)
    {
        flag=DIFF;
        break;
    }
}
  • feof() 함수는 파일의 끝(EOF, End Of File)에 도달했는지를 확인하는 함수이다. 파일의 끝에 도달했을 때 feof() 함수는 0이 아닌 값을 반환한다. 파일의 끝이 아니면 0을 반환한다. 여기서는 파일 2개 모두 파일의 끝에 도달하면 반복문을 빠져나온다. 
  • 무한 루프 내에서 두 파일의 내용을 한 줄씩 읽어서 비교한다. fgets 함수로 각 파일에서 한 줄씩 읽는다.
  • strcmp 함수로 두 문자열이 같은지 비교한다. 문자열이 다르면 flagDIFF로 설정하고 루프를 빠져나온다. 

비교 결과 출력 

if(flag==SAME)
    fputs("두 개의 파일은 완전히 일치 합니다.", stdout);
else
    fputs("두 개의 파일은 불일치 합니다.", stdout);
  • flag의 값에 따라 두 파일이 같은지 다른지에 대한 메시지를 출력합니다.

파일 닫기

state1=fclose(sorc1);
state2=fclose(sorc2);
  • 열린 파일을 닫는다.

프로그램 종료 

if(state1!=0||state2!=0)
{
    printf("file close error!\n");
    return 1;
}
return 0;
  • 파일을 닫는 데 실패했다면 오류 메시지를 출력하고, 오류와 함께 프로그램을 종료한다. 그렇지 않다면 성공적으로 프로그램을 종료한다. (0을 반환).

완성된 코드문 

#include <stdio.h>
#include <string.h>

const int SAME=1;
const int DIFF=2;

int main(int argc, char *argv[])
{
	FILE *sorc1;
	FILE *sorc2;

	char str1[100], str2[100];
	int state1, state2;
	int flag=SAME;    // same or diff
	
	if(argc!=3) 
	{
		puts("usage : comp sorurce1 source2 \n");
		return 1;
	}

	/* 파일의 개방 */
	sorc1=fopen(argv[1], "rt");
	sorc2=fopen(argv[2], "rt");	
	if(sorc1==NULL || sorc2==NULL)
	{
		printf("file open error!\n");
		return 1;
	}

	/* FILE COMPARE */
	while(1)
	{
		if(feof(sorc1)!=0 && feof(sorc2)!=0)
			break;
		fgets(str1, sizeof(str1), sorc1);
		fgets(str2, sizeof(str2), sorc2);
		if(strcmp(str1, str2)!=0)
		{
			flag=DIFF;
			break;
		}
	}

	if(flag==SAME)
		fputs("두 개의 파일은 완전히 일치 합니다.", stdout);
	else
		fputs("두 개의 파일은 불일치 합니다.", stdout);
	
	/* 파일의 종결 */
	state1=fclose(sorc1);
	state2=fclose(sorc2);
	if(state1!=0||state2!=0)
	{
		printf("file close error!\n");
		return 1;
	}
	return 0;
}