需求:
从终端获取用户输入的用户名和密码(有效长度为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
view plaincopy to clipboardprint?
/* Standard streams. */
extern struct _IO_FILE *stdin; /* Standard input stream. */
extern struct _IO_FILE *stdout; /* Standard output stream. */
extern struct _IO_FILE *stderr; /* Standard error output stream. */
看了glibc的源码后发现 fgets() 只使用 _IO_FILE 中的 _IO_read_end 和 _IO_read_ptr 两个指针而已。
当然,还需要 #include <libbio.h> 因为 _IO_FILE 在这个头文件中定义的。具体如下:
头文件: /usr/include/libio.h
view plaincopy to clipboardprint?
struct _IO_FILE {
//......
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
//......
}
2. 也许还有其它方法......
注意:
使用fgets(), 如果用户输入小于 buf_size-1(最后一个字符空间留给'\0'),则获取的字符串以'\n'结尾,
也就是说,fgets()自动把用户输入的回车字符放进去了。
===============================================================================
view plaincopy to clipboardprint?
//
// 等待用户输入字符串
// echo - 是否回显用户输入?
//
void wait_input( char *buf, int buf_size, int echo )
{
struct termios old_val, new_val;
tcgetattr( fileno( stdin ), &old_val );
new_val = old_val;
if( echo )
new_val.c_lflag |= ( ECHO );
else
new_val.c_lflag &= ( ~ECHO );
tcsetattr( fileno( stdin ), TCSANOW, &new_val );
fgets( buf, buf_size, stdin);
// 起到冲刷stdin的效果(glibc)
stdin->_IO_read_ptr = stdin->_IO_read_end;
tcsetattr( fileno( stdin ), TCSANOW, &old_val );
// 如果输入不够长,字符串最后有一个'\n'
if( '\n' == buf[ strlen(buf) - 1 ] )
buf[ strlen(buf) - 1 ] = '\0';
// 禁止回显后,输入结束时不会自动换行
if( !echo )
printf( "\n" );
return;
}
从终端获取用户输入的用户名和密码(有效长度为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
view plaincopy to clipboardprint?
/* Standard streams. */
extern struct _IO_FILE *stdin; /* Standard input stream. */
extern struct _IO_FILE *stdout; /* Standard output stream. */
extern struct _IO_FILE *stderr; /* Standard error output stream. */
看了glibc的源码后发现 fgets() 只使用 _IO_FILE 中的 _IO_read_end 和 _IO_read_ptr 两个指针而已。
当然,还需要 #include <libbio.h> 因为 _IO_FILE 在这个头文件中定义的。具体如下:
头文件: /usr/include/libio.h
view plaincopy to clipboardprint?
struct _IO_FILE {
//......
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
//......
}
2. 也许还有其它方法......
注意:
使用fgets(), 如果用户输入小于 buf_size-1(最后一个字符空间留给'\0'),则获取的字符串以'\n'结尾,
也就是说,fgets()自动把用户输入的回车字符放进去了。
===============================================================================
view plaincopy to clipboardprint?
//
// 等待用户输入字符串
// echo - 是否回显用户输入?
//
void wait_input( char *buf, int buf_size, int echo )
{
struct termios old_val, new_val;
tcgetattr( fileno( stdin ), &old_val );
new_val = old_val;
if( echo )
new_val.c_lflag |= ( ECHO );
else
new_val.c_lflag &= ( ~ECHO );
tcsetattr( fileno( stdin ), TCSANOW, &new_val );
fgets( buf, buf_size, stdin);
// 起到冲刷stdin的效果(glibc)
stdin->_IO_read_ptr = stdin->_IO_read_end;
tcsetattr( fileno( stdin ), TCSANOW, &old_val );
// 如果输入不够长,字符串最后有一个'\n'
if( '\n' == buf[ strlen(buf) - 1 ] )
buf[ strlen(buf) - 1 ] = '\0';
// 禁止回显后,输入结束时不会自动换行
if( !echo )
printf( "\n" );
return;
}
发表评论
-
crond需要重启么?
2011-06-11 12:20 1222今天一同事说把A机器的/var/spool/cron/admi ... -
GDB信号的处理和启动配置文件(转载)
2011-05-22 21:57 2203信号的处理 程序是和网络相关的,调试期间经常地收到SIGPIP ... -
信号量基础知识
2011-05-10 18:40 985linux 中信号相关的一个结构体 struct sigact ... -
asprintf
2011-05-08 21:49 2325sprintf() 的整个介面长的样子的是: int ... -
Linux下的UDP/TCP端口映射(netcat and socat)
2011-05-07 20:42 9665说起来有点土,事到如今 ... -
linux任务管理
2011-05-07 20:32 680disown是bash内部命令,nohup是外部命令 diso ... -
boost multi_index_container
2011-04-27 21:18 1524本章介绍的主题是multi_i ... -
变量相关命令(env,export,set,read, array, declare
2011-04-26 21:38 1001系统的预设参数文件:/ ... -
stl priority_queue
2011-04-26 21:20 601简单的使用示例。 view plaincopy to cli ... -
linux backlog
2011-04-25 15:13 1492在linux中,/proc/sys/net/core/so ... -
linux backlog
2011-04-25 15:13 730在linux中,/proc/sys/net/core/so ... -
stl hash_map
2011-04-23 19:57 749#include <cstdlib> #incl ... -
linux串口登陆
2011-04-23 09:31 1478在这个互连网高速发展的时代, 企业内网络设备的安全和运行稳定也 ... -
linux rename
2011-04-21 09:38 707Linux中rename命令的用法 刚学习linux的时候, ... -
stl heap
2011-04-17 10:01 767make_heap 原型: #include <a ... -
expand and upexpand
2011-04-09 13:33 707expand: NAME expand - co ... -
内核模块相关命令:lsmod,depmod,modprobe
2011-03-28 13:24 1108lsmod 功能:列出内核已载入模块的状态 用法:lsmod ... -
通过先unlink()后close()创建安全的临时文件
2011-03-15 14:26 883使用POSIX(Portable Operating Syst ... -
parted操作磁盘
2011-03-12 16:15 807除了fdisk命令,在linux下还有一个功能也非常强大的磁盘 ... -
linux写缓存调优
2011-03-11 09:34 2002我们在磁盘写操作持续 ...
相关推荐
Linux运维-运维课程下用户组管理09-stdin标准输入修改用户密码.mp4
本文主要介绍C语言清空输入缓冲区在标准输入(stdin)情况下的使用。
获取输入 这是我在高中时围绕 Scanner 类编写的一个简单包装器,它从 stdin 获取某种类型。 它验证类型并支持自定义错误消息。 这最初在useful-packages库中,但我决定将其分解。
tmpin - 添加stdin支持至任何CLI应用程序接受文件输入
get-stdin - 获得stdin作为一个字符串或缓冲区
以string获取stdin 。 在TTY上下文中,返回解析为空string的Promise。 getStdin.buffer() 获取stdin作为Buffer 。 在TTY上下文中,返回解析为空Buffer的Promise。 有关的 以字符串或缓冲区的形
Python中常用到的两种标准化输入方式:分别sys.stdin和input,两者使用方式大致相同,但是总的来说sys.stdin使用方式更加多样化一些,下面就例子说明两者之间的使用差别。 1、input输入 input输入很简单,就是获得...
ttyplot:一个实时绘图实用程序,用于在终端中展示从stdin输入的数据
用于轻松模拟向用户提问的 BDD 单元测试的用户响应的实用程序。 我需要一些东西来帮助。 npm install bdd-stdin --save-save 输入文字 var ask = require ( './ask' ) ; // ask is promise-returning stdin ...
1、使用sys.stdin 读取标准输入 [root@c6-ansible-20 script]# cat demo02.py #! /usr/bin/env python from __future__ import print_function import sys for line in sys.stdin: print(line,end=) 使用方法: ...
线索/reactphp-stdio 异步、事件驱动和 UTF-8 感知控制台输入和输出(STDIN、STDOUT),用于真正交互式 CLI 应用程序,构建在。 您可以使用这个库来构建真正的交互式和响应式命令行 (CLI) 应用程序,当用户输入一行...
上述代码示例使用了Foundation框架的NSScanner类来读取标准输入流/dev/stdin中的整数。这通常用于命令行工具项目。 在实际应用中,Objective-C代码通常更为复杂,并且会包含更多的错误处理和用户界面交互。 ...
我就想到了用多线程的方式, 开启一个子线程用stdin(比如python的input函数)获取用户输入, 主线程里设置线程启动和超时. 创建线程 Python中使用多线程很方便, threading.Threaded(函数, 参数表)然后thread.start就好...
简单的样板Java类读取stdin 用法 输入将被写入input.txt并通过管道传递到Java程序。 运行Java程序: $ ./run.sh < java>
因此,在标准情况下,每个命令通常从它的控制终端中获取输入,将输出打印到控制终端的屏幕上。 但是也可以重新定义程序的输入 stdin和输出stdout,将它们重新定向。最基本的用法是将她们重新定义到一个文件上去...
python3中使用sys.stdin.readline()可以实现标准输入,需要调用sys库,sys.stdin是一个标准化输入的方法,其中默认输入的格式是字符串,如果是int,float类型则需要强制转换。如: 例1: import sys print('Plase input...
googlelog 发送stdin至Google Cloud Logging
// 获取用户输入的字符串 printf("请输入一个字符串: "); fgets(inputString, sizeof(inputString), stdin); // 去除输入字符串中的换行符 inputString[strcspn(inputString, "\n")] = '\0'; // 计算字符串...
// 获取用户输入的字符串 printf("请输入一个字符串: "); fgets(inputString, sizeof(inputString), stdin); // 去除输入字符串中的换行符 inputString[strcspn(inputString, "\n")] = '\0'; // 计算字符串...
将STDIN消息作为服务器发送的事件