Homework Assignment #9 Solutions

1. 寫一個 C 語言的程式片段讀入兩個文字檔案的內容,並將其內容連接在一起,中間以 "####" 分隔,再將結果寫入第三個檔案,請自訂檔名 。

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

int main(void) {
  char fName1[20], fName2[20], fName3[20], *buffer;
  FILE *fPtr;
  int fLeng1, fLeng2;

  printf("Enter the name of the first input file: ");
  scanf("%s", fName1);
  fPtr = fopen(fName1, "r");
  if (fPtr==NULL) {
    printf("\nFile %s does not exist.\n\n", fName1);
    return -1;
  }
  fseek(fPtr, 0, SEEK_END);
  fLeng1 = ftell(fPtr);
  fseek(fPtr, 0, SEEK_SET);
  buffer = (char *) malloc((fLeng1 + 4) * sizeof(char));
  fread(buffer, 1, fLeng1, fPtr);
  fclose(fPtr);
  buffer[fLeng1] = '#';
  buffer[fLeng1+1] = '#';
  buffer[fLeng1+2] = '#';
  buffer[fLeng1+3] = '#';

  printf("Enter the name of the second input file: ");
  scanf("%s", fName2);
  fPtr = fopen(fName2, "r");
  if (fPtr==NULL) {
    printf("\nFile %s does not exist.\n\n", fName2);
    return -1;
  }
  fseek(fPtr, 0, SEEK_END);
  fLeng2 = ftell(fPtr);
  fseek(fPtr, 0, SEEK_SET);
  buffer = (char *) realloc(buffer, (fLeng1 + fLeng2 + 5) * sizeof(char));
  fread(&buffer[fLeng1+4], 1, fLeng2, fPtr);
  fclose(fPtr);
  buffer[fLeng1+fLeng2+4] = '\0';

  printf("The resulting file is:\n\n");
  printf("%s\n\n", buffer);

  printf("Enter the name of the output file: ");
  scanf("%s", fName3);
  fPtr = fopen(fName3, "w");
  fwrite(buffer, 1, fLeng1+fLeng2+4, fPtr);
  fclose(fPtr);

  return 0;
}

2. 下列是一個包含員工姓名、時薪、一週工作時數 (星期一至星期五) 的結構資料型態:

typedef struct {

  struct  {

    char first[7];

    char last[7];

  } name;

  float hourly_pay;

  int working_hours[5];

} week_pay;

假設一個工廠有多位員工,他們在某一週的工作時數都記錄在一個的名稱為 salary.txt 的檔案內。

(a) 寫出至少六個員工的的薪資資料內容,

(b) 寫出一個 C 語言的程式片段將 salary.txt 的資料讀到一個 week_pay 的陣列。

(a) salary.txt 的檔案內容:

大華 李       95.5  8  6  4  8  6
有禮 陳     120.0  6  5  7  8  8
文     趙      100.0  8  8  8  8  8
傑米 程     150.0  6  4  2 5  3
明明 歐陽   80.0  5  6  4  7  8
美麗 吳       85.0  6  4  7  8  5

(b)

typedef struct {

  struct  {

    char first[7];

    char last[7];

  } name;

  float hourly_pay;

  int working_hours[5];

} week_pay;

 

week_pay salary[6];

FILE *fptr;

int i, j;

 

fptr = fopen("salary.txt", "r");

for (i=0; i<6; i++) {

  fscanf(fptr, "%s %s %f", salary[i].name.first, salary[i].name.last, &salary[i].hourly_pay);

  for (j=0; j<5; j++) fscanf(fptr, "%d", &salary[i].working_hours[j]);

}

fclose(fptr);

¼

3. 假設你已經實作了 stdio.h 中的 fopen(), fclose(), fgetc(), fputc(), feof(),  fseek(), ftell(), fsetpos() 等副程式,使用這些副程式實作下列的副程式:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); // 假設 fopen 的 mode 值為 "w".

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); // 假設 fopen 的 mode 值為 "a".

// 當 fopen() 的 mode 值為 "r", "rb", 或 "r+" 時,fopen() 會檢查所開的檔案是否存在。如果檔案存在,fopen() 會將該檔案打開,並將 stream 置於檔案開始的地方。

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {

  int i;

  unsigned char c;

  for (i=0; i<size*nmemb; i++) {

    c = getc(stream);

    if (!feof(stream)) ptr[i] = c;

    else break;

  }

  return i;

}

// 當 fopen() 的 mode 值為 "w", "wb", 或 "w+" 時,fopen() 會檢查所開的檔案是否存在。如果檔案不存在,fopen() 會產生一個新檔,將 stream 置於檔案開始的地方;如果該檔案存在 fopen() 會將該檔案打開,並將 stream 置於檔案開始的地方。當檔案被 flcose() 關閉的時候,EOF 會寫入檔案最後的位置。

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {

  int i;

  unsigned char c;

  for (i=0; i<size*nmemb; i++) {

    c = putc(ptr[i], stream);

    if (c==EOF) break; // putc() has an error.

  }

  return i;

}

// 當 fopen() 的 mode 值為 "a", "ab", 或 "a+" 時,fopen() 會檢查所開的檔案是否存在。如果檔案不存在,fopen() 會產生一個新檔,將 stream 置於檔案開始的地方;如果該檔案存在 fopen() 會將該檔案打開,並將 stream 置於檔案結束的地方。當檔案被 flcose() 關閉的時候,EOF 會寫入檔案最後的位置。

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {

  int i;

  unsigned char c;

  for (i=0; i<size*nmemb; i++) {

    c = putc(ptr[i], stream);

    if (c==EOF) break; // putc() has an error.

  }

  return i;

}