리눅스 Tips, 리눅스 C/C++ 프로그래밍, 모바일 클라우드 동향 및 테스트 등

2012년 12월 6일 목요일

리눅스 시스템 프로그래밍 : 03 입력과 출력(3)


8. 원시 데이터타입의 데이터와 구조체데이터 읽고 쓰기

 그럼 이전 포스트에서 다룬 data.txt 에 저장된 int형 정보를 읽어서 화면에 출력하는 프로그램을 작성해 보도록 하자. 프로그램의 흐름은 간단하다. data.txt 를 읽기 전용 으로 연 다음 read 함수를 이용해서 4byte 씩 읽어들인다. 읽어들인 데이터는 printf 함수를 이용해서 화면에 출력하면 된다.

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define MAXLEN 80
int main()
{
  int fd;
  int readn = 0;
  int buf;
  fd = open("data.txt", O_RDONLY);
  if (fd < 0)
  {
    perror("file open error:");
    return 1;
  }
  while( (readn = read(fd, (void *)&buf, sizeof(buf) )) > 0)
  {
    printf("Read Data : %d\n", buf);
  }
}

 읽을 정보가 int형 데이터 이므로, int형 데이터 타입의 
크기 만큼 - 대부분의 경우 4byte - 읽어서 buf 에 복사하고 있다. 읽어들인 정보는 21줄에서 printf 를 통해서 
출력했다.

 이 프로그램을 실행시키면 다음과 같은 결과를 보여줄 것이다.

# ./read
Read Data : 0
Read Data : 2
Read Data : 4
Read Data : 6
Read Data : 8
...

 문자열 데이터 이거나, int 형 숫자 데이터 이거나 컴퓨터의 입장에서는 비트의 나열일 뿐임을 명심할 필요가 있다. 단지 표현의 차이을 뿐이다. 똑같은 비트의 나열이라도 문자열로 표현하고자 하면 문자열이 되는 거고, 숫자로 표현하고자 하면 숫자로 표현된다.

  8.1 좀더 복잡한 구조체 데이터 읽고 쓰기

 컴퓨터의 관점에서 모든 데이터는 bit 의 나열일 뿐이라는 것을 이해한다면, 구조체를 읽고 쓰는 것 역시 전혀 문제되지 없다. 대부분의 높은 수준의 응용 프로그램이라면 문자열이나 int, long과 같은 원시 데이터 타입보다는 구조체 데이터를 읽고 쓰도록 되어 있다.

 유저 정보를 저장하고 읽는 간단한 프로그램을 작성한다고 가정해보자. 하나의 유저를 나타내기 위해서 필요한 정보는 다음과 같다고 할 때,

이름
나이
성별
취미

 프로그래머는 대략 다음과 같은 구조체를 사용할 것이다. 구조체는 데이터를 레코드 단위로 관리할 수 있도록 도와주기 때문이다.

struct userInfo
{
  char name[28];
  int  age;
  int  sex;
  char hobb6[28];
};

 그럼 위의 구조체 정보를 저장하는 간단한 유저정보 관리 프로그램을 만들어 보도록 하자. 제대로 만드려고 하면, 각 구조체 변수 데이터를 입력 받기 위한 인터페이스까지 만들어야 겠지만 생략하도록 하겠다. 이 프로그램은 뒷 부분에서 사용자 입력을 받을 수 있도록 확장될 것이다.

 테스트를 위해서 읽기와 쓰기를 전담하는 2개의 프로그램을 작성할 것이다. 우선 쓰기 프로그램이다. 이 프로그램의 이름은 UserInfoWrite.c 로 하겠다.

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

struct userInfo
{
  char name[28];
  int age;
  int sex;
  char hobby[28];
};

void makeUserInfo(struct userInfo *uinfo,
  char *name,  // 이름
  int age,     // 나이
  int sex,     // 성 (남: 0, 여: 1)
  char *hobby) // 취미
{
  memset((void *)uinfo, 0x00, sizeof(struct userInfo));
  strcpy(uinfo->name, name);
  uinfo->age = age;
  uinfo->sex = sex;
  strcpy(uinfo->hobby, hobby);
}

int main()
{
  int fd;
  struct userInfo myAddrBook;
  fd = open("hello.txt", O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
  if (fd < 0)
  {
    perror("file open error");
    return 1;
  }

  makeUserInfo((void *)&myAddrBook, "yundream", 19, 0, "프로그래밍");
  write(fd, (void *)&myAddrBook, sizeof(myAddrBook));

  makeUserInfo((void *)&myAddrBook, "hello", 22, 1, "게임");
  write(fd, (void *)&myAddrBook, sizeof(myAddrBook));

  makeUserInfo((void *)&myAddrBook, "드라고너", 33, 1, "사냥");
  write(fd, (void *)&myAddrBook, sizeof(myAddrBook));

  close(fd);
  return 0;
}

 유저 정보와 유저 정보 구조체인 userInfo 를 넘기면, 구조체를 채우는 makeUserInfo 라는 함수를 만들었다. 현재는 프로그램 상에 직접 유저 정보를 집어 넣었지만 나중에는 키보드로 입력받을 수 있도록 할 것이다.

 Line 40 ~ 47에서 유저 정보 구조체 myAddrBook 을 파일에 쓰고 있다. int형 데이터, char형 데이터를 쓰는 것과 다를게 없음을 알 수 있다. 컴퓨터의 입장에서는 int형 데이터나 char 형 데이터나 비트의 나열일 뿐임으로 근본적으로 다를게 없기 때문이다. 몇 바이트의 정보를 저장할 것인지에 대한 저장크기에만 차이가 있을 뿐이다.

 다음은 hello.txt에 저장된 유저 정보를 읽어들여서 출력하는 프로그램이다. 프로그램의 이름은 UserInfoRead.c 로 하겠다.

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

struct userInfo
{
  char name[28];
  int age;
  int sex;
  char hobby[28];
};

int main()
{
  int fd;
  struct userInfo myAddrBook;
  int dataSize;
  fd = open("hello.txt", O_RDONLY);
  if (fd < 0)
  {
    perror("file open error");
    return 1;
  }

  dataSize = sizeof(myAddrBook);
  printf("User Info =====================\n\n");
  while(read(fd, (void *)&myAddrBook, dataSize) == dataSize)
  {
    printf("name  : %s\n", myAddrBook.name);
    printf("age   : %d\n", myAddrBook.age);
    printf("sex   : %d\n", myAddrBook.sex);
    printf("hobby : %s\n", myAddrBook.hobby);
    printf("===============================\n");
  }
  close(fd);
  return 0;
}

 데이터를 읽기만 할 것이기 때문에, O_RDONLY 를 사용했다. 다음 while문을 돌면서 userInfo 구조체의 크기 만큼, 파일로 부터 데이터를 읽어들여서 myAddrBook에 저장하고 있음을 알 수 있다.


 - 다음 포스트에 이어서...

댓글 없음:

댓글 쓰기