2015-09-26 43 views
1

我们刚刚开始了C语言中低级函数的主题,对于这部分任务我们必须要求用户输入。通常我会使用printf()和scanf(),但是对于这个任务我们只允许使用read(),write(),open(),close()和lseek()。使用无缓冲IO例程询问和读取用户输入

我的问题是如何在打印到屏幕后从键盘读取输入? 据我所知,我将不得不使用read,文件描述符将是STDIN_FILENO,但我如何确定大小计数?另外我将如何跟踪用户输入的内容?我需要为此创建一个char数组吗?

此外,如果任何人都可以参考一些很好的阅读材料或编程与低级别的功能,这将有助于很多教程。

+0

最简单的方法可能一次只读一个字符如果你得到一个换行符,将字符附加到数组中。 –

+0

如果你想从标准输入读取,你不需要事先指定数组的大小吗?我明白你的意思,但我不知道如何实施它。 – user3538161

+0

使用'read/write'来完成输入/输出和使用'getchar/printf'确实没有什么区别。主要区别是您不喜欢格式化输出或可变打印功能。您必须按照您希望的输出方式将每个输出写入'stdout'来进行格式化。如果你仍然坚持让我知道。你可以像使用任何文件一样在'stdin'上使用read。你声明一个缓冲区(数组)并从'stdin'读入缓冲区。 'read'返回给你成功读取的字符数。 –

回答

1

从我先前的评论继续,存在使用readwrite和使用像fgetsprintf更高层次的功能,以stdin阅读和写作之间的真正差别不大。主要区别在于,您不能依赖可变参数printf提供的格式字符串以及read,因此您有责任使用返回来知道实际读取了多少个字符。

下面是表示从stdinread读取输入,然后编写信息反馈与write注意基础知识很短的例子:有你应该增加像检查的字符数读额外的检查小于知道是否还有更多字符需要读取的缓冲区的大小等等)。您可以将大部分提示和read放入一个函数中,以缓解重复使用。

随着write,只记得,你写的东西stdout的顺序是的格式字符串。因此只需简单地调用write即可完成您所需的格式。虽然您可以自由使用STDIN_FILENO定义,你也可以简单地使用0 - stdin1 - stdout2 - stderr

#include <unistd.h> 

#define MAXC 256 

int main (void) { 

    char buf[MAXC] = {0}; 
    ssize_t nchr = 0; 

    /* write the prompt to stdout requesting input */ 
    write (1, "\n enter text : ", sizeof ("\n enter text : ")); 

    /* read up to MAXC characters from stdin */ 
    if ((nchr = read (0, buf, MAXC)) == -1) { 
     write (2, "error: read failure.\n", sizeof ("error: read failure.\n")); 
     return 1; 
    } 

    /* test if additional characters remain unread in stdin */ 
    if (nchr == MAXC && buf[nchr - 1] != '\n') 
     write (2, "warning: additional chars remain unread.\n", 
      sizeof ("warning: additional chars remain unread.\n")); 

    /* write the contents of buf to stdout */ 
    write (1, "\n text entered: ", sizeof ("\n text entered: ")); 
    write (1, buf, nchr-1); 
    write (1, "\n\n", sizeof ("\n\n")); 

    return 0; 
} 

编译

gcc -Wall -Wextra -o bin/read_write_stdin read_write_stdin.c 

输出

$ ./bin/read_write_stdin 

enter text : The quick brown fox jumps over the lazy dog! 

text entered: The quick brown fox jumps over the lazy dog! 
+0

我对写有点困惑。第二个参数不是一个指向缓冲区的指针吗?你怎么能传递一个字符串?当它到达文件末尾时也不读取返回0?所以不会nchr = 0? – user3538161

+0

这是一个指向缓冲区的指针。该缓冲区被声明为一个静态数组'buf [MAXC]'。但是,当作为参数传递时,数组*会衰减*为指针。这就是你可以写'int main(int argc,char * argv [])'或'int main(int argc,char ** argv)'的原因。您可以阅读关于该主题的所有内容,只需搜索** C指针衰减**即可。我简单地选择了一个静态数组来保持示例简单,而不是选择使用'malloc'动态分配一个指针,并从'read''write'逻辑分散注意力。 ('calloc'会是更好的选择)。 –

2

通过字符读取字符会对性能不利。系统调用很贵。大多数情况下,你想要某种缓冲区(堆栈中的malloced,静态内存)。 尺寸(一旦超过一定的尺寸)并不重要。

如果您的fd 0是熟食模式下的终端,您将在每次读取呼叫时获得一行(通常无法填充整个缓冲区)。重要的是要实现一个N字节的读取请求不需要返回N个字节,而少于N个字节的返回不需要意味着IO错误。如果它是一个基于磁盘的文件,那么您的缓冲区大小的读取请求将得到充分填充。

Unix环境下的高级编程Richard Stevens是一本关于此的好书。 然后,当然,系统调用的手册页。