Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在程序中同时使用puts()、gets()、getchar()、putchar()函数_C_Getchar_Gets_Puts_Putchar - Fatal编程技术网

在程序中同时使用puts()、gets()、getchar()、putchar()函数

在程序中同时使用puts()、gets()、getchar()、putchar()函数,c,getchar,gets,puts,putchar,C,Getchar,Gets,Puts,Putchar,我对在代码中同时使用put()、get()、putchar()和getchar()感到困惑 当我运行以下代码时,它正在执行所有步骤: 获取输入,打印输出,再次获取输入,打印输出 #include <stdio.h> int main() { char ch[34]; gets(ch); puts(ch); char g; g = getchar(); putchar(g); } 但是,当我使用此代码时: 它只做了两个步骤: 获取输

我对在代码中同时使用
put()
get()
putchar()
getchar()
感到困惑

当我运行以下代码时,它正在执行所有步骤: 获取输入,打印输出,再次获取输入,打印输出

#include <stdio.h>

int main() {
    char ch[34];
    gets(ch);
    puts(ch);

    char g;
    g = getchar();
    putchar(g);
}
但是,当我使用此代码时: 它只做了两个步骤: 获取输入,打印输入,然后是一行空间。我不明白它为什么会这样

代码:


在我不建议使用的语句
putchar()
gets()
的行之间,在EOF或换行符出现之前丢弃输入流可以解决问题:

.
.
int c;
while ((c = getchar()) != EOF && c != '\n')
  ;
.
.
我建议使用更安全的方法,例如:

char str[1024];
if (fgets(str, sizeof str, stdin) == NULL) {
  // Some problem, handle the error...
}

// or, Input is okay...

代码中存在一些问题,输入机制比您推断的更复杂:

  • 不应使用
    gets()
    读取输入:此函数无法安全使用,因为它不接收有关目标数组大小的信息,因此任何足够长的输入行都将导致缓冲区溢出。它已从C标准中删除。您应该改为使用
    fgets()
    ,并处理缓冲区末尾的换行符
  • g
    应具有类型
    int
    ,以适应
    getc()
    返回的所有值,即
    无符号字符类型的所有值(在大多数当前系统中
    0
    255
    )和特殊负值
    EOF
    (通常为-1)
以下是修改后的版本:

#include <stdio.h>

int main() {
    char ch[34];
    if (fgets(ch, sizeof ch, stdin))
        fputs(ch, stdout);

    int g = getchar();
    if (g != EOF)
        putchar(g);
    return 0;
}
关于控制台响应程序输入请求的行为,它是实现定义的,但通常涉及两层缓冲:

  • 文件
    流包实现了一种缓冲方案,其中数据以块的形式从系统中读取或写入。可以使用
    setvbuf()
    控制此缓冲。3种设置可用:无缓冲(这是
    stderr
    的默认设置)、行缓冲(通常是
    stdin
    stdout
    在连接到字符设备时的默认设置)以及使用可自定义块大小(常用大小为512和4096)完全缓冲
  • 当您调用
    getchar()
    或更一般的
    getc(stream)
    时,如果流的缓冲区中有一个字节可用,则返回该字节并递增流的位置,否则会向系统请求填充缓冲区
  • 如果流附加到文件,则填充缓冲区将执行
    读取
    系统调用或等效调用,除非在文件末尾或读取错误时成功
  • 如果流连接到字符设备,如终端或虚拟tty(如图形显示器上的终端窗口),则会涉及另一层缓冲,其中设备驱动程序从输入设备读取输入,并以特殊方式(如退格)处理一些键以擦除前一个字符,光标移动键在输入行内移动,Ctrl-D(unix)或Ctrl-Z(windows)表示文件结束。这一层缓冲可以通过
    tcsetattr()
    系统调用或其他特定于系统的API进行控制。交互式应用程序(如文本编辑器)通常禁用此功能,并直接从输入设备检索原始输入
  • 终端处理用户键入的密钥以形成输入行,当用户输入时发送回C流API(被翻译为系统特定的行尾序列),流函数执行另一组转换(即:在传统系统上将
    CR
    /
    LF
    转换为
    '\n'
    )字节行存储在流缓冲区中。当
    getc()
    最终有机会返回第一个可用字节时,用户已经键入并输入了整行,并且在流或设备缓冲区中挂起

在这两个程序中,
getchar()
不会返回从
stdin
读取的下一个字节,直到从终端读取完整的行并存储在流缓冲区中。在第一个程序中,该行的其余部分在程序退出时被忽略,但在第二个程序中,该行的其余部分可供后续的
get()
读取。如果键入J并输入,则读取的行为
J\n
getchar()
返回
'J'
,保留换行符[在输入流中结束,然后
gets())
将读取换行符并返回一个空行。

好吧,这里有一个问题。您在第二个示例代码中使用的函数不是stdio包的一部分

你调用
getch()
,它不是一个stdio函数。它是ncurses库的一部分,如果你在编译时没有指定要使用它,那么你就不能得到一个可执行的程序。所以这让我觉得你说的不是所有的事实

只需使用程序的函数
getch()
,就可以得到完整的行

Priyanka
输出,程序终止。我猜您使用了
getch()
来停止输出,直到您按下一个字符为止。但是由于curses库要求您在调用任何其他curses库函数之前调用
initscr()
,因此它没有正确初始化,您得到的输出可能会因此出错

我不会重复其他人已经告诉您的关于使用
get()的内容
,它仍然在标准库中,并且知道您在做什么,您仍然可以在适当控制的环境中使用它。尽管如此,其他人给您的建议在这里并不适用,因为您没有溢出您使用的短缓冲区(只有34个字符,太短,太容易挂起或崩溃程序)

来自stdio的函数使用缓冲区,而
char str[1024];
if (fgets(str, sizeof str, stdin) == NULL) {
  // Some problem, handle the error...
}

// or, Input is okay...
#include <stdio.h>

int main() {
    char ch[34];
    if (fgets(ch, sizeof ch, stdin))
        fputs(ch, stdout);

    int g = getchar();
    if (g != EOF)
        putchar(g);
    return 0;
}
Priyanka
Priyanka
J
J
Priyanka