1. 程式人生 > 其它 >浙大版《C語言程式設計》第四版(何欽銘顏暉) 第12章 檔案 課後習題答案

浙大版《C語言程式設計》第四版(何欽銘顏暉) 第12章 檔案 課後習題答案

你也可以上程式咖(https://meta.chengxuka.com),開啟大學幕題板塊,不但有答案,講解,還可以線上答題。

一、選擇題

1.以下語句的輸出結果是( )。

printf("%d,%d,%d", NULL, '\0', EOF);

A.0,0,1

B.0,0,-1

C. NULL, ,EOF

D. 1,0, EOF

答:B

解析:

NULL等於0
'\0'也是等於0
EOF等於-1

2.緩衝檔案系統的檔案緩衝區位於( )。

A.磁碟緩衝區中

B.磁碟檔案中

C.記憶體資料區中

D.程式檔案中

答:C

解析:

檔案緩衝區是用以暫時存放讀寫期間的檔案資料而在記憶體區預留的一定空間

3.定義 FILE *fp; 則檔案指標 fp 指向的是( )。

A.檔案在磁碟上的讀寫位置

B.檔案在緩衝區上的讀寫位置

C.整個磁碟檔案

D.檔案型別結構

答:D

解析:

語句 FILE *fp; ,定義了一個 FILE 結構指標, FILE 是 C 語言為了具體實現對檔案的操作而定義的一個包含檔案操作相關資訊的結構型別。

4.若以 “a+” 方式開啟一個已存在的檔案, 則以下敘述正確的是( )。

A.檔案開啟時,原有檔案內容不被刪除,位置指標移到檔案末尾,可執行新增和讀操作

B. 檔案開啟時,原有檔案內容不被刪除,位置指標移到檔案開頭,可執行重寫和讀操作

C.檔案開啟時,原有檔案內容被刪除,只可執行寫操作

D.以上各種說法都不正確

答:A

解析:

"a+" 的開啟模式,開啟文字檔案進行讀/寫/追加。

5.以下可作為函式 fopen() 中第一個引數的正確格式是( )。

A. C: user\text. txt

B. c: \user\text. txt

C. "e:\user\ text. txt"

D. "c:\\user\\text.txt"

答:D

解析:

函式 fopen 的第一個引數是指要開啟的檔名的字串,所以選項 A、B 是錯誤的。檔案路徑分隔符 \ 必須使用轉義字元,即 \\,所以選項 C 也是錯誤的。選項 D 是正確的。

二、填空題

1.檔案的三大特徵是( )、資料長度不定和資料按順序存取。

答:資料長久儲存

解析:

檔案是儲存在外在儲存器上的一組資料的有序集合。檔案的特點是資料長久儲存,資料長度不定,資料按順序存取。

2.根據資料儲存的編碼形式,C 語言中處理的資料檔案通常為( )檔案和( )檔案兩種。

答:

文字檔案

二進位制人間

解析:

在 C 語言中,按照儲存的編碼形式,資料檔案可以分為文字檔案和二進位制檔案兩種。文字檔案是以字元 ASCII 碼值進行儲存與編碼的檔案,其檔案的內容就是字元。二進位制檔案是儲存二進位制資料的檔案。

3.判斷檔案指標是否已經到了檔案尾部的函式是( )。

答:feof()

解析:

feof() ,用於判斷 fp 指標是否已經到檔案末尾,即讀檔案是否讀到了檔案結束的位置。其呼叫格式為:feof(fp); 該函式成功返回 1 表示已經到了檔案結束位置,0 表示檔案未結束。

4.統計文字檔案的字元數量。統計文字檔案 "letter.txt" 中字元的個數。請填空。

#include <stdio.h>
int main()
{
	FILE *fp;
	int count = 0;
	fp = fopen("letter.txt", _________);
	while (!feof(fp))
	{
		_________;
		count++;
	}
	printf("count=%d\n", count);
	fclose(fp);
	return 0;
}

答:

"r"

fgetc(fp)

解析:

第一個空,開啟檔案的模式,因為只是讀取,所以填 "r" 就可以。

第二個空,就是逐個讀取字元。

5.以下程式段實現的功能是( )。

	char infile[10], outfile[10];
	FILE *fpa, *fpb;
	gets(infile);
	gets(outfile);
	fpa = fopen(infile, "r");
	fpb = fopen(outfile, "w");
	while (!feof(fpa))
	{

		fputc(fgetc(fpa), fpb);
	}
	fclose(fpa);
	fclose(fpb);

答:將檔名為鍵盤輸入的infile表示的檔案內容複製到檔名為鍵盤輸入的outfile變量表示的檔案中

解析:

這裡只讀模式打開了infile檔案,只寫模式打開了outfile,然後迴圈讀取infile檔案中的每個字元,寫入到outfile檔案中。

三、程式設計題

題目1:統計文字檔案中各類字元個數:分別統計一個文字檔案中字母,數字及其他字元的個數。試編寫相應程式。

答案程式碼:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	// 習題(12.3.1)
	/*
	統計文字檔案中各類字元個數:分別統計一個文字檔案中字母,數字及其他字元的個數。

	*/

	char ch;
	char *path = "data1.txt";
	FILE *fp = fopen(path, "r");
	if (!fp)
	{
		printf("file open error\n");
		exit(0);
	}

	int letter = 0, digit = 0, other = 0;

	while ((ch = fgetc(fp)) != EOF) // EOF 表示到達末尾
	{
		if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))

			letter++;
		else if (ch >= '0' && ch <= '9')
			digit++;
		else
			other++;
	}
	printf("字母:%d,數字:%d,其他:%d\n", letter, digit, other);

	fclose(fp);
	return 0;
}

