■ 파일 입출력 ■


*fopen으로 열고 flose로 닫는다.


개방 모드 

 파일이 있을 때

 파일이 없을 때

 r

읽기만 

null 반환 

 w

내용 지우고 쓰기 

새로운 파일 자동 생성 

 a

내용 이어 쓰기 

새로운 파일 자동 생성 


1. fopen -> 메모리에 stream file 생성

*stream file은 문자 배열 형태의 버퍼를 가지고 있다.


버퍼에서 데이터를 읽거나 쓸 때 필요한 정보들을 구조체로 묶어서 보관합니다.

(=> 파일의 데이터 양을 버퍼만으로 관리할 수 없어서)

그래서 파일 포인터(파일 구조체 주소)를 반환합니다.



#문자 입력 함수 fgetc : 파일에서 문자 입력(파일에서 데이터를 읽어옴)

#문자 출력 함수 fputc : 문자를 파일에 출력(파일에 데이터 저장)



텍스트 파일

 바이너리 파일

 r, w, a

 rb, wb, ab

 +를 붙이면 읽고 쓰기 작업이 동시에 가능

(r+, w+, a+, rb+, wb+, ab+)


*텍스트 파일은 아스키 코드값에 따라 데이터를 읽고 

그외의 파일 형식을 바이너리 파일이라고 알고 있으면 된다.

(바이너리 파일 같은 파일은 메모장으로 열면 안보이고 Notepad++같은 tool을 이용해서 볼 수 있다) 



#문자 입력 함수 fgets 

#문자 출력 함수 fputs 

*문자열을 읽을 때 주의 할 점 : 문자열의 마지막 앞에 (NULL 앞에) \n(개행문자)가 존재한다는 것을 인식하자


예)        .txt

abc

def

123


1. 첫 줄 읽어 오기

2. str[strlen(str) -1] = '\0';    //개행문자를 대신하면 \0을 넣어줘서 개행문자 제거



#입력 함수 fscanf 

#출력 함수 fprintf


->흔히 쓰는 scanf, printf를 파일을 지정하여 쓸 수 있다 => 보편적으로 많이 이용한다.


/*형식 예

FILE *fp;

int res = fscanf(fp, "%s%d",name,&data);

*/


#파일을 읽기 전용 으로 읽을 때 파일이 있는지 예외처리를 해주자

<예>

FILE *fp;

if(fp ==NULL)

{

return 1;

}



#파일의 내용이 있는지 검는지 검사 형식


*파일을 다 읽으면 EOF를 반환한다.

*입력시 Ctrl + z를 누르면 EOF(-1)를 반환 한다.

1.

if(res ==EOF)//

{

break;

}


2.

if(feof(fp))

{

break;

}



#매출 관리 프로그램

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct
{
    char title[30];   
    double price;     
    int count;          
    double tot;    
     
} Book;
 
int check(char *title, Book *book, int count);
 
