반응형

명령어 라인으로 주어진 2개의 텍스트 파일을 합하여 하나의 파일로 만드는 프로그램을 작성하라.


argc는 argument의 수, argv는 argument가 char 형 문자열로 저장되는 포인터 배열입니다.

argv[0]은 무조건 실행 파일의 경로가 저장되고 argv[1]부터는 사용자가 입력한 인수가 저장되는데

공백문자(' ')로 분리됩니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
int main(int argc, char *argv[])
    FILE *fp1=NULL;
    FILE *fp2=NULL;
    FILE *fp3=NULL;
    char line[SIZE];
    if((fp1=fopen(argv[1],"r"))==NULL)
    {
        printf("file open error1\n");
        exit(1);
    }
    if((fp2=fopen(argv[2],"r"))==NULL)
    {
        printf("file open error2\n");
        exit(1);
    }
    if((fp3=fopen(argv[3],"a"))==NULL)
    {
        printf("file open error3\n");
        exit(1);
    }
    while(!feof(fp1))
    {
        fgets(line,SIZE,fp1);
        fputs(line,fp3);
    }
    while(!feof(fp2))
    {
        fgets(line,SIZE,fp2);
        fputs(line,fp3);
    }
    printf("\n%s %s를 합하여 %s를 작성하였습니다.\n",argv[1],argv[2],argv[3]);
    fclose(fp1);
    fclose(fp2);
    return 0;
}
cs







반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C언어' 카테고리의 다른 글

문자열 동적 메모리  (0) 2017.02.21
양의 정수들의 합  (0) 2017.02.21
단어 바꾸기  (0) 2017.02.18
특정 단어 찾기  (0) 2017.02.18
텍스트 파일과 이진 파일  (0) 2017.02.17
반응형

