文章目录
一. 关于本文
这是我在CSDN上写的第一篇博客,也算是给大一上画一个句号。
本文主要是想记录我在c语言课程设计中遇到的问题和体会等等,不过现在距离那个时候也挺久了,有些问题已经记不太清了哈哈哈,但是无伤大雅,接下来就开始吧!
二. 课设内容
三.大体思路
首先,最关键的功能应该是录入,其他功能都是建立在有信息的基础上进行操作。
对于录入功能,我的思路是:使用动态单链表存储学生的各项信息,然后将整条链表的信息以"a"即增加的方式逐节点写入文件中。
此后,文件中有了信息,就可以读取它们了。这里我同样使用动态单链表存储学生信息,然后fscanf按格式读取每一行的信息,构建成一条链表,并定义一个头指针作为全局变量,以供其他函数使用。
有了这条链表,其他操作就容易多了。例如查询,统计和排序功能,都需要遍历这条链表,然后输出或者再进行其他操作。
具体内容这里就不再详细展开。
四.遇到的问题
1.有时在录入信息时,如果输入格式错误,后续再次输入的内容无法被scanf读取
这里引用百科的内容——
“对于 scanf("%d %d",&a,&b);
函数返回值为int型。如果a和b都被成功读入,那么scanf的返回值就是2;
如果只有a被成功读入,返回值为1;
如果a和b都未被成功读入,返回值为0;
如果遇到错误或遇到end of file,返回值为EOF。end of file为Ctrl+z 或者Ctrl+d。”
由以上可知scanf是有返回值的,当循环后再次遇到scanf时,它会直接读取上次的返回值,造成输入无效。
解决方法:因此在scanf语句下加上getchar将其返回值吸收。
2. 密码输入时超出位数,提示密码错误后再输入正确密码仍然报错
原因分析:经过调试后发现,第一次输入密码后,数组已经存储上次输入的内容,第二次输入的位数比原来少的话,就存在没有被重新覆盖的元素(此处我不是用scanf整体输入,而是单字符存入数组),因此造成错误。
解决方法:使用memset将数组清空。
3.程序在vs运行时出现“未加载wntdll.pdb”的提示
这里引用博主Ding_HHD的博客《关于VS中出现的未加载wntdll.pdb的异常》——
“几十行的代码看了半天没看出来错误,于是选择一步步调试,发现是在主函数运行结束的时候抛出的异常。想了想可能是自己编程习惯不好,没有用free去释放malloc,所以尝试在结尾处添加了free。逐步执行的过程中发现异常变成了在一个free函数执行的过程中抛出,于是回过头去查看该指针的每一个操作,总算是找到了问题。
代码中for循环的过程中,i的限制条件不够严格,导致在某些数据情况下,t[i]会出现越界访问,而t就是那个malloc分配的指针。”
原来在网上查询此错误的解决方法,大多是对编译器进行设置,但我试了好几次都没有效果。找到上面这个方法后,我一步步调试了程序,发现确实是由于循环时链表越界。修改了循环条件后,程序终于正常运行。
4.将录入的信息写入文件时出现乱码“葺葺葺葺葺葺”
原因分析:调试后发现,给新定义的指针分配内存后,因为还未给其明确指向,所以它在vs中的指向就是乱码(这种乱码大概是vs的一种错误提示机制,屯屯屯也是如此)。
解决方法:不定义新指针,直接使用公共链表(即读取文件信息构成的链表)的头指针来写入,问题解决。
5.使用增加功能时,如果增加的位置是第一个,且增加的学生不止一个时,前面一个学生信息会消失
原因分析:第一个增加的学生插入第一个位置之后,第二个学生就不是插入第一个位置了,而是普通的中间插入。
解决方法:定义计数变量来控制不同的插入方式
6.在某些函数使用公共链表后,原链表数据变成乱码
原因分析:调试后发现,问题出在free上。因在函数中定义的指针p是指向公共链表的头指针的,此时如果将p给free掉,则同样会把公共链表头指针给free了,也因此头指针变成野指针,链表丢失。
解决方法:在使用free之前,要检查该指针的释放对其他地方有没有影响。
五.体会
收获有实在的和潜移默化的。实在的是自己对c语言更熟悉了,也学到了许多知识,例如编写程序之前最好想好框架,把一些功能相通或者可能会多次使用的函数写成通用的,就避免了冗杂。抽象的就是在自己设计,编写和调试的过程中,专注力和耐性有所进步,这对以后的学习有很重要的作用。
体会多是在过程中体现出来的,在刚布置课程设计时,我其实对自己能否完成抱很大的怀疑态度,但为了挑战自己,我在思考后还是决定选择难度最高的一题,一方面是想测试一下自己对c语言的掌握程度,是不是只停留在课内做题而已,另一方面是想考验自己有没有这个勇气和决心去做好一件事情。选完课题后,当时我链表刚学,文件处理还没学,于是想开始着手做的欲望基本没有,大概就是我们常说的开始很难吧。决定开始是看到舍友已经在很认真地从早到晚做,觉得很慌然后就开始做了。
一开始听舍友说,最难的部分就是录入,做完录入问题就不大了。果不其然,光是做录入功能我就花了快五天。一开始链表的操作很不熟悉,于是花了大概一天时间在看文章和视频学链表和文件处理。之后在CSDN上看到一个接近此课程设计的程序,就进去观摩,学着博主思路写了录入功能,但就是这个侥幸心理害了我,写完后我大概有三天都在处理这个写法的问题,最后实在想不通然后自己写了一个,果然路一下子就通了,到后来修改的时候我也知道问题出在哪里。
写完了录入后,写其他功能的时候果然行云流水,花了两天把要求的功能写的差不多了,再把前面写的再优化一下,然后就是把要检查的报告内容先写好。在老师还没通知报告有没有问题时,我开始整理代码,把各种功能函数及其声明分类放置并加上注释说明函数功能,这节约了不少查找和检查的时间。然后就是思考有什么功能可以增加,并把想法实现。
另外还把界面做得好看了一些,只可惜已经没时间去学习图形界面的制作。最后就是写报告,画流程图和注释。然后发现报告确实很花时间也很难写,要经过很多修改才能得到最后一版,而且要仔细检查和排版,光是报告就花了跟写代码差不多的时间,不过在写的过程中也能发现一些很小的错误和平时测试没有碰到的bug。
总的来说,做课设还是有很多收获的。最深刻的一点就是,要克服不想开始的惰性,其实一旦开始去做一件事后,它就不会像想象中那么难了。又想起高中物理老师说的,就像推箱子一样,一开始要克服的是静摩擦力,但是一旦推动之后,箱子受到的动摩擦就要比原来小了。
写在最后
以上就是我脑子里还记得的课设体验,其实还有许多地方没有说到,但是记不清了。
就先写到这吧!