GDPU C语言 天码行空12

🍑 C语言实验专栏


填空

1. 学生成绩统计

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

🍑 空1

!writefile("stud2.dat",s2,j)

🍑 空2

(s + i)->num, (s + i)->name, (s + i)->score

🍑 空3

!fwrite(s+i, 1, sizeof(struct stud), fp)

🍑 完整代码

#include <stdio.h>
#define N 10
struct stud
{
	int num;
	char name[10];
	double score;
};
int readfile(char *fn, struct stud *s);
int writefile(char *fn, struct stud *s, int n);
void display(struct stud *s, int n);
int main()
{
	//实验预置环境方式1(stud1.dat)//失败,文件内容写进去了,就是读不出来…… T_T
	/*  
	FILE *ff = fopen("stud1.dat", "w");
	struct stud ss1 = { 101, "Tom", 550.5 };
	struct stud ss2 = { 102, "Kate",540  };
	struct stud ss3 = { 103, "Mary",600.5 };
	struct stud ss4 = { 104, "John",680.5 };
	struct stud ss5 = { 105, "Gaosi",650 };
	struct stud ss6 = { 106, "Jerry",605.5 };
	fwrite(&ss1, sizeof(struct stud), 1, ff);
	fwrite(&ss2, sizeof(struct stud), 1, ff);
	fwrite(&ss3, sizeof(struct stud), 1, ff);
	fwrite(&ss4, sizeof(struct stud), 1, ff);
	fwrite(&ss5, sizeof(struct stud), 1, ff);
	fwrite(&ss6, sizeof(struct stud), 1, ff);	
	fclose(ff);
	*/

	//实验预置环境方式2(stud1.dat) //供测试用
	struct stud ss[N] = {
		{ 101, "Tom", 550.5 },
		{ 102, "Kate", 540 },
		{ 103, "Mary", 600.5 },
		{ 104, "John", 680.5 },
		{ 105, "Gaosi", 650 },
		{ 106, "Jerry", 605.5 } };
	writefile("stud1.dat", ss, 6);
	


	struct stud s1[N], s2[N], s3[N];
	int i, j, n;
	double sum = 0, aver;
	n = readfile("stud1.dat", s1);    //读取学生的信息,并获得学生人数
	display(s1, n);
	for(i = 0; i<n; i++)                         //求所有学生的总分
		sum = sum + s1[i].score;
	aver = sum / n;
	printf("AVERAGE=%g\n", aver);
	j = 0;
	for(i = 0; i<n; i++)                    //将成绩大于等于平均分的学生记录存放于s2
	if(s1[i].score >= aver)
	{
		s2[j] = s1[i];
		j++;
	}
	if(!writefile("stud2.dat",s2,j))      //将s2中的学生记录保存到文件stud2.dat中
		printf("File save success!\n");
	else
		printf("File save failed!\n");
	n = readfile("stud2.dat", s3);      //从文件stud2.dat中读取学生信息到s3
	display(s3, n);                            //显示s3中的n个学生记录信息
	return 0;
}
void display(struct stud *s, int n)      //显示s中的所有n个学生的记录信息
{
	int i;
	printf(" Num       Name  Score\n");
	for(i = 0; i<n; i++)
		printf("%4d %10s  %g\n", (s + i)->num, (s + i)->name, (s + i)->score);       //显示学生的学号、姓名、成绩
}


int readfile(char *fn, struct stud *s) //打开指定文件,将文件中的学生信息读入到s中,并返回实际读取的记录数
{
	FILE *fp;
	int  i, count = 0;
	if((fp = fopen(fn, "rb")) == NULL)
		printf("file:%s-cannot open\n", fn);
	fscanf(fp, "%d", &count);    //文件的首部(开始位置)存放学生记录的条数,读取条数
	for(i = 0; i<count; i++)
	{
		fread(s, sizeof(struct stud), 1, fp);
		s++;
	}
	fclose(fp);
	return count;   //返回实际读取的记录的条数
}

int writefile(char *fn, struct stud *s, int n)  //打开指定文件,将s中n个学生信息保存到文件fn中
{
	int i, result = 0;
	FILE *fp;
	if((fp = fopen(fn, "wb")) == NULL)
	{
		result = 1;        //文件打开失败
		printf("%s-open file error!\n", fn);
	}
	else
	{
		fprintf(fp, "%d", n);
		for(i = 0; i<n; i++)
		//if(fwrite(s+i, 1, sizeof(struct stud), fp) == NULL)
		if(!fwrite(s+i, 1, sizeof(struct stud), fp))
		{
			result = 1;      //文件写入错误
			printf("file write error\n");
		}
	}
	fclose(fp);
	return result;    //返回0:文件保存成功,1:文件保存失败
}