텍스트 파일을 읽어서 각 줄의 앞에 줄 번호를 붙이는 프로그램을 작성하라. 줄 번호는 폭이 6이고 오른쪽 정렬되도록 하라.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
    FILE *fp = NULL;
    char arr[SIZE];
    char name[SIZE];
    int num = 1;
    printf("파일 이름: ");
    gets(name);
    if ((fp=fopen(name,"r"))==NULL)
    {
        printf("파일 오픈 실패\n");
        exit(1);
    }
    while (!feof(fp))
    {
        fgets(arr, SIZE, fp); //fgets함수는 개행문자까지 받는다.
        if (arr[strlen(arr) - 1== '\n')
            {
                arr[strlen(arr) - 1= '\0';
            }  //따라서 개행문자가 출력되므로 개행문자를 NUL문자로 바꿔준다.
        printf("%6d: ", num); //폭6 오른쪽정렬
        puts(arr);
        num++;
    }
    fclose(fp);
    return 0;
}
cs





반응형
반응형

먼저 아래의 소스코드를 보자.


1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main()
{
    char szStr[20];
    gets(szStr);
    printf("%d",*szStr);
    return 0;
}
cs

이 코드를 실행해서 아무것도 입력하지않고 enter를 쳐주면 아마 '\0' 이 szStr[0]에 저장될 것이고 이것이 정수 형식으로 출력되므로 0이 나올 것이다. (szStr[0] 과 *szStr 이 같은 것을 출력한다는 것을 모른다면 ... 복습하고 오세욧)

결과는 0이나옵니다. (아스키코드값) 아스키코드 0은 NUL 문자입니다. (문자열 끝을 나타낼 때 쓰는 것) ('\0' 의 아스키코드는 0)




하지만 이 것은 어떨까요?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main()
{
    char szStr[20];
    fgets(szStr,20,stdin);
    printf("%d",*szStr);
    return 0;
}
cs

fgets와 gets는 차이점이 있는데요 fgets는 개행문자 '\n' 을 문자열에 포함시킵니다. gets 는 개행문자를 문자열에 포함하지 않습니다.

결과는 10이나옵니다. (아스키코드값) 10은 LF(NL Line feed, new line) 을 의미합니다. 커서를 현재 행에서 다음 행으로 즉 아래로 내린다는 뜻입니다.


이번에는 7번 문제의 힌트를 읽어보겠습니다. 

fgets(...,stdin) 를 사용하면 사용자로부터 한 줄의 문장을 받을 수 있다. 만약 fgets()가 0을 반환하면 공백 문자열이 입력된 것이므로 반복 루프를 종료하고 출력 파일을 닫으면 된다.

라고 써있는데요. fgets는 오류가 발생할 때 null pointer를 반환합니다. 파일 끝에 도달하였는데 아무런 문자를 읽지 못하였을 때는 

문자열의 내용은 그대로 두고 null pointer를 반환합니다. (포인터 : NULL 이나 0      문자열 : 0이나 '\0' 이나 "")


1
2
3
4
5
6
7
8
#include <stdio.h>
 
int main()
{
    char szStr[20];
    printf("%d",fgets(szStr,20,stdin));
    return 0;
}
cs

그렇다면 fgets 로 szStr을 받는데 아무것도 입력하지 않고 엔터를 쳤을 경우 NULL 포인터가 반환되니 값이 0이 나와야 하는데 그것을 확인해 보겠습니다. 


나오지 않습니다. 심지어 주소도 실행 할 때마다 계속 바뀝니다.  그렇다면 get는 어떨까요


1
2
3
4
5
6
7
8
#include <stdio.h>
 
int main()
{
    char szStr[20];
    printf("%d",gets(szStr));
    return 0;
}
cs


똑같이 어떤 특정한 주소값이 나오고 할 때마다 계속 바뀝니다.


1
2
3
4
5
6
7
8
#include <stdio.h>
 
int main()
{
    int *p=NULL;
    printf("%d",p);
    return 0;
}
cs

그리고 포인터를 NULL 로 초기화 (NULL 이랑 0은 같은것임 포인터에서) 하였을 때 주소값이 0이나오는지 확인해 보았더니 맞는 말이었습니다.




결론적으로 힌트에 나와있는 말이 실제로 그렇게 되지 않는 다는 것을 알 수 있습니다.. 그래서 다른 방법으로 코딩을 해 보겠습니다.




사용자가 입력하는 텍스트를 파일에 저장하여 주는 프로그램을 작성하여 보자. 사용자가 공백 문자열을 입력하면 입력을 종료하는 것으로 가정한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
int main(void)
{
    FILE *fp=NULL;
    char name[SIZE];
    char line[SIZE];
    int count1,count2,i;
    printf("파일 이름을 입력하세요: ");
    gets(name);
    if((fp=fopen(name,"w"))==NULL)
    {
        printf("파일 열기 오류\n");
        exit(1);
    }
    while(1)
    {
    line[0]='\0';
    count1=0;count2=0;
    fgets(line,SIZE,stdin);
    for(i=0;line[i]!='\0';i++)
    {
        count1++;
        if((line[i]==' ')||(line[i]=='\t')||(line[i]=='\n'))
        {count2++;}  //개행문자도 해주는 이유는 무조건 들어가는 문자이기 때문
    } //총 글자수와 공백 문자 수를 비교하여 같으면 프로그램 종료, 다르면 계속 실행
    if(count1==count2)
        break;
    fputs(line,fp);
    }
    fclose(fp);
    return 0;
}
cs



괜히 힌트 때문에 시간을 버렸네요.

문자열 내 모든 문자(\n포함 ) 수와 문자열 내 모든 공백문자 (\t, ' '를 세는데 \n 도 포함합니다. 왜냐하면 무조건 들어가는 문자이기 때문)

수를 비교하여 같으면 프로그램 종료, 다르면 계속 진행하게 코딩하였습니다.







반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C언어' 카테고리의 다른 글

도서 관리 프로그램  (0) 2017.02.17
줄 번호 붙이기  (0) 2017.02.17
인쇄 가능 문자 수 세기  (0) 2017.02.13
성적 평균 구하기  (0) 2017.02.12
텍스트 파일 비교  (0) 2017.02.11
반응형

하나의 파일을 다른 이름의 파일로 복사하는 프로그램을 작성하라. 이진 파일이라고 가정하고 fread()와 fwrite()를 사용한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
int main(void)
{
    FILE *fpr=NULL;
    FILE *fpw=NULL;
    char buff[SIZE];
    int count=0;
    if((fpr=fopen("first.bin","rb"))==NULL)
    {
        printf("잘못된 파일 열기1\n");
        exit(1);
    }
    if((fpw=fopen("second.bin","wb"))==NULL)
    {
        printf("잘못된 파일 열기2\n");
        exit(1);
    }
    while((count=(fread(buff,sizeof(char),SIZE,fpr)))!=0)
    {
        printf("%d",count); //몇 개 세었는지 보려고
    fwrite(buff,sizeof(char),count,fpw);
    }
    return 0;    
}
cs

buff 와 fread 나 fwrite 를 쓸 때 덩어리의 크기를 int로 하면 오류가 생길 수 있습니다. 중간에 잘리는 경우(예를들어 09에서 0과 9사이에서 잘리는 경우)

데이터가 손실되는 것을 경험하였습니다. 따라서 1byte 단위인 char로 하는 것이 가장 안전합니다. (촘촘이 자르는 것이 가장 안전하겠죠??)

예를들어 int 형으로 한다면

1000100 을 복사하면 앞의 1000만 복사가 됩니다. 뒤에 100은 덩어리 (4byte) 가 꽉 안차서 손실이 되는 것 같아요 (정확한 것 아님 결과로부터 추론한 것임 (출력값은 1이됨)

정확한 것을 아시는 분은 댓글로 달아주세요)

그런데 10001000 을 하면  10001000 이 복사되고 출력값은 2가됩니다. 따라서 덩어리를 다 채워줘야 하는 것 같습니다.






반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C언어' 카테고리의 다른 글

텍스트 파일 비교  (0) 2017.02.11
fgets 함수  (0) 2017.02.11
대문자로 변경  (0) 2017.01.31
텍스트 파일 비교  (0) 2017.01.31
암호화와 복호화  (0) 2017.01.16
반응형

텍스트 파일을 열어서 파일 안에 들어 있는 문자들을 모두 대문자로 변경하는 프로그램을 작성한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 100
 
int main(void)
{
    FILE *fp=NULL;
    char a[SIZE];
    int i;
    if((fp=fopen("1.txt","r+"))==NULL)
    {
        printf("잘못된 파일 열기\n");
        exit(1);
    }
    fgets(a,SIZE,fp);
    printf("입력 파일 : ");
    for(i=0;a[i]!=NULL;i++)
    {
        printf("%c ", a[i]);
    }
    printf("\n");
    fseek(fp,0,SEEK_SET);
    for(i=0;a[i]!=NULL;i++)
    {
        a[i]=toupper(a[i]);
    }
    fputs(a,fp);
    fseek(fp,0,SEEK_SET);
    fgets(a,SIZE,fp);
    printf("출력 파일 : ");
    for(i=0;a[i]!=NULL;i++)
    {
        printf("%c ", a[i]);
    }
    printf("\n");
    return 0;
}
cs




반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C언어' 카테고리의 다른 글

fgets 함수  (0) 2017.02.11
파일 복사  (0) 2017.01.31
텍스트 파일 비교  (0) 2017.01.31
암호화와 복호화  (0) 2017.01.16
대소문자 변경  (0) 2017.01.16
반응형

두개의 텍스트 파일을 비교하여 같은지 다른지를 알려주는 프로그램을 작성하라.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
#define DEBUG 0
void open_file(FILE **fp1, FILE **fp2);
void check(FILE *fp1, FILE *fp2);
int main(void)
{
    FILE *fp1=NULL;
    FILE *fp2=NULL;
    int quit=0;
    while(1)
    {
    open_file(&fp1,&fp2);
    check(fp1,fp2);
    fseek(fp1,0,SEEK_SET);
    fseek(fp2,0,SEEK_SET);
    printf("종료하려면 9999 계속하려면 1\n");
    scanf("%d",&quit);
    if(quit==9999)
        break;
    getchar();
    }
    return 0;
}
void open_file(FILE **fp1, FILE **fp2)
{
    char name1[SIZE];
    char name2[SIZE];
    printf("첫번째 파일 이름: ");
    gets(name1);
    printf("두번째 파일 이름: ");
    gets(name2);
    if((*fp1=fopen(name1,"r"))==NULL)
    {
        printf("파일오픈불가능1\n");
        exit(1);
    }
    if((*fp2=fopen(name2,"r"))==NULL)
    {
        printf("파일오픈불가능2\n");
        exit(1);
    }
}
void check(FILE *fp1, FILE *fp2)
{
    char a,b;
    while(1)
    {
        a=fgetc(fp1);
        b=fgetc(fp2);
        #if DEBUG==1
        printf("%d %d\n", a,b);
        #endif
        if((feof(fp1)!=0&&feof(fp2)==0)||(feof(fp1)==0&&feof(fp2)!=0))
        {
            printf("두 파일은 서로 다릅니다(길이다름).\n");
            break;
        }
        if(a!=b)
        {
            printf("두 파일은 서로 다릅니다(글자다름).\n");
            break;
        }
        if(feof(fp1)!=0&&feof(fp2)!=0)
        {
            printf("두 파일은 서로 같습니다.\n");
            break;
        }
    }
}
cs



먼저 이중포인터를 사용한 이유는 fp1, fp2 자체가 파일을 가리키는 포인터죠. 따라서 처음에 초기값으로

NULL을 가리키고 있으니까 포인터가 가리키는 주소를 바꿔주려면 이중포인터를 사용해야해서 그렇습니다.

두번째로 중요한 것은 check 함수인데요. 여기서 '글자다름' 파트를 '길이다름' 파트보다 먼저 쓰게되면

무조건 다른 것이 글자다름으로 나오게 됩니다. 왜냐하면 텍스트 파일에서 EOF(파일의 끝)은 -1 값을

반환하게 되는데요 이것을 비교했을 때 글자다름을 먼저 수행하게 되면 무조건 -1과는 다른 값이 되므로

(길이가 다르기 때문에 다른 한쪽은 문자일 것이므로 어떠한 정수값을 가질 것임) 글자다름

으로 출력이 됩니다. 따라서 길이다름을 먼저 해주어야 길이가 다를 때는 길이다름으로 출력을 할 수 있습니다.

이것은 눈으로 확인할 수 있게 #if 로 표시를 해놓았습니다. 눈으로 확인하고 싶으시면 DEBUG 값을 1로 바꾸세요.

아래 스크린샷에도 추가해 놓았습니다.

파일 실행하기전 txt 파일로 아래와 같이 생성한 후에 시작해야합니다. (r타입으로 읽기 때문에)



이와같이 텍스트 파일에서는 파일의 끝이 -1로 표현되기 때문에 꼭 길이다름을 먼저 판별해 주어야 한다.

아니면 무조건 글자다름으로만 나온다. (길이가 다를 경우 -1은 무조건 다른 파일의 남은 글자와 다를테니까)




반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C언어' 카테고리의 다른 글

파일 복사  (0) 2017.01.31
대문자로 변경  (0) 2017.01.31
암호화와 복호화  (0) 2017.01.16
대소문자 변경  (0) 2017.01.16
정수 비트 이동  (0) 2017.01.16

+ Recent posts