大学教材《C语言程序设计》(浙大版)课后习题解析 | 第十一、十二章

概述

      本文主要提供《C语言程序设计》(浙大版) 第十一、十二章的课后习题解析,以方便同学们完成题目后作为参考对照。

专栏直达链接:

《C语言程序设计》(浙大版)_孟俊宇-MJY的博客-CSDN博客​icon-default.png?t=N7T8http://t.csdnimg.cn/ZtcgY

一.第十一章(指针进阶)

选择题

[11-1]

下面程序段的运行结果是( )。

int x[5] = {2, 4, 6, 8, 10}, *p, **pp;
p = x;
pp = &p;
printf("%d", *(p++));
printf("%d\n", **pp);

A.4 4

B.2 4

C.2 2

D.4 6

答:B

解析:

题目中先定义了 int 类型的数组 x,又定义两个指针。

然后 p = x,表示将 x 的基地址赋值给 p,所以 p 指向数组中第一个元素。

第一次打印 *(p++),获取 p 指向的元素,打印 2, 然后指针位置向后移动一个位置。

因为 pp = &p,表示将 p 的地址赋值给 pp,所以 pp 指向 p,p 经过上次打印时的 ++,已经向后一定一个,所以第二个打印 **pp,打印的就是 4。

[11-2]

对于以下变量定义,正确的赋值是( )。

int *p[3], a[3];
A. p=aB. *p=a[0]C. p=&a[0]D. p[0]=&a[0]

答:D

解析:

定义为int *p[3],a[3]; 可知这里 p 是一个指针数组,p 为数组名,所以不能作为赋值号的左操作数,所以选项 A 和 C 不对 *p 即 p[0],所以选项 B 等效于 p[0]=a[0],a[0]是int类型,而p[0] 应该存储指针变量(int *),所以B也不对。

[11-3]

下列程序段的输出是( )。