執行結果:

所讀檔案內容如下:

題目2:將實數寫入檔案:從鍵盤輸入若干實數(以特殊數值-1結束),分別寫到一個文字檔案中。試編寫相應程式。

答案程式碼:

#include <stdio.h>
#include "stdlib.h"
int main()
{
	// 習題(12.3.2)
	/*
	將實數寫入檔案:從鍵盤輸入若干實數(以特殊數值-1結束),分別寫到一個文字檔案中。

	*/

	FILE *fp;
	float num = 0;

	fp = fopen("data2.txt", "w+");
	if (!fp)
	{
		printf("file open error\n");
		exit(0);
	}
	while (scanf("%f", &num), num != -1)
	{
		fprintf(fp, "%f\n", num);
	}
	fclose(fp);

	return 0;
}

執行結果:

寫入目標檔案:

題目3:比較兩個文字檔案是否相等:比較兩個文字檔案的內容是否相同,並輸出兩個檔案中第一次出現不同字元內容的行號及列值。試編寫相應程式。

答案程式碼:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	// 習題(12.3.3)
	/*
	比較兩個文字檔案是否相等:比較兩個文字檔案的內容是否相同,並輸出兩個檔案中第一次出現不同字元內容的行號及列值。

	*/

	FILE *fp1, *fp2;
	int array1 = 1, row1 = 1, array2 = 1, row2 = 1;
	char ch1, ch2;
	// data3_1 與 data3_2 都是與當前程式在同一目錄下的檔案
	fp1 = fopen("data3_1.txt", "r");
	fp2 = fopen("data3_2.txt", "r");
	if (!fp1 || !fp2)
	{
		printf("file open error\n");
		exit(0);
	}

	while (!feof(fp1) || !feof(fp2))
	{
		ch1 = fgetc(fp1);
		ch2 = fgetc(fp2);
		if (ch1 == '\n')
		{
			row1++;
			array1 = 1;
		}
		if (ch2 == '\n')
		{
			row2++;
			array2 = 1;
		}
		if (ch1 == EOF || ch2 == EOF)
			break;
		if (ch1 != ch2)
		{
			printf("data3_1\t行號:%d 列號:%d\n", row1, array1);
			printf("data3_2\t行號:%d 列號:%d\n", row2, array2);
			break;
		}
		else
		{
			array1++;
			array2++;
			printf("讀到字元:%c\n", ch1);
		}
	}
	if (ch1 == EOF && ch2 != EOF)
		printf("data3_2 檔案已經到達末尾");
	if (ch2 == EOF && ch1 != EOF)
		printf("data3_1 檔案已經到達末尾");
	if (ch1 == EOF && ch2 == EOF)
		printf("兩個檔案完全相同!");
	fclose(fp1);
	fclose(fp2);

	return 0;
}