int main()
{
    FILE *ifp,*ofp;
    Book book[10];
    char title[30]; 
    double price;     
    int count,i=0,num,k;  
    int j;
    int max; 
    
    ifp = fopen("a.txt","r");
    if(ifp == NULL)
    {
        printf("a.txt 열지 못했습니다.\n");
        return 1;
    }
    
    ofp = fopen("b.txt""w");
    if (ofp == NULL)
    {
        printf("b.txt 열지 못했습니다.\n");
        return 1;
    }
    
    fgets(title,sizeof(title),ifp);
    
    while(!feof(ifp))
    {
 
        title[strlen(title)-1= '\0';
        fscanf(ifp,"%lf%d",&price,&count);
        fgetc(ifp);
        num = check(title, book,i);
        
        if(num>=0)
            {
                book[num].tot +=(price * count);
            }
        else
            {
            strcpy(book[i].title,title);
            book[i].price=price;
            book[i].count = count;
            book[i].tot = price * count;
            i++;
            }
            
        fgets(title,sizeof(title),ifp);    
    }
 
    
    //정렬
    k=i;
 
    for(i=0;i<k-1;i++)
    {
        max = i;
        for(j=i+1;j<k;j++)
        {
            if(book[j].tot > book[max].tot)
            max = j;    
        }    
        
        if(max !=i)
        {
        Book temp;
        temp = book[i];
        book[i]=book[max];
        book[max]=temp;
        }
    }
    
    //파일로 출력(저장) 
    for(i=0;i<k;i++)
    {
        fprintf(ofp,"%d. %s - %.0lf원\n", i+1,book[i].title,book[i].tot * 10000.0); 
    }
 
    fclose(ifp);
    fclose(ofp);
    return 0
}
 
//팩 제목이 같으면 가격만 add 
int check(char *title, Book *book, int count)
{
    int i;
    for(i=0;i<count;i++)
    {
        if(strcmp(title,book[i].title)==0)
        return i;//같으면  i번째 
    }
    return -1;//없으면 return
}
cs










#마방진

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
#include<stdio.h>
#include<string.h>
void magicSquareTest(void);
void setMagicSquare(int (*magic)[19]);
void printArray19(int (*magic)[19]);
int num;
int magic[19][19];
 
int main() {
    magicSquareTest();
    setMagicSquare(magic);
    printArray19(magic);
    
    system("pause");
    return 0;
}
void magicSquareTest(void) {
    printf("inpur number : ");
    scanf("%d",&num);
}
void setMagicSquare(int (*magic)[19]) {
    int count=1,k;
    int i=0,j=num/2;
    
    for (k=0;k<num*num;k++)
    {
        if(count%num==0)
            magic[i++][j]=count;
        else
            magic[i--][j++]=count;
            
        if(i<0)
            i=num+i;
        if(j>num-1)
            j=num-j;
            
        count++;
    }
}
void printArray19(int (*magic)[19]) {
    int i,j;
    for (i=0;i<num;i++
    {
        for (j=0;j<num;j++)
            printf("%5d",magic[i][j]);
        printf("\n");
    }
}
cs



#주민등록번호

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include<stdio.h>
#include<string.h>
int leap_year(int year);
int strtoNum(char* str);
int formatErrorCheck(char* str);
int dayofmonth[]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int main()
{
    char str[14];
    char flag;
    
    while(1)
    {
        
    printf("\"_\"를 제외한 확인할 주민등록 번호 13자리를 입력하세요 : ");
    gets(str);
        fflush(stdin);
    if(!formatErrorCheck(str))
    {
    printf("검증코드 오류인 주민등록 번호 입니다.\n");
    printf("다시 입력하시겠습니까? (y/n) ");
    scanf("%c"&flag);
     fflush(stdin);
    if (flag == 'Y' || flag == 'y')
    continue;
    else
    break;
    }
 
    else
    {
        printf("올바른 주민등록 번호 입니다.\n");
           printf("다시 입력하시겠습니까? (y/n) ");
    scanf("%c"&flag);
     fflush(stdin);
    if (flag == 'Y' || flag == 'y')
    continue;
    else
    break;
    }
}
    system("pause");
    return 0
}
 
int strtoNum(char* str)
{
    return atoi(str);
}
int leap_year(int year)
{
    if(year >50)
    year =year + 1900;
    else
    year =year + 2000;
    
    if(year%4!=0return 0;
    else if(year%100!=0return 1;
    else if(year%400==0return 1;
    else return 0;
}
 
int formatErrorCheck(char* str)
{
    if(strlen(str) !=13)
    return 0;
    
    char month[10]={0};
    strncpy(month,str+2,2);
    if(strtoNum(month)>12)
    return 0
 
    char day[10]={0};
    char year[10]={0};
    strncpy(year,str,2);
    strncpy(day,str+4,2);
    
    if(leap_year(strtoNum(year)))
    {
        dayofmonth[2]=28;    
    }
    if(strtoNum(day)>dayofmonth[strtoNum(month)])
    return 0;
 
    int magic[12= {2,3,4,5,6,7,8,9,2,3,4,5};
    int i , sum=0;
    int carry;
    for(i=0;i<12;i++)
    {
        sum +=magic[i]*(str[i]-48);
    }
    carry = sum%11;
    if(((11-carry)%10!=(str[12]-48))
    return 0;
    else
    return 1;    
}
cs


'C 언어' 카테고리의 다른 글

[C언어_Day9]파일 입출력  (0) 2018.10.11
[C언어_Day7]동적 할당  (0) 2018.10.11
[C언어_Day6]함수 포인터 + Void 포인터  (0) 2018.10.11
[C언어_Day5]명령 인수, 포인터 사용  (0) 2018.10.11
[C언어_Day4]String 예제  (0) 2018.10.11

■동적 할당■


코딩할 때 지역변수나 매개변수들을 stack에 저장된다 stack에 저장되면 블록을 빠져나가면 사라지게 된다.

반면, 동적 할당은 heap에 저장되어 free명령을 하기 전까지 살아있다.

(프로그램이 종료되면 운영체제가 알아서 free해준다. 하지만 free를 꼭 해주는 습관이 좋다.(그냥 해라)

아마 free를 안해주고 방대한 양이라면 메모리 누수가 생겨 런타임 에러가 발생하면... 상상도 하기 싫다.)


원형을 보면    void *malloc(unsigned int size);    ->size만큼 할당, 시작 위치 반환

(void 포인터를 썻군! 어떤 자료형이 와도 쓸 수 있구만! 대한 casting 해야겟네..)


이외에도 calloc(할당 공간 0으로 초기화), realloc(함수의 크기 조절)도 있습니다.



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
#include<stdio.h>
#include<stdlib.h>
 
int main()
{
    char temp[100];
    int i;
    int num=0;
    char *str[num];
    
    printf("문장의 개수 입력 : ");
    scanf("%d",&num);
    
    fflush(stdin);
    
    for(i=1;i<=num;i++)
    {
        printf("%d번째 문장을 입력하세요(99글자까지 입력 가능) :",i); 
        gets(temp);
        printf("\n");
        str[i] = (char *)malloc(strlen(temp)+1); //문자열 끝에 넣어줄 null때문에 +1 
    
        strcpy(str[i],temp);
    }
    
    for(i=1;i<=num;i++)
    {
        printf("%s\n",str[i]);    
        free(str[i]);
    }
    printf("출력이 끝났습니다.\n");
    
    system("pause");
    return 0
}
 
cs

fflush(stdin);는 버퍼를 clear해주는 역할입니다. 이 부분에 대해서는 따로 정리할 겁니다!
간단히 말하자면 버퍼라는 임시 공간이 있는데 키보드로 입력하여 enter 하면 들어갑니다.(공백, 탭, 엔터들도 함께 들어가죠!)
scanf는 공백(스페이스바)을 구분하여 몇 개 인지 구분을 하고 \n(new line)(enter키)를 치면 버퍼에서 가져갑니다.
그래서 예)1 2 3\n

scanf : \n가 있네? \n전까지 가져가야지~ 공백 2개네 3녀석이 들어왔구만!

하고 처리를 합니다. 반면 gets는 문자열을 입력하는 명령어죠! scanf와 다르게 공백까지 저장을 해줍니다.

gets : \n가 있네? 음... 우선 다 가져가자!

라며 "1 2 3"을 들고 옵니다. 하지만 scanf가 가져간 후의 버퍼상태를 보면

버퍼 : \n

되어있어서 gets가 입력 받기도 전에 버퍼에 \n가 남아있기 때문에 아무것도 가져오지 못합니다.

사용자 : (num을 입력했고.. 문장을 입력해볼까? ???뭐야 왜 넘어가지)

gets : \n가 있네? 음... 우선 다 가져가자!(들고 간게 없음..)

이때 fflush(stdin)을 써주면 clear되어 버퍼에 아무것도 남아있지 않습니다.


#끝 말 잇기
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
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
int Check(char **str, char *temp, int count);
 
int main()
{
    char temp[80];
    char *str[100= { 0 };
    int i, count;
 
    i = 0;
    while(1)
    {
        printf("단어 입력 :");
        scanf("%s", temp);
        if (!strcmp(temp, "end")) break;
        if( i && (str[i - 1][strlen(str[i - 1]) - 1!= temp[0]))
        {
            printf("단어 잇기가 불가능합니다!\n");    
            continue;
        }
        if(!Check(str,temp,i))
        {
            printf("# 이미 존재하는 단어입니다!\n");
            continue;
        }
            
        str[i] = (char *)malloc(strlen(temp) + 1);
        if(str[i] == NULL)
        {
            printf("> 메모리 부족...\n");
            break;
        }
        strcpy(str[i], temp);
        i++;
    }
    count =i;
    
    for(i=0;i<count;i++)
    {
    printf("%s ",str[i]);
        free(str[i]);
    }
    
    system("pause");
    return 0
}
 
int Check(char **str, char *temp, int count)
{
    int i;
    for(i=0;i<count;i++)
    {
        if(!strcmp(str[i],temp))
        return 0;        
    }
    return 1;
    
}
 
cs


■함수포인터와 void 포인터



# void 포인터


<한 줄 요약>

어떤 자료형이든 가능! 그러나 casting(강제 형변환) 해서 써야만 한다.


즉, void 포인터를 사용하면 유동적으로 사용할 수 있고 함수의 경우 자료형에 따라 만들 함수를 줄여줄 수 있습니다.

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 <string.h>
 
void swap(char *type, void *ap, void *bp);
 
int main(void)
{
    int age1, age2;
    double height1, height2;
 
    scanf("%d%lf"&age1, &height1);
 
    scanf("%d%lf"&age2, &height2);
 
    swap("int"&age1, &age2);
    swap("double"&height1, &height2);
 
    return 0;
}
 
void swap(char *type, void *ap, void *bp)
{
    int temp;
    double dtemp;
 
    if(strcmp(type, "int"== 0)
    {
        temp = *(int *)ap;
        *(int *)ap = *(int *)bp;
        *(int *)bp = temp;
    }
    if(strcmp(type, "double"== 0)
    {
        dtemp = *(double *)ap;
        *(double *)ap = *(double *)bp;
        *(double *)bp = dtemp;
    }
}
cs

#함수 포인터
기능은 다르지만 형태가 같은 함수를 선택적으로 호출할 때 함수 포인터를 쓴다.

자세히는 잘 모르겠지만 뭔가 묶어놓는(?) 느낌이 든다.

폴더 안에 폴더를 만드는 것처럼 이해했다.

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
#include<stdio.h>
int sum(int,int);
int sub(int,int);
double mul(double,double);
double div(double,double);
 
int func1(int (*fp)(int,int));
double func2(double (*fp)(double,double));
int main()
{
    printf("%d\n",func1(sum));    
    printf("%lf\n",func2(mul));
    return 0;
}
 
int func1(int (*fp)(int,int))
{
    int a,b;
    printf("정수 입력 :"); 
    scanf("%d%d",&a,&b);
    
    return fp(a,b);
}
 
double func2(double (*fp)(double,double))
{
    double a,b;
    printf("정수 입력 :"); 
    scanf("%lf%lf",&a,&b);
    
    return fp(a,b);
}
 
int sum(int a,int b)
{
    return a+b;
}
 
int sub(int a,int b)
{
    return a-b;
}
 
double mul(double a,double b)
{
    return a*b;
}
double div(double a,double b)
{
    return a/b;
}
cs
이렇게 sum,sub,mul,div라는 기능을 하는 주요 함수가 있고
sum,sub는 int형으로 func1을 통해서 접근하고

mul,div는 double형으로 func2를 통해서 접근하여 사용한다.



함수포인터는 초기화 할 때 매개변수의 자료형과 return의 자료형이 같아야 한다.



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
40
41
42
43
44
45
46
47
48
49
50
51
#include<stdio.h>
 
char *my_token(char *ps);
//char형 주소를 반환하고 char형 포인터 매개변수를 갖는 함수
int main()
{
    char str[80];
    char *p;
    
    printf("문장 입력 : ");
    gets(str);
    
    while((p =my_token(str)) !=NULL)//한문자씩 출력 
    {
    printf("%s\n",p);
    }
    //str이 NULL이 올때가지 실행 즉, 문자열의 끝(NULL)까지 실행 
    return 0;
}
 
char *my_token(char *ps)
{     
    static char* ch = NULL;
    static int end =0;      //정적 지역변수 선언
    char *start; 
    char *count;
    
    if(ps==NULL)
    return NULL;            //문자열이 있는지?
    
    if(end == 1//끝났는지? 
    return NULL;
    
    if(ch ==NULL)//시작  
    start = ps;
    else
    start = ch+1;
    
    count = start;
    
    while(*count !=' '&&*count !='\0')
    count++;
    // 공백 까지 counting
    if(*count =='\0'end =1;//끝 
    else
    *count = '\0';//구분했을때 공백에 null 
    
    ch = count;//위치 넣어줌. 
    
    return start; 
}
cs



■명령 인수


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<string.h>
int main(int argc, char **argv) {
    char str[80];
    int num1, num2;
    int i;
    int count;
    int sum=0;
    //cmd 에서 입력 예 : atio 123 4
    //                 ->  argv[0] argv[1] argv[2]
    strcpy(str,argv[1]);
    count = atoi(argv[2]);
    //문자열을 정수로 넣어준다. 
    for (i=0;i<count;i++) {
        num1 = atoi(str);
        printf("\n%s\n",str);
        strrev(str);
        printf("%s\n",str);
        printf("--------\n");
        sum =num1+atoi(str);
        //문자 -> 정수 
        printf("%d\n",sum);
        itoa(sum, str, 10);
    }
}
//atio.exe(실행파일을) cmd의 디렉토리에 마춰서(C:\)넣은후 실행
cs




1. strcmp 구현
flow :  문자열 2개를 받아 한 문자씩 검사

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>
 
int my_strcmp(char* str1, char* str2);
 
int main()
{
    char str1[80],str2[80];
    int check; 
    
    printf("첫 번재 비교할 문자열 입력 : ");
    gets(str1);
    printf("두 번재 비교할 문자열 입력 : ");
    gets(str2);
    check = my_strcmp(&str1,&str2);
    
    if(check ==1)
    printf("%s가 더 큽니다.",str1);
    else if(check ==-1)
    printf("%s가 더 큽니다.",str2);
    else
    printf("두 문자열이 같습니다.");
 
    return 0;    
}
 
int my_strcmp(char* str1, char* str2)
{
    while((*str1 == *str2 )&&(*str1 !='\0'))
    {
        str1++;
        str2++;    
    }
    
    if(*str1>*str2) return 1;
    else if(*str1<*str2) return -1;
    else return 0;
}
 
 
cs

2. swap

문자열 2개를 받아 한 문자씩 swap

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
#include<stdio.h>
#include<string.h>
 
void swap(char* str1,char* str2);
 
int main()
{
    char str1[80],str2[80];
    printf("1번 문자열을 입력하세요 : ");
    gets(str1);
    printf("2번 문자열을 입력하세요 : ");
    gets(str2);
    
    
    printf("swap 전 : %s - %s\n",str1,str2); 
    swap(&str1,&str2);
    printf("swap 후 : %s - %s",str1,str2);
    return 0;
}    
void swap(char *pa, char *pb)
{
    char temp;
    while((*pb != '\0'|| (*pa != '\0'))
    {
        temp = *pa;
        *pa = *pb;
        *pb = temp;
        
        pa++;
        pb++;
    }    
}
cs
3. 가장 긴 단어 찾기

getchar로 한문자씩 입력을 받아서 null값전까지 counting한다


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>
 
int main(void)
{
    int ch;
    int len, max = 0;
 
    while(1)
    {
        len = 0;
 
        ch = getchar();                    // 문자 입력
        while((ch != -1&& (ch != '\n'))  // Ctrl+Z키를 누르거나 엔터 키를 치지 않는 동안
        {
            len++;                         // 문자의 수를 센다
            ch = getchar();
        }
        if(ch == -1break;                // Ctrl+Z키가 눌려진 경우 입력 종료
        if(len > max) max = len;           // 새로 입력한 단어의 길이가 현재 가장 긴                                            
    }                                      // 단어의 길이보다 길면 그 값을 가장 긴 길이로 설정
    printf("가장 긴 단어의 길이 : %d\n", max);
 
    return 0;
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
int main() {
    char str[80];
    printf("문장 입력 : ");
    gets(str);
    int i,count=0;
    ;
    for (i=0;str[i];i++) {
        if(str[i]>='A'&&str[i]<'Z') {
            str[i]=str[i]-'A'+'a';
            count++;
        }
    }
    printf("바뀐 문장 : %s\n",str);
    printf("바뀐 문자 수 : %d\n",count);
    system( "pause");
    return 0;
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<stdio.h>
int main() {
    int i;
    while(1) {
        for (i=1;i<=5;i++) {
            if(i%3==0continue;
            printf("C Programming...\n");
        }
        if(i==5)break;
//i가 5일때 continue이기 떄문에 i가 6이되어 break가 되지 않아
무한 루프가 된다.
    }
    system( "pause");
    return 0;
}
cs


'C 언어' 카테고리의 다른 글

[C언어_Day6]함수 포인터 + Void 포인터  (0) 2018.10.11
[C언어_Day5]명령 인수, 포인터 사용  (0) 2018.10.11
[C언어_Day4]String 예제  (0) 2018.10.11
[C언어_Day3]대소문자 변경  (0) 2018.10.11
[C언어_Day1]for문 연습  (0) 2018.10.11

+ Recent posts