《Linux C编程环境》 课程大实验 及近期练习题:计算器,复写机,目录树创建,批处理执行器,扫雷


​ 之前作业的题了,征求了老师的意见,同意我把个人解析放开公布,再提交作业已经无效了。网上可搜不到这些题。

2021年1月8日更新:删除了部分代码,防止抄袭

2021年1月13日更新:完整内容放至个人博客,感兴趣可以联系我。大一的学习,首先要靠自己努力。

个人博客:ZXJyMHIudG9wL2FydGljbGUvbGludXhwcm9ncmFtbWUv


问题名称:计算器

交互场景:

程序读input.txt文件,逐行完成文件中计算指令,将每一步的执行结果输出到output.txt文件中去。

Input.txt文件内容举例:

123+234*2

对应的output.txt文件内容举例:

357714

思路过程:

C语言最后一章讲了数据持久化——文件,不知道同学们有没有思考下何谓数据持久化?这也是文件的意义。

首先定义文件指针fpr来读取文件,fpw来输出文件,并用标准格式fopen打开,创建文件。失败则有提示语句并退出。

这里注意,题目要求是当前路径下!带盘符这样的路径是绝对路径,你无法保证在其他电脑上运行时,在相应的路径下有一个input文件,所以这里用相对路径!就是在程序运行时的目录下!不需要带盘符等东西。

    if((fpr=fopen("input.txt","r"))==NULL)//读取不需要写入,所以以只读打开{......exit(-1);//使用exit函数需要加头文件<stdlib.h>}if((fpw=fopen("output.txt","w"))==NULL)//输出要以写的方式创建文件......

接着定义字符串数组str和统计的数s,由于题目是计算器,input肯定是第一行一个数,第二行一个运算符再第三行一个数,以此类推,所以我构造了cal函数,里面用switch开关语句来决定进行何种运算。

//c是传入的运算符,表明要做何种运算,s是计算结果char str[20];//用来存文件再向下读一行读到的数字switch(c)//读到了运算符,再往下读一定是数字!{case '+':fgets(str,20,fpr);s+=change(str);break;......}
......//返回值即为计算结果

我们看,第一次是一个数,第二次是一个符号,第三次又是一个数,第四次又是一个符号,我们很容易发现,其实它是第一次一个数,然后就是一个符号一个数,一个符号一个数,于是我们单独处理第一个数,后面就是循环了。

先读取了input第一行,进行了加运算,给s一个初值,因为第一个是单独的数,我们就可以等价于原结果s为0,第一次运算就是0+第一行

s=cal('+',s,fpr);//加运算,s初值为0,返回值即为第一个数了

然后进行while循环,因为文件位置的指针到了下一行,再读取一定是一个运算符,当读取到字符不是NULL说明没结束就继续循环,

while(fgets(str,sizeof(str),fpr))

读到运算符那一行在字符串str里,现在str里有什么?

str[0]='(一个运算符)'
str[1]='\n'//换行会被读入
str[2]='\0'

调用cal函数传递读到的运算符str[0],switch开关进行计算并写入文件,最后fputc加一个换行,至此循环体结束。

 fprintf(fpw,"%d",s=cal(str[0],s,fpr));......

其中计算时还用到一个小自定义的函数change,就是将字符串内容读取并转换成整形return。在cal函数里switch判断做什么运算后再进行一次读取,然后传入change,返回整形的这个数。

......while(s[i]!='\n')//换行会被读入,千万不要写s[i]!='\0'!{xxxxxx}
......

这样程序就完成了,最后fclose关闭文件。

Example Answer:

由于历届大作业题目相似,已删除答案,如有疑问可联系我或翻我博客

问题名称:复写机

交互场景:

程序读取用户的输入,是一个整数n。程序读取input.txt文件,将文件中的每个字符复写n次后,作为output.txt文件的内容写出。

键盘输入举例:

2

Input.txt文件内容举例:

AbcEfg

对应的output.txt文件内容举例:

AAbbccEEffgg

思路过程:

人类的本质是复读机!

这题比第一题简单。与第一题一样,定义文件指针fpr和fpw,读取和创建输入输出文件,失败则有提示语句并退出。

先定义n,题目要求键盘输入n,然后还是while循环,当fgets读取没返回NULL表示没结束就继续循环,读取到内容给字符串数组str,

while(fgets(str,sizeof(str),fpr))

然后构造函数write,传入数组str,文件指针fpw来输出,还有输入的n,

void write(char str[],FILE *fpw,int n)

因为我们已经读了一行内容放入字符串str,所以不必传fpr了,然后在write函数里,while循环,读取str每个字符,只要不是换行符就继续循环,

    while((c=str[j++])!='\n')