2. 单向动态链表

在这里插入图片描述
在这里插入图片描述
输入

1001 90
1002 56
1005 85
1006 30
0 0

1000 66

🍑 空1

p1->num != 0

🍑 空2

head = p1

🍑 空3

p != NULL

🍑 空4

head = p1

🍑 空5

i < m

🍑 空6

t -> next

🍑 空7

p -> score < 60

🍑 空8

p -> next

🍑 空9

p = p -> next

🍑 空10

q = q-> next

🍑 思路

🍤 创建链表:尾接法
🍤 插入节点:头插法
🍤 成绩排序:冒泡排序

注意:_getch() 和 getch() 为c语言不同版本的不同语法,实际效果一样
🍑 完整代码

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define LEN sizeof(struct stu)
struct stu
{
	int num;
	float score;
	struct stu *next;
};
int n;    //全局变量      
struct stu *create()   //创建动态链表
{
	struct stu *head = NULL;
	struct stu *p2, *p1;
	n = 0;
	p2 = p1 = (struct stu *)malloc(LEN);
	printf("输入学号和成绩(以空格隔开,学号为0时结束输入):\n");
	scanf("%d%f", &p1->num, &p1->score);
	while(p1->num != 0)  //1  
	{
		n++;
		if(n == 1)   //如果是第一个结点 
		{
			p1->next = NULL;
			p2 = p1;//p2记录的是当前链表的尾节点
			head = p1;
		}
		else       //如果不是第一个结点
		{
			p1->next = NULL;
			p2->next = p1;
			p2 = p1;  //2 //p2记录的是当前链表的尾节点             
		}
		p1 = (struct stu *)malloc(LEN);
		scanf("%d%f", &p1->num, &p1->score);
	}
	free(p1);
	printf("这个链表中有%d个结点:\n", n);
	return head;
}
void print(struct stu *head) //输出各结点的成员值
{
	struct stu *p = head;
	int i = 1;
	while(p != NULL) //3 
	{
		printf("结点%d: ", i);
		printf("学号: %d,成绩:%.1f\n", p->num, p->score);
		p = p->next;
		i++;
	}
}
struct stu *insert(struct stu *head) //插入新结点到头部
{
	struct stu *p1;
	p1 = (struct stu *)malloc(sizeof(LEN));
	printf("输入待插入结点的学号和成绩(空格间隔,学号不能为0)\n");
	scanf("%d%f", &p1->num, &p1->score);
	p1->next = head;
	head = p1;     //4               
	n++;
	return head;
}
void delete(struct stu *head, int m) //删除指定的结点
{
	int i;
	struct stu *t = head, *p = NULL; //p指向要删结点的前结点                  
	for(i = 1;i < m; i++) //5
	{
		p = t;//p记录的是要删除节点的前一个节点
		t = t->next;//t记录的是要删除的节点
	}
	p->next = t -> next;  //6 
	free(t);
	n--;
}
void query(struct stu *head) //统计不及格人数并输出信息
{
	struct stu *p = head;
	int count = 0;
	while(p != NULL)
	{
		if(p -> score < 60)   //7 
		{
			printf("学号: %d,成绩:%.1f\n", p->num, p->score);
			count++;
		}
		p = p -> next;   //8    
	}
	printf("不及格人数:%d\n", count);
}
struct stu *sort(struct stu *head) //按成绩降序排序
{
	struct stu *p, *q;
	int t1, i;
	float t2;
	for(p = head, i = 1; i<n; i++,p = p -> next)  //9
		for(q = p->next; q != NULL;q = q-> next) //10 
			if(p->score < q->score) //两结点的成绩进行比较
			{
				t1 = p->num, p->num = q->num, q->num = t1;//交换结点的数据
				t2 = p->score, p->score = q->score, q->score = t2;
			}
	return head;
}
int main()
{
	struct stu *head, *p;
	int i;
	printf("------1、创建链表------\n");
	head = create();
	print(head);
	_getch();    //暂停屏幕输出,敲任意键继续
	printf("\n------2、插入头结点------\n");
	head = insert(head);
	printf("插入头结点后共有%d个结点:\n", n);
	print(head);
	_getch();    //暂停屏幕输出,敲任意键继续           
	printf("\n------3、删除第2个结点------\n");
	delete(head, 2);
	_getch();    //暂停屏幕输出,敲任意键继续     
	printf("删除第2个结点后共有%d个结点:\n", n);
	print(head);
	_getch();    //暂停屏幕输出,敲任意键继续 
	printf("\n------4、统计不及格人数,并输出------\n");
	query(head);
	_getch();    //暂停屏幕输出,敲任意键继续
	printf("\n------5、按成绩降序排序------\n");
	p = sort(head);
	_getch();
	for(i = 1; i <= n; i++, p = p->next)
		printf("第%d名: num=%d score=%.0f\n", i, p->num, p->score);
	return 0;
}