兩個檔案的內容相同:

執行結果:

兩個檔案的內容不同:

執行結果:

題目4:將檔案中的資料求和並寫入文字檔案尾:檔案 Int _Data.dat 中存放了若干整數,將檔案中所有資料相加,並把累加和寫入該檔案的最後。試編寫相應程式。

答案程式碼:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	// 習題(12.3.4)
	/*
	將檔案中的資料求和並寫入文字檔案尾:檔案Int _Data. dat 中存放了若干整數,將檔案中所有資料相加,並把累加和寫入該檔案的最後。

	*/
	FILE *fp;
	int n, sum = 0;
	fp = fopen("Int _Data.dat", "rb+");
	if (!fp)
	{
		printf("file open error\n");
		exit(0);
	}
	// 讀取
	while (fscanf(fp, "%d", &n) != EOF)
		sum += n;
	printf("sum = %d\n", sum);
	fprintf(fp, "\n%d", sum);
	fclose(fp);
	return 0;
}

Int _Data.dat 檔案中的內容:

執行結果:

寫入計算結果後,Int _Data.dat 檔案中的內容:

題目5:輸出含 for 的行:將文字檔案 test.txt 中所有包含字串 “for” 的行輸出。試編寫相應程式。

答案程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 80

void Findfor(char *ch);
int main()
{
	// 習題(12.3.5)
	/*
	輸出含 for 的行:將文字檔案 test.txt 中所有包含字串  “for”  的行輸出。

	*/

	FILE *fp;
	char ch[N];
	fp = fopen("test.txt", "r");
	while (!feof(fp))
	{
		fgets(ch, N, fp);
		Findfor(ch);
	}
	fclose(fp);
	return 0;
}

void Findfor(char *ch)
{
	int i = 0;
	for (i = 0; i < strlen(ch); i++)
	{
		if (ch[i] == 'f' && ch[i + 1] == 'o' && ch[i + 2] == 'r')
			printf("This row have for:%s\n", ch);
	}
}

test.txt 檔案內容如下:

執行結果:

題目6:刪除檔案中的註釋:將 C 語言源程式( hello.c)檔案中的所有註釋去掉後存入另一個檔案(new_ hello.c)。 試編寫相應程式。

答案程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	// 習題(12.3.6)
	/*
	刪除檔案中的註釋:將 C 語言源程式( hello.c)檔案中的所有註釋去掉後存入另一個檔案(new_ hello.c)。

	*/

	FILE *fp1, *fp2;
	char ch;
	char comment[2];
	/*開啟讀出資料的檔案*/
	if ((fp1 = fopen("hello.c", "r")) == NULL)
	{
		printf("File open error!\n");
		exit(0);
	}
	/*開啟寫入資料的檔案*/
	if ((fp2 = fopen("new_hello.c", "w")) == NULL)
	{
		printf("File open error!\n");
		exit(0);
	}
	/*對檔案1中的字元進行處理*/
	while (!feof(fp1))
	{
		ch = fgetc(fp1);
		if (ch == EOF)
			continue;
		if (ch == '/')
		{
			ch = fgetc(fp1);
			//單行註釋 ,遇到換行符結束,結束後需輸出換行符
			if (ch == '/')
			{
				while (ch != '\n' && ch != EOF)
				{
					ch = fgetc(fp1);
				}
				fputc('\n', fp2);
			}
			/*跨行註釋,遇到結束符結束,每次讀入兩個字元進行比較,若不是則退回一個字元,繼續比較*/
			else if (ch == '*')
			{
				fgets(comment, 3, fp1);
				while (strstr(comment, "*/") == NULL)
				{
					fseek(fp1, -1L, SEEK_CUR);
					fgets(comment, 3, fp1);
				}
			}
			//不是註釋符,只是單純的'/'符號,則退回兩個字元,讀寫'/'
			else
			{
				fseek(fp1, -2L, SEEK_CUR);
				ch = fgetc(fp1);
				fputc(ch, fp2);
			}
		}
		else
		{
			fputc(ch, fp2);
		}
	}
	//關閉檔案
	if (fclose(fp1))
	{
		printf("Can not close the file! \n");
		exit(0);
	}
	//關閉檔案
	if (fclose(fp2))
	{
		printf("Can not close the file! \n");
		exit(0);
	}
	printf("處理結束\n");

	return 0;
}