然后for循环,输出n次读到的字符到output,结束后没有返回值,

 for(i=0;i<n;i++)fputc(c,fpw);

回到主函数,输出一个换行符,至此循环体结束,这样就能一行一行读取str,再一个一个输出字符n次,最后fclose关闭文件,程序就完成了。

没错,就这么简单

Example Answer:

由于历届大作业题目相似,已删除答案,如有疑问可联系我或翻我博客

问题名称:目录树创建

交互场景:

程序读取用户输入的整数n,在当前目录创建n个子目录目录名依次为“dirx”,其中x为1-n的某个数字,每个目录中均有一个readme.txt文件,文件中的内容均为x这个数字

没得样例

思路过程:

本题是Linux C的题,不再仅仅是C语言的题了。一样先定义文件指针fp,不过只要定义一个输出指针就行了,因为不需要读取文件,一样失败会有提示语句并退出。

首先先输入n,要创建n个子目录名字为dirx,定义字符串path表示创建的目录名,定义字符串name表示创建目录里readme.txt的名字

因为要创建n个子目录,所以就写个for循环做n次,用mkdir函数,内跟路径名和权限代码,windows下不起作用,但Linux操作系统这里用0777表示所有人都有对文件读写执行的权限。路径名path,我们赋了三个字符”dir”,因为最后一位就是1-n顺序的数,所以刚好把for循环的i用上,

