2017-08-09 39 views
2

我正在写一个程序,在Linux终端上复制输入逐字输出。代码如下(来自Dennis Ritchie的C书)延迟输出到EOF而不是换行

#include <stdio.h> 
/* copy input to output; 2nd version*/ 

main() 
{ 
    int c; 
    while ((c = getchar()) != EOF) 
     putchar(c); 
} 

该程序及其执行正常工作。但我想稍作修改。

输出显示在每个新行字符的终端上(当我按下Enter键时)。我想延迟输出,直到按信号结束文件,按Ctrl + D。为了延迟我在终端上的输出,我必须对该程序进行哪些修改。

示例输出我得到如下:

我希望得到
abcd (enter) 
abcd 
llefn;elnf(enter) 
llefn;elnf 
(ctrl+d) 

输出示例如下:

abcd(enter) 
llefn;elnf(ctrl+d) 
abcd 
llefn;elnf 
+2

将字符放入缓冲区并显示整个缓冲区和结束。没有其他选项AFAIK –

+1

不需要更改程序的修复就是将输入写入文本文件,然后将其作为输入重定向到您的程序。 'a.out

+0

@Meehm是的,它没有任何额外的空间工作正常,但有可能使用终端本身做的东西? – hanugm

回答

1

如前所述in the comments:把字符到缓冲区和显示整个缓冲区末尾:

#include <stdio.h> 

#define BUF_SIZE 1024 

int main() 
{ 
     char str[BUF_SIZE]; // the buffer 
     int c, i = 0; 

     while (i < BUF_SIZE-1 && (c = getchar()) != EOF) 
     str[i++] = (char) c; 

     str[i] = '\0'; 

     printf("%s\n", str); // display the contents of the buffer 
} 
+0

不要写简单的'main()';它应该是最小的int main(),最好是int main(void)。这是这个千年所有标准的要求。 –

+1

@JonathanLeffler虽然OP正在读一本书,但是从上个千年开始...... –

+0

@JonathanLeffler right,编辑。 –

2

您需要存储这些ch字符的缓冲区,控制索引你在哪里写,当你收到EOF只是通过printf打印该缓冲区。

如果你不能解决这个问题,你可以在这里激发

#include <stdio.h> 

#define BUFFER_SIZE 1024 

int main() 
{ 
    int c, i = 0; 
    char buffer[BUFFER_SIZE]; 

    while ((c = getchar()) != EOF) 
    { 
     if (i < BUFFER_SIZE - 1) 
     { 
      buffer[i] = c; 
      i++; 
     } 
     else 
     { 
      buffer[BUFFER_SIZE - 1] = '\0'; 
      printf("%s", buffer); 
      i = 0; 
     } 
    } 

    buffer[i] = '\0'; 
    printf("%s", buffer); 

    return 0; 
} 
+0

只要'c'不是0就可以正常工作。对于OP可能没问题。 – chux

+0

此代码还会每1023个字节输出一个额外的'\ n',并在最后一个额外的一个。 – chqrlie

1

您可以用setvbuf(3)设置缓冲区stdout

#include <stdio.h> 
main() 
{ 
     int c; 
     char buf[BUFSIZ]; 
     setvbuf(stdout,buf,_IOFBF,BUFSIZ); 
     while ((c=getchar())!=EOF) 
       putchar(c); 
} 

这里的关键是使用_IOFBF常数指定的完全缓冲模式。 缓冲器的大小被设置为BUFSIZ通常等于8192

如由Jonathan莱弗勒缓冲器的大小有限的评论被正确指出可能导致程序突然吐出其内容错乱的终端。为了避免这种情况,可以跟踪缓冲区的使用情况,并在缓冲区填满时扩展其大小。

+1

没关系,如果文件小于缓冲区大小。文件有时很大。 –

+1

我猜世界可能已经改变了。通常,BUFSIZ通常是512.即使是8192也不是那么大,尽管它比我想象的要大得多。 –

+0

@JonathanLeffler自1996年以来,GNU/linux中的BUFSIZ是8192.在大多数情况下,应该足够用于来自终端的交互式输入。我同意,要正确实现规范,我们需要动态增长缓冲区。 –

2

一个简单的,尽管草率和局部解决方案是配置stdout与大量缓冲器全缓冲:

#include <stdio.h> 

int main(void) { 
    int c; 

    setvbuf(stdout, NULL, _IOFBF, 32767); 
    while ((c = getchar()) != EOF) { 
     putchar(c); 
    } 
    return 0; 
} 

注:

  • 在一个32位或64位系统,则可能会使缓冲区变得非常大。
  • 通过NULLsetvbuf可以让它为malloc()分配缓冲区。
+0

你可以从一个很大的'size_t'值开始,除以2直到成功:D –

+0

@AnttiHaapala:是的,我可以写'for(size_t size =〜(size_t)0 >> 1; size; size >> = 1){if(!setvbuf(stdout,NULL,_IOFBF,size)break;}'但这对于OP的技能水平来说太神秘了 – chqrlie

+0

如果你不知道你需要多大的缓冲区,但需要编程有效吗?分配字节数量听起来效率不高。:-) –