int i, a[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, *p[4];
for (i = 0; i < 4; i++)
{p[i] = &a[i * 3];
}
printf("%d\n", p[3][2]);

A.12

B.8

C.6

D.上述程序有错误

答:A

解析:

题目中定义了一维数组 a[12],以及一个指针数组 p。

当 i=0 时,第一次循环:p[0]=&a[0] ,p[0] 指向 a[0]

当 i=1 时,第二次循环:p[1]=&a[3] ,p[1] 指向 a[3]

当 i=2 时,第三次循环:p[2]=&a[6] ,p[2] 指向 a[6]

当 i=3 时,第四次循环:p[3]=&a[9] ,p[3] 指向 a[9]

当 i=4 时,循环结束。

p[3][2],相当于 p[3]+2,因为 p[3] 指向 a[9] ,所以 p[3][2] 指向 a[11],a[11] 所对应的值是 12 ,所以输出12。

[11-4]

设有如下定义的链表,则值为 7 的表达式是( )。

struct st
{int n;struct st *next;
} a[3] = {5, &a[1], 7, &a[2], 9, NULL}, *p = a;

A. p->n

B. (p->n)++

C. p->next->n

D. ++p->n

答:C

解析:

题目中 *p=a,表示指针 p 指向 a 的基地址。

选项 A,打印数组 a 中第一个元素的 n 的值,输出 5。

选项 B,也是打印 5。因为是后加。

选项 C,p 指向 a 的基地址,默认第一个元素, p->next,表示它的下一个元素,就是 7 和 &a[2],打印它的 n,就是 7。

选项 D,因为 -> 的优先级高于 ++,所以这里取 p -> n,数组中第一个元素的 n ,为 5,前置++,所以打印 6。

[11-5]

下面程序段输入一行字符,按输入的逆序建立一个链表。

struct node{char info;struct node *link;} * top, *p;char c;top = NULL;while ((c = getchar()) != '\n'){p = (struct node *)malloc(sizeof(struct node));p->info = c;___________;top = p;}

A. top->link=p

B. p->link= top

C. top=p->link

D. p=top->link

答:B

解析:

因为要逆序建立链表,所以让 p->link 赋值为 top,然后 top赋值为 p。

填空题

[11-1]

下面程序段的输出结果是( )。

const char *s[3] = {"point", "continue", "break"};for (int i = 2; i >= 0; i--)for (int j = 2; j > i; j--)printf("%s\n", s[i] + j);

答:

ntinue

int

oint

解析:

这里是两层循环嵌套,

i=2时,j=2时,内层循环条件不满足。

i=1时,j=2时,打印 s[i]+j ,就是 s[1]+2,对应continue,但是因为要加 2,所以从下标为 2 的字符开始,就是 ntinue。

​ j=1时,内层循环条件不满足。

i=0时,j=2时,打印 s[i]+j ,就是 s[0]+2,对应point,但是因为要加 2,所以从下标为 2 的字符开始,就是 int。

​ j=1时,打印 s[i]+j ,就是 s[0]+1,对应point,但是因为要加 2,所以从下标为 2 的字符开始,就是o int。

[11-2]

下面程序段的输出结果是( )。

const char *st[] = {"Hello", "world", "!"}, **p = st;
p++;
printf("%s-%c\n", *p, **p);
(*p)++;
printf("%s-%c-%c\n", *p, **p, (**p) + 1);

答:

world-w

orld-o-p

解析:

首先定义了指针数组 st,存储的是 3 个字符串的地址。然后又定义了二级指针变量 p,这里 p 存储的是 st 的基地址。

然后 p++,那么指向了里面的第二个字符串的地址。*p 打印该字符串。world,**p,打印字符 w。

然后 (*p)++,那么指针向后移动一位,从 o 开始,打印 orld,**p 打印 o, (**p) + 1 先取 **p 就是 o 然后再加 1,就是 p。

[11-3]

下面程序段的输出结果是( )。

static int a[4][4];
int *p[4], i, j;
for (i = 0; i < 4; i++)p[i] = &a[i][0];
for (i = 0; i < 4; i++)
{*(p[i] + i) = 1;*(p[i] + 4 - (i + 1)) = 1;
}
for (i = 0; i < 4; i++)
{for (j = 0; j < 4; j++)printf("%2d", p[i][j]);printf("\n");
}

答:

1 0 0 1

0 1 1 0

0 1 1 0

1 0 0 1

解析:

首先定义了一个 4X4 的矩阵,默认都是 0 。

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

然后又定义了一个指针数组 p。

第一个 for 循环中:p[0] 存储 a[0][0] 的地址。p[1] 存储 a[1][0] 的地址。p[2] 存储 a[2][0] 的地址。p[3] 存储 a[3][0] 的地址。

第二个 for 循环中:

i = 0 时,

*(p[i] + i) = 1 ,表示 *(p[0]+0) ,表示 第一行第一个元素修改值为 1。 *(p[i] + 4 - (i + 1)) = 1 ,表示 *(p[0]+3) , 表示第一行第四个元素修改值为 1。

i = 1 时,

*(p[i] + i) = 1 ,表示 *(p[1]+1) ,表示 第二行第二个元素修改值为 1。 *(p[i] + 4 - (i + 1)) = 1 ,表示 *(p[1]+2) , 表示第二行第三个元素修改值为 1。

i = 2 时,

*(p[i] + i) = 1 ,表示 *(p[2]+2) ,表示 第三行第三个元素修改值为 1。 *(p[i] + 4 - (i + 1)) = 1 ,表示 *(p[2]+2) , 表示第三行第二个元素修改值为 1。

i = 3 时,

*(p[i] + i) = 1 ,表示 *(p[3]+3) ,表示 第四行第四个元素修改值为 1。 *(p[i] + 4 - (i + 1)) = 1 ,表示 *(p[3]+0) , 表示第四行第一个元素修改值为 1。

第三个 for 循环,打印这个矩阵,所以最终结果为:

1 0 0 1

0 1 1 0

0 1 1 0

1 0 0 1

[11-4]

找出最小字符串。输出多个字符串中最小的字符串。请填空。

 const char *st[] = {"bag", "good", "This", "are", "zoo", "park"};const char *smin = _________;for (int i = 1; i < 6; i++)if (_________ < 0)smin = st[i];printf("The min string is %s \n",_________ );

答:

*st

strcmp(st[i], smin)

smin

解析:

首先定义了一个字符指针数组,想找到里面的最小字符串,首先取第一个字符串赋值给 smin,所以 *smin = *st,然后循环中依次比较字符串大小,strcmp(st[i], smin) <0 ,那么就取 st[i] 赋给 smin,循环结束后打印 smin 即可。

[11-5]

查找最高分。输入 n(n<=10)个成绩,查找最高分并输出。请填空。

#include <stdio.h>
int *GetMax(int score[], int n);
int main(void)
{int i, n, score[10], *p;scanf("%d", &n);for (i = 0; i < n; i++)scanf("%d", &score[i]);p = _____________;printf("Max:%d\n", *p);return 0;
}
int *GetMax(int score[], int n)
{int i, temp, pos = 0;temp = score[0];for (i = 0; i < n; i++)if (score[i] > temp){temp = score[i];pos = i;}return _____________;
}

答:

GetMax(score, n)

score + pos 或者 &score[pos]

解析:

就是定义一个函数,找到数组中的最大值,返回它的地址。所以第一个空调用函数,参数传入数组和 n 的值。第二个空,就是函数中返回结果。数组的本质就是存储数组的基地址,加上 pos 即可。

[11-6]

输出链表中不及格学生的学号和成绩。已建立学生"英语"课程的成绩链表(成绩存于 score 域中,学号存于 num 域中),下列函数的功能是输出不及格学生的学号和成绩。请填空。

void require(struct student *head)
{struct student *p;if (head != NULL){____________;while (p != NULL){if (____________)printf("%d%.1f\n", p->num, p->score);p = p->next;}}
}

答:

p = head

p->score < 60

解析:

第一个空将 head 赋值给 p,第二个空判断成绩是否及格。

程序设计题

[11-1]

输出月份英文名:输入月份,输出对应的英文名称。要求用指针数组表示 12 个月的英文名称。例如,输入 5 ,输出 May。试编写相应程序。
答案代码:

#include <stdio.h>
char *getmonth(int month);
int main() {// 习题(11.3.1)char *p;int n;printf("input n:");scanf("%d", &n);p = getmonth(n);if (p == NULL)printf("wrong input!\n");elseprintf("%s\n", p);return 0;
}
char *getmonth(int month) {char *a[12] = {"January",   "February", "March",   "April","May",       "June",     "July",    "August","September", "October",  "November"};if (month > 0 && month < 13) {return a[--month];} elsereturn 0;
}

运行结果:

[11-2]

查找星期:定义一个指针数组,将下表的星期信息组织起来,输入一个字符串,在表中查找,若存在,输出该字符串在表中的序号,否则输出 -1。试编写相应程序。
序号 星期

0 Sunday

1 Monday

2 Tuesday

3 Wednesday

4 Thurday

5 Friday

6 Saturday

答案代码:

#include <stdio.h>
#include <string.h>
int main()
{// 习题(11.3.2)char *p[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};char s[10];printf("input string:");scanf("%s", s);int i = 0, j = -1;for (i = 0; i < 7; i++){if (!strcmp(p[i], s)){j = i;break;}}printf("%d\n", j);return 0;
}

运行结果:

[11-3]

计算最长的字符串长度:输入 n(n<10)个字符串,输出其中最长字符串的有效长度。要求自定义函数 int max_ len(char *s[], int n),用于计算有 n 个元素的指针数组 s 中最长的字符串的长度。试编写相应程序。
答案代码:

#include <stdio.h>
#include <string.h>
int max_len(char *s[], int n);
int main()
{// 习题(11.3.3)int i, n;char *s[10];char a[10][100];printf("input n(n<10):");scanf("%d", &n);printf("input %d  string :\n", n);for (i = 0; i < n; i++){scanf("%s", a[i]);s[i] = a[i];}printf("%d\n", max_len(s, n));return 0;
}
int max_len(char *s[], int n)
{int i, j = 0;for (i = 0; i < n; i++){if (strlen(s[i]) > strlen(s[j])){j = i;}}return strlen(s[j]);
}

运行结果:

[11-4]

字符串的连接:输入两个字符串,输出连接后的字符串。要求自定义函数 char *strcat(char *s, char *t), 将字符串 t 复制到字符串 s 的末端,并且返回字符串 s 的首地址。试编写相应程序。
答案代码:

#include <stdio.h>
char *strcat(char *s, char *t);
int main()
{// 习题(11.3.4)char s[80], t[80];printf("input 1 string s:");gets(s);printf("input 2 string t:");gets(t);printf("%s\n", strcat(s, t));return 0;
}
char *strcat(char *s, char *t)
{int i = 0;int j = 0;while (s[i] != '\0'){i++;}while (t[j] != '\0'){s[i] = t[j];i++;j++;}return s;
}

运行结果:

[11-5]

指定位置输出字符串:输入一个字符串后再输入两个字符,输出此字符串中从与第 1 个字符匹配的位置开始到与第 2 个字符匹配的位置结束的所有字符。例如,输入字符串 "program" 与 2 个字符 "r" 和 "g" 后,输出 "rog" 。要求自定义函数 `char *match(char *s, char ch1, char ch2)` 返回结果字符串的首地址。试编写相应程序。
答案代码:

#include <stdio.h>
#include <string.h>
char *match(char *s, char ch1, char ch2);
int main()
{// 习题(11.3.5)char s[100], *p;char ch1, ch2;printf("input string:");scanf("%s", s);getchar();printf("input two char:");scanf("%c %c", &ch1, &ch2);p = match(s, ch1, ch2);if (p != NULL)printf("%s\n", p);elseprintf("Not found!\n");return 0;
}
char *match(char *s, char ch1, char ch2)
{char c[100], *p;int i = 0;int j = 0;int start = -1;int end = -1;int k;while (s[i] != '\0'){if (s[i] == ch1) // 找到起始下标{start = i;}if (s[i] == ch2) //找到结束下标{end = i;break; // 如果找到了,就可以直接结束while循环了。}i++;}if (start >= 0 && start <= end){// 遍历 start到 end的字符k = start;while (k <= end){c[j] = s[k];k++;j++;}c[j] = '\0';p = c;return p;}else{return NULL;}
}

运行结果:

[11-6]

查找子串:输入两个字符串 s 和 t ,在字符串 s 中查找子串 t ,输出起始位置,若不存在,则输出 -1。要求自定义函数 char *search(char *s, char *t)返回子串 t 的首地址,若未找到,则返回 NULL 。试编写相应程序。
答案代码:

#include <stdio.h>
#include <string.h>
char *search(char *s, char *t);
int main()
{// 习题(11.3.6)char s[100], t[100], *p;printf("input  string:");scanf("%s", s);printf("input substring:");scanf("%s", t);p = search(s, t);if (p != NULL){printf("%ld\n", p - s);}else{printf("-1\n");}return 0;
}
char *search(char *s, char *t)
{int size_t = strlen(t), size_s = strlen(s), T, i, j;char *p = NULL;for (i = 0; i <= (size_s - size_t); i++){p = s + i;T = 1;for (j = 0; j < size_t; j++){if (*p != *(t + j)){T = 0;break;}p++;}if (T == 1)break;}if (T == 0)return NULL;elsereturn s + i;
}

运行结果:

[11-7]

奇数值结点链表:输入若干个正整数(输入 -1 为结束标志)建立一个单向链表,头指针为 L ,将链表 L 中奇数值的结点重新组成个新的链表 NEW ,并输出新建链表的信息。试编写相应程序。
答案代码:

#include <stdio.h>
#include <stdlib.h>
struct ListNode
{int data;struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *getodd(struct ListNode **L);
void printlist(struct ListNode *L);
int main()
{// 习题(11.3.7)struct ListNode *L, *Odd;L = readlist();Odd = getodd(&L);printlist(Odd);printlist(L);return 0;
}
void printlist(struct ListNode *L)
{struct ListNode *p = L;while (p){printf("%d ", p->data);p = p->next;}printf("\n");
}
struct ListNode *readlist()
{int data;                            // 输入数据int size = sizeof(struct ListNode); // 单个链表结点占据的内存struct ListNode *head, *tail, *p;head = tail = NULL;printf("input number:");scanf("%d", &data);while (data != -1){p = (struct ListNode *)malloc(size);p->data = data;p->next = NULL;if (head == NULL){head = p;}else{tail->next = p;}tail = p;scanf("%d", &data);}return head;
}
struct ListNode *getodd(struct ListNode **L)
{int data;int size = sizeof(struct ListNode);struct ListNode *head, *tail, *pNew; // 链表Newstruct ListNode *ptr1, *ptr2;head = tail = NULL;// L链表的head是奇数while (*L != NULL && (*L)->data % 2 != 0){data = (*L)->data;// 将L链表的奇数重新组成一个新的链表pNew = (struct ListNode *)malloc(size);pNew->data = data;pNew->next = NULL;if (head == NULL){head = pNew;}else{tail->next = pNew;}tail = pNew;// 删除L链表的奇数ptr2 = *L;*L = (*L)->next;free(ptr2);}if (*L == NULL){return NULL;}// L链表的head非奇数ptr1 = *L;ptr2 = (*L)->next;while (ptr2 != NULL){data = ptr2->data;if (data % 2 != 0){// 将L链表的奇数重新组成一个新的链表pNew = (struct ListNode *)malloc(size);pNew->data = data;pNew->next = NULL;if (head == NULL){head = pNew;}else{tail->next = pNew;}tail = pNew;// 删除L链表的奇数ptr1->next = ptr2->next;free(ptr2);}else{ptr1 = ptr2;}ptr2 = ptr1->next;}return head;
}

运行结果:

[11-8]

删除结点:输入若干个正整数(输入 -1 为结束标志)建立一个单向链表,再输入一个整数 m ,删除链表中值为 m 的所有结点。试编写相应程序。

答案代码:

#include <stdio.h>
#include <stdlib.h>
struct ListNode
{int data;struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *deletem(struct ListNode *L, int m);
void printlist(struct ListNode *L);
int main()
{// 习题(11.3.8)/*删除结点:输入若干个正整数(输入 -1 为结束标志)建立一个单向链表,再输入一个整数 m ,删除链表中值为 m 的所有结点。*/int m;struct ListNode *L = readlist();printf("input m:");scanf("%d", &m);L = deletem(L, m);printlist(L);return 0;
}
void printlist(struct ListNode *L)
{struct ListNode *p = L;while (p){printf("%d ", p->data);p = p->next;}printf("\n");
}
struct ListNode *readlist()
{int data;int size = sizeof(struct ListNode);struct ListNode *head, *tail, *p;head = tail = NULL;printf("input number:");scanf("%d", &data);while (data != -1){p = (struct ListNode *)malloc(size);p->data = data;p->next = NULL;if (head == NULL){head = p;}else{tail->next = p;}tail = p;scanf("%d", &data);}return head;
}
struct ListNode *deletem(struct ListNode *L, int m)
{struct ListNode *ptr1, *ptr2;//要被删除结点为表头结点while (L != NULL && L->data == m){ptr2 = L;L = L->next;free(ptr2);}// 链表空if (L == NULL){return NULL;}// 要被删除结点为非表头结点ptr1 = L;ptr2 = L->next; // 从表头的下一个结点搜索所有符合删除要求的结点while (ptr2 != NULL){if (ptr2->data == m) // ptr2所指结点符合删除要求{ptr1->next = ptr2->next;free(ptr2);}else{ptr1 = ptr2; // ptr1后移一个结点}ptr2 = ptr1->next; // ptr2指向ptr1的后一个结点}return L;
}

运行结果:

二.第十二章(文件)

选择题

[12-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

[12-2]

缓冲文件系统的文件缓冲区位于( )。
A.磁盘缓冲区中

B.磁盘文件中

C.内存数据区中

D.程序文件中

答:C

解析:

文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间

[12-3]

定义 FILE *fp; 则文件指针 fp 指向的是( )。
A.文件在磁盘上的读写位置

B.文件在缓冲区上的读写位置

C.整个磁盘文件

D.文件类型结构

答:D

解析:

语句 FILE *fp; ,定义了一个 FILE 结构指针, FILE 是 C 语言为了具体实现对文件的操作而定义的一个包含文件操作相关信息的结构类型。

[12-4]

若以 “a+” 方式打开一个已存在的文件, 则以下叙述正确的是( )。
A.文件打开时,原有文件内容不被删除,位置指针移到文件末尾,可执行添加和读操作

B. 文件打开时,原有文件内容不被删除,位置指针移到文件开头,可执行重写和读操作

C.文件打开时,原有文件内容被删除,只可执行写操作

D.以上各种说法都不正确

答:A

解析:

"a+" 的打开模式,打开文本文件进行读/写/追加。

[12-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 是正确的。

填空题

[12-1]

文件的三大特征是( )、数据长度不定和数据按顺序存取。
答:数据长久保存

解析:

文件是保存在外在存储器上的一组数据的有序集合。文件的特点是数据长久保存,数据长度不定,数据按顺序存取。

[12-2]

根据数据存储的编码形式,C 语言中处理的数据文件通常为( )文件和( )文件两种。
答:

文本文件

二进制文件

解析:

在 C 语言中,按照存储的编码形式,数据文件可以分为文本文件和二进制文件两种。文本文件是以字符 ASCII 码值进行存储与编码的文件,其文件的内容就是字符。二进制文件是存储二进制数据的文件。

[12-3]

判断文件指针是否已经到了文件尾部的函数是( )。
答:feof()

解析:

feof() ,用于判断 fp 指针是否已经到文件末尾,即读文件是否读到了文件结束的位置。其调用格式为:feof(fp); 该函数成功返回 1 表示已经到了文件结束位置,0 表示文件未结束。

[12-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" 就可以。

第二个空,就是逐个读取字符。

[12-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文件中。

程序设计题

[12-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++;elseother++;}printf("字母:%d,数字:%d,其他:%d\n", letter, digit, other);fclose(fp);return 0;
}

运行结果:

所读文件内容如下:

[12-2]

将实数写入文件:从键盘输入若干实数(以特殊数值-1结束),分别写到一个文本文件中。试编写相应程序。
答案代码:

#include <stdio.h>
#include "stdlib.h"
int main()
{// 习题(12.3.2)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;
}

运行结果:

写入目标文件:

[12-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 = 0;}if (ch2 == '\n'){row2++;array2 = 0;}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;
}

两个文件的内容相同:

运行结果:

两个文件的内容不同:

运行结果:

[12-4]

将文件中的数据求和并写入文本文件尾:文件 Int _Data.dat 中存放了若干整数,将文件中所有数据相加,并把累加和写入该文件的最后。试编写相应程序。
答案代码:

#include <stdio.h>
#include <stdlib.h>
int main()
{// 习题(12.3.4)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 文件中的内容:

[12-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)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 文件内容如下:

运行结果:

[12-6]

删除文件中的注释:将 C 语言源程序( hello.c)文件中的所有注释去掉后存入另一个文件(new_ hello.c)。 试编写相应程序。
答案代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{// 习题(12.3.6)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 文件对比:

[12-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 更改后:

 总结

      本篇文章为本专栏的最后一篇文章,本专栏以讲解​《C语言程序设计》(浙大版)课后习题为主要内容,以如有疑问或提供意见,请指出,谢谢!!!

   文章内容参考: 程序咖

   如想观看讲解视频或解析请参考:C语言程序设计第4版(浙大版)何钦铭颜晖著 (chengxuka.cn)程序咖XR实验室是程序咖平台旗下的前沿科技沉浸式面试准备和学习实验室。瞄准「Web3.0」、「元宇宙」、「区块链」、「NFT」、「数字孪生」、「VR/AR/XR」、「DAO」等前沿科技沉浸式课程,带给您最好的学习体验,提升您的职场竞争力。icon-default.png?t=N7T8https://www.chengxuka.cn/#/mooc/outline?_id=39&title=C%25E8%25AF%25AD%25E8%25A8%2580%25E7%25A8%258B%25E5%25BA%258F%25E8%25AE%25BE%25E8%25AE%25A1%25E7%25AC%25AC4%25E7%2589%2588%28%25E6%25B5%2599%25E5%25A4%25A7%25E7%2589%2588%29%25E4%25BD%2595%25E9%2592%25A6%25E9%2593%25AD%25E9%25A2%259C%25E6%2599%2596%25E8%2591%2597

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/595719.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

达梦DMHS-Manager工具安装部署

目录 1、前言 1.1、平台架构 1.2、平台原理 2、环境准备 2.1、硬件环境 2.2、软件环境 2.3、安装DMHS 2.3.1、源端DMHS前期准备 2.3.2、源端DMHS安装 2.3.3、目的端DMHS安装 3、DMHS-Manager客户端部署 3.1、启动dmhs web服务 3.2、登录web管理平台 4、添加DMHS实…

Linux系统基础知识

​ 一、Linux基础 1、简介 严格来讲,Linux这个词本身只表示Linux内核,但实际上人们已经习惯了用Linux来形容整个基于Linux内核的操作系统。 2、系统特点 开源(源代码可见)免费(Linux系统)注意:开源不一定免费安全性稳定可移植性好高性能(服务端没有图形页面)3、发…

list的使用

前言 我们前面已经对string和vector进行了学习使用&#xff0c;以及对他们的底层进行了模拟实现&#xff01;本期我们继续学习STL的另外一个容器---list。 本期内容介绍 什么是list&#xff1f; list的常用接口 什么是list? 还是来看看官方的文档说明&#xff01; 这里通过…

基于springboot实现教师人事档案管理系统项目【项目源码+论文说明】

基于springboot实现在线商城系统演示 摘要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本ONLY在线商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理…

如何客观评价5G的现状?

前几天&#xff0c;在知乎上看到一个帖子&#xff0c;热度挺高&#xff1a; 看了一下帖子的回答&#xff0c;基本上都在骂5G。 作为通信行业从业者&#xff0c;我说说我自己的看法。大家姑且听听&#xff0c;一起交流一下。 我们目前所处的这个时代&#xff0c;有一个很大的特点…

python标准数据类型--列表常用方法

在Python中&#xff0c;列表&#xff08;List&#xff09;是一种非常常用的数据类型&#xff0c;用于存储一组有序的元素。Python提供了许多内置方法来操作列表&#xff0c;使得对列表的处理变得非常灵活和便捷。在本篇博客中&#xff0c;我们将介绍一些常用的列表方法&#xf…

《QT实用小工具·十二》邮件批量发送工具

1、概述 源码放在文章末尾 该项目实现了邮件的批量发送&#xff0c;如下图所示&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef SMTPCLIENT_H #define SMTPCLIENT_H#include <QtGui> #include <QtNetwork> #if (QT_VERSION > QT_VERSION_CHECK(5,0,…

Redis中的持久化

持久化 .RDB手动触发save命令bgsave命令 自动触发bgsave的具体流程RDB的处理保存压缩校验 RDB的优缺点 AOF命令写入文件同步重写机制启动时恢复数据 本章重点回顾 . RDB RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发 手动触发…

约数与倍数-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第45讲。 约数与倍数&#…

C语言底层知识------文件操作

清明第二天&#xff0c;为了假期不这么放纵&#xff0c;现在又来更新一篇文件操作的文章&#xff0c;关于文件操作比较底层&#xff0c;这里我们就了解一下有关函数使用和一些基础概念即可&#xff0c;无需深究函数是如何实现。 常常会回顾努力的自己&#xff0c;所以要给自己的…

Redis各个方面入门详解

目录 一、Redis介绍 二、分布式缓存常见的技术选型方案 三、Redis 和 Memcached 的区别和共同点 四、缓存数据的处理流程 五、Redis作为缓存的好处 六、Redis 常见数据结构以及使用场景 七、Redis单线程模型 八、Redis 给缓存数据设置过期时间 九、Redis判断数据过期的…

在线文档编辑工具好用在哪?中小型企业需要它吗?

随着科技的飞速发展&#xff0c;我们的工作方式也在不断地改变。在这个融合的数字时代&#xff0c;使我们的工作变得更加简单高效的在线文档编辑工具正得到越来越广泛的应用。 那么&#xff0c;首先我们来看看在线文档编辑工具到底好用在哪里&#xff1f;与传统的文档编辑方式相…