【9】自定义I/O函数s_gets
1、C语言库里的I/O函数
我们知道C语言库里自带很多的I/O函数(输入输出),例如:scanf、printf……这里我们重点讲输入函数。
-
scanf() 从第一个非空白字符开始,遇到空白字符(空行、空格、制表符、换行符)结束,其中字符串不包括空白字符。通过转化说明(例如%d)可以输入不同的数据类型,是一个优秀的“翻译家”。 getchar() 读取一个字符 gets(int word[]) 读取整行输入,并存储字符和 到words中,丢弃换行符/不检查溢出/默认从屏幕读入 fgets(int word[], int arrsize, stdin/stdout) 读取整行输入,存储arrsize-1个字符和一个 到word中,不丢弃换行符/检查溢出/会指明读入文件(如果读到第一个是
则存储
,然后停止读取) gets_s(int word[], int arrsize) 读取整行输入,存储arrsize-1个字符和一个 到word中,丢弃换行符/检查溢出/默认从屏幕读入(如果>=arrsize则有可能导致程序终止) s_gets()是我们自己定义一个加强版fgets()
2、自己定义一个加强版fgets():s_gets()
(1)几个输入函数的对比
前两个比较简单,重点是gets、fgets、gets_s这三个函数
①当字符数组没有超出数组大小时,上述函数都没有问题
②但是当输入字符串太长时
使用get不安全,有可能会擦除已有的数据导致程序终止;
使用fgets只会读取符合数组大小的字符串,多余的全部放回缓存区,有可能会保存了 ;
使用get_s虽然安全,但是程序会中止或退出由于fgets会存储 。
③可以看出使用fgets比较方便并且安全快捷,唯一的问题就是fgets会保存 而不是丢弃它,这个 有时候会造成一点问题,故可以利用fgets来构造一个更加好的函数s_gets。
(2)具体代码
#define NUMBER 10 int main() { char words[NUMBER]; while (fgets(words, NUMBER, stdin) != NULL && words[0] != )//1、保证输入成功,并且第一个字符不是/n { int i = 0; while (words[i] != && words[i] != )//2、“是字符” == “中途输入就有 ”或“输完了自动加了 ” { i++; zz } if (words[i] != )//3、将混杂的 改变成为 { words[i] = ; } else//4、即就是结尾 了,将后面没有读取的舍弃 { while (getchar() != ) { ;//5、或者替换成continue } } } return 0; }
再改造成一个s_gets()函数
char* s_gets(char* st, int n)//存储数组首元素地址、存储字符大小 { char* ret_val;//返回值 int i = 0;//数组下标 ret_val = fgets(st, n, stdin); if (ret_val)//非NULL { while (st[i] != && st[i] != ) { i++; } if (st[i] == ) { st[i] = ; } else { while (getchar() != ) continue; } } return ret_val; }
如果使用库函数strchar还能再整洁一点
//另外更加简短的方法 #include <string.h> char* s_gets(char* st, int n)//存储数组首元素地址、存储字符大小 { char* ret_val;//返回值 char* find; ret_val = fgets(st, n, stdin); if (ret_val)//非NULL,成功输入 { find = strchar(st, ); if (find)//如果不是换行符就返回空指针 { *find = ; } else { while (getchar() != ) continue; } } return ret_val; }