我的间隔写为<a;b>
我用scanf("<%d;%d>", &a, &b);
阅读,但问题是我需要使用我的函数多次这样的间隔,直到我按CTRL + Z
或{{1}在Unix上。
到目前为止,我尝试过这样的事情,但它没有用。
CTRL + D
答案 0 :(得分:2)
你的问题并不简洁。这样:
int main( void ) {
int a=0, b=0;
printf("Intervaly: \n");
while(scanf("<%d;%d>",&a,&b) == 2){
printf("Ruznych kvadru: %d\n", capacity(a, b));
}
return 0;
}
实际上你想要的是,用<%d;%d>
的长行或逐行 - 两者都可以。你的问题,隐藏在评论中,EOF不会立即终止 - 而是你需要两次CTRL-D来阻止它。原因也在于评论中。
按照您的方式扫描后,您将在输入流中留下\n
(因为您必须按回车键才能发送输入而不会终止)。有两种方法可以解决这个问题 - 将其添加到scanf
中,这不太灵活,有一些问题,或者在while中清除它:
while(scanf("<%d;%d>",&a,&b) == 2){
printf("Ruznych kvadru: %d\n", capacity(a, b));
getchar();
}
您现在需要按CTRL-D一次。如果您尝试从文件输入重定向,您会看到此问题也不存在。为什么会这样?您在输入流中有\n
。你按下EOF,所以scanf得到一个换行符并忽略它 - 等待新的输入。只有现在新的EOF才能杀死scanf
。
我建议在此网站上搜索scanf
个问题,看看为什么不使用它,以及其他不错的选择。
<强>附录强>
评论中给出的一个更优雅的解决方案,由@BluePixy向我指出并由@DavidBowling向我指出是用于scanf
:
scanf("<%d;%d>%*c", &a, &b);
这将自然地吞噬额外的角色,包括新的空间,而不需要额外的getchar
。我认为这是scanf
用法的最优雅解决方案。
更多
按照OP的评论和David的再次评论(再次感谢!)以便占用0或更多空格,您只需要格式化空格指令:
scanf("< %d ; %d >%*c", &a, &b);
现在可以(或不可以)在每个整数周围添加空格。
答案 1 :(得分:0)
关于循环条件,while( scanf(" <%d;%d>", &a, &b)) == 2 )
应该足够了,但您可能还应该跟踪错误诊断的数量:
int nread=2;
while( (nread=scanf(" <%d;%d>", &a, &b)) == 2){ //...
Ctrl-Z
部分更复杂。
Ctrl-Z
导致规范设置终端驱动程序以生成SIGTSTP
信号。
此信号的默认配置是将进程置于睡眠状态,这意味着您
不能简单地使用ISO C&#39; signal
函数来注册信号处理程序,因为
如果这些信号处理程序可能会无意中恢复原始信号处理
收到多个信号实例,这会使你的过程停止。
您需要访问POSIX并使用sigaction
。
sigaction
处理程序可以设置一个易失性标志,这将是一个终止循环的信号。
由于在scanf
内部接收信号会导致scanf
失败
EINTR
,对此进行强大的错误处理有点令人费解:
#include <stdio.h>
#include <signal.h>
#include <errno.h>
static int volatile ctrl_z;
void SignalHandler( int Signum )
{
(void)Signum;
ctrl_z=1;
}
int main( void ) {
// ctrl + z
sigaction(SIGTSTP, &(struct sigaction){ .sa_handler=SignalHandler }, 0);
int a=0, b=0, nread=2;
/*...*/
while( (nread=scanf(" <%d;%d>", &a, &b)) == 2){
/*...*/
if(ctrl_z)
return 0;
errno=0; /*so we know if scanf failed because of the signal*/
}
if ( (!ferror(stdin) && feof(stdin)) ||
(ferror(stdin) && errno==EINTR && ctrl_z) )
return 0;
return 1;
}