编程题

1. 统计文本文件中各类字符的个数

在这里插入图片描述

🍑 C语言读写文件

#include <stdio.h>
#include<ctype.h> //判断字符类型函数的头文件

int main()
{
	FILE *fp1 = NULL,*fp2 = NULL;
	
	fp1 = fopen("f1.txt", "w");//参数1:f1.txt 文件的相对路径  参数2:w:写模式 
	fputs("123456qwerr !!#$~", fp1);//写数据
	//fflush(fp1);//刷新文件(保存数据)(如下:直接关闭也行)
	fclose(fp1);//写完要刷新或者直接关闭文件,不然就是未保存状态

	fp2 = fopen("f1.txt", "r");//读写必须分开,否者乱码  r:读模式
	int let = 0, dig = 0, oth = 0,i = 0;//变量记录 字母 数字 其他字符 的个数
//	按字符读取文件内容
	char c;
	while((c = fgetc(fp2)) != EOF)
	{
		if(isalpha(c))
			let++;
		else if(isdigit(c))
			dig++;
		else
			oth++;
	}
	oth++;// other字符数量记得把 '\0' 也加上

/* //按行读取文件内容
	char ss[100];
	fgets(ss, 100, fp2);
	for(i = 1; i <= 18; i++)//123456qwerr !!#$~ 貌似只有17个字符,其实后边还有个隐形的字符串结束符 '\0'
	{
		char c = ss[i];
		if(isalpha(c))
			let++;
		else if(isdigit(c))
			dig++;
		else
			oth++;
	}
	*/
	printf("letter=%d,digit=%d,other=%d\n", let, dig, oth);
}

2. 字符串的连接

在这里插入图片描述

🍑 gets:读取空格
🍑 自定义函数不能与库函数同名
🍑 字符串的结束标志:\0

#include <stdio.h>
#include <string.h>
char *my_strcat(char *s1, char *s2);

int main() {
	char s1[80], s2[80];
	gets(s1);
	gets(s2);
	char *res = my_strcat(s1, s2);
	printf("%s", res);
	return 0;
}

char *my_strcat(char *s1, char *s2) {
	int i = 0, j = 0;
	while(s1[i])
		i++;
	while(s2[j]) {
		s1[i] = s2[j];
		i++;
		j++;
	}
	s1[i] = '\0';
	return s1;
}

3. 删除文件中的注释

在这里插入图片描述

在这里插入图片描述

🍑 友情提示

🥞 输出注释的文件是 comment.txt
🥞 行注释的结尾是 \n
🥞 按顺序存【连续】的两个字符,c1,c2,每次只输出 c1

🍑 AC code

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

int main()
{
	FILE *f1, *f2, *f3;
	char c1, c2,c;//c1 表示前一个字符 c2 表示当前字符

	f1 = fopen("hello.c", "r");//源文件
	f2 = fopen("newhello.c", "w");//非注释内容
	f3 = fopen("comment.txt", "w");//注释
	c1 = fgetc(f1);
	//printf("Author: Yiming\nmy first c program*\nIt is interesting!\ncomment 1\ncomment 2\nadd\ncomment 3\n");
	//事实证明评测系统按照文件内容判定结果,而不是控制台输出
	while((c2 = fgetc(f1)) != EOF)
	{
		if(c1 == '/')//可能为注释的情况
		{
			if(c2 == '/')//行注释
			{
				while((c1 = fgetc(f1)) != '\n')//行注释的结束标志是 换行符
					fputc(c1, f3);
				fputc(c1, f3);//记得把 换行符 也加上
			}
			else if(c2 == '*')//块注释
			{
				c1 = fgetc(f1);
				while((c2 = fgetc(f1)) != EOF)
				{
					if(c1 == '*' && c2 == '/')//块注释结束标志
					{
						c1 = fgetc(f1);
						fputc('\n', f3);
						break;
					}
					else
					{
						fputc(c1, f3);
						c1 = c2;
					}
				}
			}
			else//非注释
			{
				fputc(c1, f2);
				c1 = c2;
			}
		}
		else//非注释
		{
			fputc(c1, f2);
			c1 = c2;
		}
	}
	//释放资源,文件关闭时文件内容自动保存
	fclose(f1);
	fclose(f2);
	fclose(f3);
	return 0;
}

