C语言笔记(二)
- 利用 strrchr() 和 strcmp() 组合判断文件后缀名
- 利用 srand() 和 rand() 组合生成 (伪) 随机数
- 一个简单的问题
一、识别文件后缀名
在第二次程设作业中,需要将命令行参数作为文件名open,于是在这一步需要对文件名做规范检查,以下是网上查到的一些规范:
-
文件名或目录最长255字符
-
保留字符(不能使用)
- 任何控制字符(0-31)
- / 斜线(SLASH) (使用为路径分隔线;UNIX中的根目录符号)
- | 管道(PIPE)
- \ 反斜线(BACKSLASH) (使用为路径分隔线)
- ? 问号(QUESTIONMARK) (在Windows操作系统中使用为一个通配符)
- " 双引号(DOUBLE-QUOTATIONMARK) (这使用于标示含有空白字符的文件名称)
- * 星号(STAR) (在Windows操作系统中使用为通配符)
- : 冒号(COLON) (这使用于决定哪一个挂载点 / Windows操作系统中的磁盘)
- < 小于(LESS THAN) (原先由用户在主控台输入的消息改由文字档输入)
- > 大于(GREATER THAN)(原先输出至主控台的消息改输出至文字档)
- . 句点(可允许使用,但最后的句点会被诠释为扩展名的分隔)
- 另外,某些文件名称亦会保留,不能作为文件名称使用,如下
1
CON, PRN, AUX, CLOCK$, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
上述仅针对windows(NTFS)文件系统,即:
更多详情请见文件命名
所以在打开文件或是新建文件时需要检查预设文件名是否合理,那么这个时候出现了一个小小的问题,就是比如说用户想要建立一个名叫“abc.txt”的文本文件,但是用户输入文件名时可能出现两种情况:
- 用户输入的是“abc”
- 用户输入的是“abc.txt”
那么为了避免歧义(或者说能够让程序更加聪明一点),可以通过检查后缀名的方式来决定是否自动添加“.txt”扩展名
由此我们将话筒交给strrchr()函数:
Q: 请问您是做什么工作?
A: “I can return a pointer to the last occurrence of character in the C string str.”
译: 返回一个指针,指向 C 字符串 str 中最后一次出现的(要找的)字符。Q: 请问该如何使用呢?
A: 下面是我的原型,注意,当整个字符串都没有该字符时,返回空指针。
1 |
|
所以说,在此我们可以利用strrchr()函数找到预设文件名中最后一个’.’,若返回值非空指针,则调用strcmp()函数将其与“.txt”等扩展名字符串作比较。
即:
1 |
|
二、生成随机数
又是在第二次程设作业中,需要实现的功能是生成随机整数三元组构成的数据文件。于是一开始查到了stdlib.h库里的rand()函数,搜索发现rand()函数返回值是0到RAND_MAX(库中定义的常值,最小为32767)中的任意一个整型数(包括边界),那么可以用下式来获得自定义区间的值:
1 |
|
但是上式有一个致命问题,就是生成的实际是伪随机数,而由于生成时设立的种子没变,所以多次连续使用得到的值是不变的
于是找到了srand()函数,它的作用是重新设立种子,具体使用方法如下:
1 |
|
三、一个简单的问题
又又是程设实验二,在登记生成数据的条数时想到了一个小问题,即这个记录条数必然得是正数吧,那如果输入是负数,或者输入是不合规范的该怎么办,不能直接任由它malloc一个负的内存吧。所以想到了用while循环来保证得到一个正整数。这里采用的是scanf()从标准输入流获取:
1 |
|
显然,上述代码无法处理输入为诸如“bkajbc”的样子,因为scanf()在处理错误输入时会返回EOF(但是据老师所说是返回错误码,恕我没能找到有关的文章或者是我没看懂解释,先码住,以后填坑),然后将这些输入放在缓冲区(stdin是默认为行缓冲的),于是乎,while循环便停不下来了。
由此考虑到清空缓冲区的操作,搜到了以下几种方法:
1 |
|
至此本应告一段落,但是我还找到了一个方法:
1 |
|
本以为这个也能发挥作用,但没细想,这个只是将缓冲区改成无缓冲罢了,错误的依旧错误地读入了,并没有消除。
老师课上提出了鲁棒性(Robust)的一个方面 ,即scanf是有返回值的,而通常都会需要去检查返回值(printf不需要检查是因为,出错信息一般也是用printf标准输出,要检查的话不就陷入循环论证的圈子了www),由墨菲定律可知,只要有犯错的可能,那么一定会出错,所以不能抱这种态度。根据老师提出的建议,我的想法大概如下:
1 |
|
还提出了关于exit()的问题,exit()的用法如下:
1 |
|
一些总结
- 首先是工程作业很能锻炼到架构能力,从流程图能够直观的反映出对业务需求的理解能力、和业务逻辑业务规则的完备性,往往做一些算法题可能几十行就能解决,但是在这种情况,就需要考虑命名的规范性,程序的健壮性,可移植性和高性能性
- 老师提到了查找资料最好是用官方文档,就算是很多英文专有名词也要争取读懂,而博客啊或者其他的资料仅能用于参考,md深有体会。