【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;
}