scanf("%d",&n);
......
for(i=1;i<=n;i++)
{char path[xx]="dir";
...未完

我首次写代码这里只写了把i赋给path[3],即path[3]=i+'0'//注意字符串的0不是数字0

可是后来想到了问题,如果输入的数不是一位数,而是两位数三位数,这里就会出错了(不可能一位里面存两位数)

于是我想到了函数sprintf,将int型数i转换为字符串类型

sprintf();

然后strcat连接path,这样path就是”dirx”了,x为顺序的数,每次循环都随着i变化,用mkdir函数路径为path建立子文件夹就好了。

strcat(path,num);//num看上面,是i的数字字符
mkdir(path,0777);//在path目录下建一个dirx的文件夹
//因为这里都是在for循环里的!(看上面)

然后要创建文件了,在每个目录底下,于是用strcpy函数先把path拷到name里,再用strcat函数补上”/readme.txt”,这样字符串name里就有”dirx/readme.txt”,’/'表示进目录里面

strcpy(name,path);//此时name="dirx"
strcat(name,"/readme.txt");//此时name="dirx/readme.txt"

这时候再fopen创建文件路径为name,把num也就是那个x输出到文件里,最后fclose,

 if((fp=fopen(name,"w"))==NULL){exit(-1);}fputs(num,fp);//这里不用转为数字,因为即使输出数字字符我们在文件里看到的也是这个数字......

这些都在一个循环里,至此循环体结束,这样做n次循环,也就达到了题目的要求。

我做出修改的就是这题,这里要注意字符串函数的应用,同时要考虑程序会不会类似有bug的情况发生!

Example Answer:

由于历届大作业题目相似,已删除答案,如有疑问可联系我或翻我博客

问题名称:批处理执行器

交互场景:

程序读取cmd.txt文件,将cmd.txt文件中的每行执行的结果收集到output.txt文件中。

Cmd.txt文件内容举例:

pwdls | wc -w

对应的output.txt文件内容举例:

/home/ne/8

思路过程:

批处理执行器,也是Linux C的题目,有读取有输出,定义文件指针fpr和fpw,报错有提示语句并退出,这里多定义一个空文件指针temp,因为接下来要用到popen函数。定义字符串contect来读取cmd执行的结果,定义字符串str读取cmd.txt的行内容。

写一个while循环,只要fgets读到不是NULL就继续,然后用popen开管道调用fork()产生子进程,执行shell运行之前读取到str里的命令,把结果读取到空指针temp中

然后fgets读取temp到字符串connect里,这里connect就是cmd运行的结果了,我们fputs直接写入output文件中,然后pclose关闭管道

 while(fgets(str,sizeof(str),fpr)){temp=popen(str,"r");fgets(xxx);fputs(xxx);pclose(temp);}

至此循环体结束,最后fclose关闭文件,问题就解决了。

如果不明白popen的用途可以看书第七章(我其实也没怎么看书,只是把函数都过一遍,然后要用啥就去看它的函数原型),或者网上搜popen函数学习。

Example Answer:

由于历届大作业题目相似,已删除答案,如有疑问可联系我或翻我博客

作业题结束了,下面另外的题了,之前有位同学问我的,我觉得比较有趣,就拿来分享一下。


问题名称:扫雷

问题描述:

扫雷游戏是一款十分经典的单机小游戏。在nn行mm列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。

现在给出nn行mm列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。

注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。

输入格式

第一行是用一个空格隔开的两个整数nn和mm,分别表示雷区的行数和列数。

接下来nn行,每行mm个字符,描述了雷区中的地雷分布情况。字符’*’表示相应格子是地雷格,字符’?’表示相应格子是非地雷格。相邻字符之间无分隔符。

输出格式

输出文件包含nn行,每行mm个字符,描述整个雷区。用’*’表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。

样例输入 #1

3 3
*??
???
?*?

样例输出 #1

*10
221
1*1

样例输入 #2

2 3
?*?
*??

样例输出 #2

2*1

*21

说明/提示

对于 100\%100%的数据, 1≤n≤100, 1≤m≤1001≤n≤100,1≤m≤100。

思路过程:

​ 准备用一个主函数解决,看输入,先输入两个数定义雷区长宽,然后输入雷区数据,由于是符号’?‘和’*’,所以定义字符串数组s,行为n,列为m+1,因为要放’\0’。然后为了计算一个格子周围8个格子的雷数,我们定义一个整形数组a,把周围包起来,也就是行为n+2,列为m+2。

 int i,j,n,m,x,k,t;scanf("%d %d",&n,&m);int a[n+2][m+2];char s[n][m+1];

例如样例输入1的

*??
???
?*?

在字符串数组s里就是

*??\0
???\0
?*?\0

先把数组a全置为0,然后对于有雷的地方我们在数组a里把它置为1

 for(i=0;i<n+2;i++)for(j=0;j<m+2;j++)a[i][j]=0;for(i=0;i<n;i++)for(j=0;j<m;j++)if(s[i][j]=='*')a[i+1][j+1]++;

对于样例输入1数组a里内容

00000
01000
00000
00100
00000

真正中间3x3才是雷区,周围一圈是包起来的

然后开始运算,对于中间的3x3每个格子,如果是1,那就不动;如果是0,那就要计算雷数,这样就是对于它周围八个格子,如果有1(表明有雷),计数的x就自增,字符串s里就输入这个位置的雷数

这也是为啥数组a要包一圈雷区

 for(i=0;i<n;i++)for(j=0;j<m;j++){if(a[i+1][j+1]==1)continue;x=0;//每次循环置为0for(k=0;k<=2;k++)for(t=0;t<=2;t++)if(a[i+k][j+t]==1)//这边其实是i+1+k,-1<k<1。j同理。x++;s[i][j]=x+'0';}

然后输出就行了

题目就完成了

Example Answer:

#include <stdio.h>
#include<string.h>
int main()
{int i,j,n,m,x,k,t;scanf("%d %d",&n,&m);int a[n+2][m+2];char s[n][m+1];getchar();//上面有一次scanf输入,要吃掉一个换行符,不然下面输入会有换行符到s[0][0]for(i=0;i<n;i++)gets(s[i]);//输入雷区数据for(i=0;i<n+2;i++)for(j=0;j<m+2;j++)a[i][j]=0;//数组a置0for(i=0;i<n;i++)for(j=0;j<m;j++)if(s[i][j]=='*')//雷点置为1a[i+1][j+1]++;for(i=0;i<n;i++)for(j=0;j<m;j++){if(a[i+1][j+1]==1)//如果是1,表明这地方是雷continue;//对于s就不动它,结束本层循环x=0;//计数器置0for(k=0;k<=2;k++)for(t=0;t<=2;t++)if(a[i+k][j+t]==1)//周围8格扫雷x++;//有雷就自增s[i][j]=x+'0';//把雷数的数字字符覆盖掉s内的'?'}for(i=0;i<n;i++)//最后输出{   for(j=0;j<m;j++)printf("%c",s[i][j]);putchar('\n');   }return 0;
}


本来不想写的,可是马上要编程竞赛了,又凑上期末考试,就抽时间发博客了,刚好自己也复习巩固一下算法

看了下历年算法比赛,就六道题,17年还会三道,18年不会了,保佑我今年算法比赛混个奖

祝大家期末考试都取得好成绩!

如果有问题或者错误请见谅,并联系我改正!一起努力学习!

《Linux C编程环境》 课程大实验 及近期练习题:计算器,复写机,目录树创建,批处理执行器,扫雷相关推荐

  1. 上千个国外免费权威优质编程学习课程大放送 —— 提升篇

    随着互联网的发展,像 MIT 和斯坦福等世界名校,都开始在网上公开一些优质的在线免费课程供大家学习.到现在,已经有来自全球共 1000 所左右的学校提供了非常多的优质课程,最有名的平台就是 MOOC. ...

  2. 【华为云技术分享】Linux内核编程环境 (1)

    在上一期中,我们介绍了Linux内核的源码结构,这一期我们介绍Linux内核编程环境,首先介绍的是Linux内核的编译方法. 一.Linux内核编译方法 本期中我们以Linux 4.19.94版内核来 ...

  3. 搭建Linux云编程环境

    仅个人记录可参考 本篇解决你想在一台陌生的电脑上ps.Excel.word.敲代码,却无相应环境而又不想安装各种软件和设置环境变量的烦恼. 获取root权限 解bl锁→修补镜像boot→刷入trwp→ ...

  4. 计算器软件C语言课程设计实验报告,c简单计算器实验报告_相关文章专题_写写帮文库...

    时间:2019-05-15 12:55:15 作者:admin 计算器实验报告 班级: 07计本(1)班 姓名: 王林 学号: 20706031047 指导老师: 韩静 一. 需求分析 (1)制作一个 ...

  5. linux 嵌入式 交叉 环境搭建 实验原理,实验三 嵌入式Linux开发环境的搭建

    南京邮电大学通达学院 实 验 报 告 实验 实验三题目 嵌入式Linux开发环境的搭建 课程名称 嵌入式驱动开发实验 学院 专业 班 实验者学号同做者学号 08002210 姓名 毛骏超 同做者学号 ...

  6. emacs Linux Java编程环境_Linux下搭建用emacs查看代码的开发环境

    在windows下面我们有source in sight可以方便的浏览大工程中的代码,切换到linux环境下开发时,我们也可以搭建一个这样的环境.下面的内容将介绍如何搭建这样一个开发环境(这里我们假设 ...

  7. apue.3与unp在Linux上编程环境搭建

    导读 在学习Unix高级环境编程与Unix网络编程的时候,按照作者的提示操作即可成功的编译运行这两本书提供的源代码,但是如果自己想想在自己的环境里按照书籍学习,也就是在自己的环境里调用作者封装的api ...

  8. Linux配置编程环境+云服务器上传文件

    Java环境配置 Ubuntu https://www.cnblogs.com/lfri/p/10437266.html Centos https://blog.csdn.net/qq_2107771 ...

  9. 【华为云技术分享】Linux内核编程环境 (2)

    在上一期中,我们介绍了Linux内核编译方法,这一期我们用一个例子来介绍如何向Linux内核中增加一个模块. 一.LKM内核模块 LKM是Loadable Kernel Module的缩写,意思是可加 ...

最新文章

  1. GitHub使用指南——建立仓库、建立文件夹、上传图片详细教程
  2. 二叉树的基本特性和二叉树的几种基本操作的机制_关于二叉树,你该了解这些!...
  3. 李宏毅-ELMO、BERT、GPT视频笔记
  4. 原生js实现一个连连看小游戏(一)
  5. java正则表达式中的坑String.matches(regex)、Pattern.matches(regex, str)和Matcher.matches()
  6. HDU1760 A New Tetris Game NP态
  7. 解决JavaScript浮点数(小数) 运算出现Bug的方法
  8. JIT编译对比AOT编译(附图片)
  9. 我从华为身上学到的项目管理经验 -- 设计篇
  10. 计算机主机配置一般有机箱主板cpu,组装台式电脑配置清单
  11. RL 笔记(3)PPO(Proximal Policy Optimization)近端策略优化
  12. 第十一课 区块链常用共识算法介绍
  13. matlab 符号微积分
  14. SerialFeature
  15. java通过jstack命令查询日志深入理解
  16. 【各大公司年会奖品清单】腾讯送直升飞机,网易与日女星度过美好的下午?...
  17. 激光雷达学习笔记-------Ubuntu 18.04 + 思岚科技 A1M8+ ROS 上手使用及基于hector_slam 建图
  18. Android手游外挂入侵----寓攻于守,方能破敌
  19. 清华大学计算机周建宇,一曲高歌征服清华考官
  20. Wireshark的提示

热门文章

  1. 微信公众号html在线编辑器,【微信公众平台工具开发】雷人微信网页编辑器
  2. 【Windows MTU】Windows上最大传输单元MTU值的查看和设置
  3. Win7系统重装账户被禁用的解决方法
  4. 【.net函数式编程】可重复的执行repeatable execution
  5. Web端兼容性测试--浏览器/平台/分辨率
  6. JVAV SE学习总结(01)
  7. 怎样把PDF格式转换成可编辑的PPT幻灯片?
  8. 关于Flutter中使用 webview_flutter: 1.0.6 打开公众号连接只显示标题不显示内容的记录
  9. CSS3各个模块详解
  10. 光环:研发云搭建及人才梯队建设——姚冬