用C语言阅读和写作

时间:2016-10-18 14:56:22

标签: c stdio

所以我在阅读函数fgets和scanf以及打印函数write和printf时遇到以下代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
    printf("Enter an integer: ");
    int n = 0; scanf("%d",&n);
    printf("The input number is: %d\n", n);
    printf("Please enter a string now: ");
    char buffer[200];
    read(0,buffer,200);
    printf("The input string is: %s", buffer);
    printf("which is: %s\n", buffer);
    printf("Now please enter another message: ");
    fgets(buffer,200,stdin);
    write(1,buffer,200);

    return 0;
}

我会收到这些错误:

1 - 在第一次扫描后,它不会只显示输入字符串的消息。

2 - 我现在写的是它将保存在字符串中的内容。

3 - 它将跳过最后的fgets ......

输出示例: enter image description here

根本没有任何意义;我想得到这样的输出:

Enter an integer: 15
The input number is: 15
Please enter a string now: This is the message1
The input string is: This is the message1 which is: This is the message1
Now please enter another message: This is the message2
This is the message2

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

有趣的问题。将标准I / O(scanf()fgets())和文件描述符I / O(read())混合在同一基础文件描述符上(0又称标准输入; stdin作为文件流)充其量是个问题。你会得到奇数球效应。

在文件流级别,当输入来自终端时,stdinstdout之间存在一些同步; stdout上的待定输出通常由库刷新。使用read()时,没有此类同步。这就是为什么直到你回来之后才出现提示。

当您为该号码键入1时,您还会提供换行符。标准I / O缓冲换行符;它被保留,以便下一个文件流操作可以读取它。然后你读了一行read()。这不知道标准I / O缓冲区,因此它等待来自终端的新输入行。您需要捕获读取的数据量,因为输入未终止;这是标准I / O库提供的服务,而不是低级read()函数。

当你再调用fgets()时,它会读取缓冲的换行符(读取整数时不由scanf()处理)并返回空行。

请注意,如果您在标准输出上等待任何缓冲输出(例如,您使用了printf("Beginning of line: ");而没有换行符),那么write()的输出将出现在{{1}上缓冲的信息之前}。

使用stdoutfread()将为您提供直接二进制I / O(例如,无空终止),但会使用与fwrite()等函数相同的I / O缓冲区和printf()。使用这些时会出现混合行为 - 通常最好在单个文件流上使用fgets() / fread()或文本I / O函数,而不是两者都使用,但是混合它们是允许的,相对来说是相对的简单易懂,偶尔有用。

所以,你所看到的都是可以解释的,但做解释是很辛苦的。它也清楚地表明了为什么你不应该在同一个底层文件描述符上混合文件流和文件描述符I / O--特别是不是标准输入。

答案 1 :(得分:1)

为什么不使用before_action :method1, only: :start def start .... if some_case render json: {ok: "ok"} end end def method1 ... if some_case render json: {error: "Some error"} return end end 更好的格式:

scanf

答案 2 :(得分:0)

read(0,buffer,200);

最多可读取200个字符,但不会向buffer添加终止空字符。因此,对printf的以下调用会导致未定义的行为。

您需要添加代码来捕获函数的返回值,并确保null终止字符串。

int n = read(0, buffer, 199);  // Leave one for the terminating null character
if ( n == -1 )
{
   // Deal with the error.
}
else
{
   // null terminate the string.
   buffer[n] = '\0';
}