執行結果:

hello.c 檔案和 new_ hello.c 檔案對比:

題目7:(選做)賬戶餘額管理:建立一個隨機檔案,用來儲存銀行賬戶和餘額資訊,程式要求能夠查詢某個賬戶的餘額,當客戶發生交易額時(正表示存入,負表示取出)能夠更新餘額。賬戶資訊包括賬號、賬號名和餘額三個資料項。試編寫相應程式。

檔案部分內容如下:

AcctNo AcctName Balance
1 zhangsan 1 000. 00
2 lisi 1 300. 00
3 wangwu - 100. 00
……

答案程式碼:

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

long size;
struct account
{
	char no[10];
	char acctname[50];
	double balance;
};

FILE *openfile(char *openmode);
double userbalance(FILE *fp, char *name);
void pay(FILE *fp, char *name, double count);
int main()
{
	// 習題(12.3.7)
	/*
	選做)賬戶餘額管理:建立一個隨機檔案,用來儲存銀行賬戶和餘額資訊,程式要求能夠查詢某個賬戶的餘額,當客戶發生交易額時(正表示存入,負表示取出)能夠更新餘額。賬戶資訊包括賬號、賬號名和餘額三個資料項。

	*/

	FILE *fp;
	int choice;
	char name[50];
	double balance;
	double count;

	while (1)
	{
		printf("請輸入選擇型別\n");
		printf("1.查賬戶餘額\n");
		printf("2.賬戶交易\n");
		printf("退出按其她\n");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
		{
			printf("輸入名字:");
			scanf("%s", name);
			fp = openfile("r+");
			balance = userbalance(fp, name);
			printf("%s, %.2lf\n", name, balance);

			break;
		}
		case 2:
		{
			printf("輸入名字:");
			scanf("%s", name);
			fp = openfile("r+");
			printf("輸入交易金額:");
			scanf("%lf", &count);
			pay(fp, name, count);
			break;
		}
		default:
			exit(0);
			break;
		}
	}
	return 0;
}
// 開啟檔案
FILE *openfile(char *openmode)
{
	FILE *fp;
	if ((fp = fopen("accout.dat", openmode)) == NULL)
	{
		printf("File open error!\n");
		exit(0);
	}
	return fp;
}

// 使用者餘額
double userbalance(FILE *fp, char *name)
{
	struct account user;
	double balance;
	fseek(fp, 0L, SEEK_SET);
	while (!feof(fp))
	{
		fscanf(fp, "%s %s %lf", user.no, user.acctname, &user.balance);
		if (strcmp(user.acctname, name) == 0)
		{
			balance = user.balance;
			break;
		}
	}
	// fclose(fp);
	return balance;
}

// 交易
void pay(FILE *fp, char *name, double count)
{
	FILE *fpout;
	struct account user;
	double balance;
	balance = userbalance(fp, name);
	balance = balance + count;
	fseek(fp, 0L, SEEK_SET);
	fpout = fopen("temp.dat", "w");
	int no = 0;
	int res = 1;
	while (1)
	{
		res = feof(fp);
		if (res != 0)
		{
			break;
		}

		fscanf(fp, "%s %s %lf\n", user.no, user.acctname, &user.balance); //讀入
		// printf("%s %s %lf\n", user.no, user.acctname, user.balance);
		if (strcmp(user.acctname, name) == 0)
		{
			user.balance = balance;
			// printf("if---%s %s %lf\n", user.no, user.acctname, user.balance);
			fprintf(fpout, "%s %s %.2lf\n", user.no, user.acctname, user.balance);
		}
		else
		{
			// printf("else---%s %s %lf\n", user.no, user.acctname, user.balance);
			fprintf(fpout, "%s %s %.2lf\n", user.no, user.acctname, user.balance);
		}
	}

	fclose(fpout);
	fclose(fp);
	unlink("accout.dat");
	rename("temp.dat", "accout.dat");
}

accout.dat 檔案內容:

執行結果:

accout.dat 更改後: