需求:
从终端获取用户输入的用户名和密码(有效长度为n),我把 buffer 设为 n+10,这样当用
户输入过长时可以接收到多余的字符,从而判断出超长了;如果用户直接按回车键,那么应该
接收到0个字符。
函数:
fgets( buf, buf_size, stdin)
问题:
当用户输入超过 buf_size 时,下次再调用 fgets(),它会直接返回而不是等待用户输入,
因为 fgets() 是直接从 stdin 拿字符的,上次没有取完的字符,直接被 fgets() 拿走然
后返回;
网上的解决方法:
1. 使用fflush()。可惜没有任何作用,虽然在Windows下可以,但Linux下没有这个效果。
2. 调用完 fgets() 后用 while( (ch = getchar() ) != '/n' && ch != EOF );
清除 stdin 中剩余的字符。问题是如果用户输入小于buf_size, fgets() 成功返回后,
又进入 getchar() 等待用户输入,用户必须至少多按一次回车键才能得到他想要的结果。
3. 使用 C++ 的 cin>>buf, 然后再调用 cin.clear() 清除stdin。 这次 stdin 是真的
可以成功清除了,解决了多余字符问题,但是如果你直接回车,cin>>buf 是不会返回的,
必须至少输入一个字符后再回车才行,与需求不符。
4. ......
我的方法:
1. fgets() 后,直接 stdin->_IO_read_ptr = stdin->_IO_read_end; 即可解决所有
问题。stdin 实际上是一个结构体指针,如下:
头文件: /usr/include/stdio.h
看了glibc的源码后发现 fgets() 只使用 _IO_FILE 中的 _IO_read_end 和 _IO_read_ptr 两个指针而已。
当然,还需要 #include <libbio.h> 因为 _IO_FILE 在这个头文件中定义的。具体如下:
头文件: /usr/include/libio.h
2. 也许还有其它方法......
注意:
使用fgets(), 如果用户输入小于 buf_size-1(最后一个字符空间留给'/0'),则获取的字符串以'/n'结尾,
也就是说,fgets()自动把用户输入的回车字符放进去了。
===============================================================================