내장형 하드웨어/C언어

C언어 - text mode, binary mode, fprintf, freed, 배열과 포인터

동화다아아 2011. 6. 30. 17:31

 

- 텍스트 모드와 이진모드(Text Mode and Binary Mode)

⇒ 텍스트 형식과 이진 형식은 숫자를 저장하는 방법의 구분이고, 텍스트 모드와 이진 모드는 도스 파일의 해석에 대한 구분이다. 텍스트 모드와 이진 모드의 차이는 유닉스에서 유래된 C 언어와 도스 운영체제의 차이점에서 비롯되었다. 텍스트 모드는 도스 파일을 유닉스 파일처럼 보이기 위해서 개행문자와 파일의 끝을 C언어가 변환시킨다. 이진 모드에서는 도스 파일을 변환없이 그대로 보인다.



// 파일을 이진 모드로 열어서, 한 문자씩 읽어 화면에 출력하는 프로그램

#include<stdio.h>
#define LENGTH 10

int main(int argc, char *argv[])
{
        
int i = 0;
        FILE *fp;
        
char ch;
        
char string[LENGTH+1];

        
if(argc !=2)
        {
                printf(
"Wrong in command line");
                
return -100;
        }
        
if((fp=fopen(argv[1], "rb")) == NULL)
        {
                printf(
"Can't open file %s.", argv[1]);
                
return -10;
        }
        
while((ch = fgetc(fp)) != EOF)
        {
                printf(
"%3x", ch);
                
if(ch>31)
                {
                        *(string + i++) 
= ch;
                }
                
else
                
{
                        *(string + i++) 
= '.';
                }
                
if(i>=LENGTH)
                {
                        *(string + i) 
= '\0';
                        printf(
"        %s\n", string);
                        i
=0;
                }
        }
        fclose(fp);
        
return 0;
}

⇒ 실행결과         

 

/* 학생의 이름, 영어와 수학성적을 입력받아 평균을 계산하여 파일에 기록하고, 파일의 내용을 출력하는 프로그램 */

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

typedef struct
{
        
char name[25];
        
int english;
        
int math;
        
float average;
}STUDENT;

int main()
{
        STUDENT st;
        FILE *fp;

        
if((fp = fopen("d11-7.dat","wb")) == NULL)
        {
                printf(
"Can't open file d11-7.dat");
                
return -100;
        }
        printf(
"Please type <enter key> for Name, if you finish input\n");
        printf(
"Enter Name: ");
        gets(st.name);

        
while(strlen(st.name)>0)
        {
                printf(
"Enter English score: ");
                scanf(
"%d"&st.english);
                printf(
"Enter Math score: ");
                scanf(
"%d"&st.math);
                st.average 
= ((float)st.english + st.math)/2;
                fwrite(
&st, sizeof(st), 1, fp);

                
if(ferror(fp))
                {
                        perror(
"Error: ");
                        fclose(fp);
                        
return -100;
                }
                printf(
"\nPlease type <enter key> for Name, if you finish input\n");
                printf(
"Enter Name: ");
                
//fflush(stdin);
                
getchar(); // while(getchar()!='\n');
                
gets(st.name);
        }
        fclose(fp);

        
if((fp = fopen ("d11-7.dat""rb")) == NULL)
        {
                printf(
"Can't open file d11-7.dat");
                
return -10;
        }
        printf(
"\nName    english    math    Average\n");
        
while(fread(&st, sizeof(st), 1, fp)==1)
        {          

      printf("%s\t  %d\t  %d\t  %7.2f\n", st.name, st.english, st.math, st.average);
        }
        fclose(fp);
        
return 0;
}

⇒ 실행 결과         

 


// 데이터 파일의 두 번째 줄을 화면과 파일에 출력하는 프로그램

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char *argv[])
{
        
char ch = 0;
        
long pos;
        FILE *infp, *outfp;

        
if(argc != 3)
        {
                printf(
"Data file name missing!");
                
return -100;
        }
        
if((infp = fopen(argv[1], "rb")) == NULL)
        {
                printf(
"cannot fileopen");
                
return -10;
        }
        
if((outfp = fopen(argv[2], "wb")) == NULL)
        {
                printf(
"cannot file create");
                
return -1;
        }
        
while(fgetc(infp) != '\n');
        pos 
= ftell(infp);

        while(ch !='\n')
        {
                fseek(infp, pos++, SEEK_SET);
                ch 
= fgetc(infp);
                putchar(ch);
                fputc(ch, outfp);
        }
        fclose(infp);
        fclose(outfp);
  
        
return 0;


⇒ 실행결과

 


#include<stdio.h>

int main()

{

        FILE *fp;

        int iNum = 0x12345678;

        int iRet;

        fp = fopen("A.txt","w");

        if(fp==NULL)

        {

                printf("File read error\n");

                return -100;

        }

        iRet = fprintf(fp, "%d\n", iNum); // fprintf로 iNum 출력

        iRet = fwrite(&iNum, 1, 4, fp); // fwrite로 iNum 출력

        fprintf(fp, "%d\n", iNum);

        close(fp);

        return 0;

}

⇒ 출력결과         

 

⇒ A. txt파일을 열어보면 → 305419896이 저장되어 있는 것을 볼 수 있다.

⇒ 왼쪽의 코드를 보면 각 숫자에 해당하는 ASCII 코드번호가 16진수로 나타나는데 이것으로 보아 int형 4byte로 저장된 것이 아니라 각각의 숫자가 char형 1byte로 저장된 것을 볼 수 있다. 이것은 fprintf와 fscanf를 사용했을 때, 우리가 입력할 데이터가 4바이트 값에 들어가지 않고 그 크기가 커졌음을 알 수 있다.

⇒ fprintf, fscanf는 화면출력 기반, 즉 화면에 표시된 것을 저장하므로 데이터를 살펴보았을 때 그 값이 다르다.

⇒ 이것을 바꾸기 위해 아스키 xV4에 해당하는 것을 보면 78 56 34 12 의 결과를 볼 수 있으며 이를 위해 fread, fwrite를 사용하였다.



- 배열

char T[] = "ABCDE";

65

66

67

68

69

00

⇒ 위 배열의 symbol table은

type

name

address

char[]

T

100

※ 주소는 임의로 설정

이며 char[] 는 char * const T와 같으며 char *P = T로 했을 때 양 쪽의 형은 일치한다.


// 배열과 포인터의 관계를 알기위한 테스트

#include<stdio.h>

int main()

{


        char T[] = "ABCDE";

        char *P = T;

        printf("%s\n", T);

        T[0] = 'Z';

        printf("%s\n", T);

        *(P+0) = 'A';

        printf("%s\n", T);

        T[1] = 'Z';

        printf("%s\n", T);

        *(P+1) = 'B';

        printf("%s\n", T);

        *(T+2) = 'Z';

        printf("%s\n", T);

        P[2] = 'C';

        printf("%s\n", T);


        return 0;

}

⇒ 출력 결과         

 

⇒ *P = 'A'; 는 *(P+0)='A'와 같다.

⇒ *(P+1)의 주소를 알기위해 &를 붙이면

 → &*(P+1) → (P+1) → &P[1]로 되며 이 세가지는 모두 같다.


※ 포인터란 가리키는 메모리를 어떻게 볼것인가? 라고 생각해 볼 수 있다.

  (해당하는 곳을 몇바이트 덩어리로 볼것인가.)