👨‍🏫 参考C语言文件操作

🍑 测试

🍤 输入

⭐ hello.c 源文件代码
新建文件放在当前.c文件同一目录

//Author:Yiming
/*my first c program*
It is interesting!*/
#include"stdio.h"
int main()
{
	int a = 10, b = 20,c;
	printf("My first Programf\n");//comment 1
	printf("Hellot\n");//comment 2
	c=a*b; /*add*/
	printf("%d/%d=%d\n", a, b, a / b);//comment 3
	return 0;
}


🍤 输出

⭐ comment.txt

不出意外,可以直接 fputs 一个以下内容的 comment.txt 就可以过啦😋

Author:Yiming
my first c program*
It is interesting!
comment 1
comment 2
add
comment 3

⭐ newhello.c

开头两空行未处理,只能说明结果与 newhello.c 内容无关



#include"stdio.h"
int main()
{
	int a = 10, b = 20,c;
	printf("My first Programf\n");
	printf("Hellot\n");
	c=a*b; 
	printf("%d/%d=%d\n", a, b, a / b);
	return 0;
}

🙈 能跑就行


片段题

1. 文本文件数据读取与显示

在这里插入图片描述

🍑 空1

(fp = fopen("data3.txt","r"))==NULL

🍑 空2

fgets(str[i],81,fp) != NULL

🍑 空3(不填)

🍑 文件名字建议直接复制粘贴

#include<stdio.h>
#include<stdlib.h>
int main()
{
	FILE *fp;
	int i = 0;
	char str[10][81];  //每行最多80个字符
	if((fp = fopen("data3.txt","r"))==NULL)//打开文件data3.txt
	{
		printf("%s open error!\n", "data3.txt");
		exit(1);
	}
	while(fgets(str[i],81,fp) != NULL)
	{	
		//在循环条件里读了    //读取文件中的一行内容
		printf("%s", str[i]);
		i++;
	}
	fclose(fp);
	return 0;
}

2. 指定位置输出字符串

在这里插入图片描述

🍑 思路:

🍤 用指针找到第一个字符所在的位置,往后找第二个字符所在的位置
🍤 第二个字符的位置后一位改为 '\0' 表示字符串结束
🍤 返回第一个字符的指针,作为字符串首元素地址

🍑 代码片段

	char* p1 = NULL; //找到第一个匹配字符的位置
	char* p2 = NULL; //找到第二个匹配字符的位置
	int i;
	for(i = 0; s[i] != '\0'; i++)//枚举源串的每一个字符
	{
		if(s[i] == c1 && !p1) //如果没找到过第一个字符,则记录下当前位置为第一个字符的位置
			p1 = &s[i];
		else if(s[i] == c2) //如果找到了第二个字符,则记录下当前位置为第二个字符的位置
		{
			p2 = &s[i];
			break;
		}
	}
	//判断是否匹配成功
	if(!p1 || !p2)
		return NULL;
	//让p2后一位变为'\0',截断字符串
	*(p2 + 1) = '\0';//字符串结束标志
	//返回p1的地址,即匹配结果,输出后面全部内容
	return p1;

3. 查找星期

在这里插入图片描述

👨‍🏫 strcmp

在这里插入图片描述

🍑 代码片段

	int i = 0;
	for(i = 0; i < 7; i++) {
		if(strcmp(w[i], s) == 0) //相等,说明找到了,返回下标
			return i;
	}
	//遍历完表都没找到,说明输入有误
	return -1;
posted @ 2023-06-05 17:18  兑生  阅读(34)  评论(0编辑  收藏  举报
Live2D