【问题标题】:What is the difference between getchar/putchar, gets/puts and fgets/fputs (in C)?getchar/putchar、gets/puts 和 fgets/fputs(在 C 中)有什么区别?
【发布时间】:2016-08-30 10:07:59
【问题描述】:

我目前正在研究 C 语言中的输入和输出,我发现有大约十亿种不同的方式来获取输入,例如 getch、getchar、gets 和 fgets,对于输出(putchar、puts、 fputs 等)。

所有这些不同的 I/O 方法让我有点困惑,所以我来这里问一下上述函数之间的基本区别是什么。

我还使用这些不同的函数编写了一些代码,并根据我所学到的内容评论了我认为它们是如何工作的,但我不确定我的理解是否正确。我在其他地方也读过它们,但解释很复杂,似乎不连贯。

那么谁能告诉我我是否正确使用它们,如果没有,我应该如何使用它们以及它们之间的主要区别是什么?

这是我的代码:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

void individualCharacters()
{
    char theChar;

    while ((theChar = getchar()) != '~') {  //    getchar() stores all characters in a line buffer as it is entered until newline is entered
        putchar(theChar);    // putchar() prints the characters in the line buffer and does not print a newline, line buffering depends on compiler
    }
}

void withoutF()
{
    char name[50];

    printf("What is your name? ");

    gets(name);    // receives a string until newline is entered, newline is then replaced with string terminator, array limit should not be passed

    puts("Hi");    // only prints one string at a time and adds the newline because gets() previously replaces the newline
    puts(name);
}

void withF()
{
    char name[50];

    printf("What is your name? ");

    fgets(name, 50, stdin);    // does add a newline so the newline takes up one space in the array, it stores input until either newline is entered or array limit is reached

    fputs("Hi ", stdout);    // does not print a newline but prints the string input up to the array limit
    fputs(name, stdout);
}

void main()
{
    //sum();

    //individualCharacters();

    //withoutF();

    //withF();

    //printRandomString();
}

这些只是我编写的一些函数,它们以不同的方式获取输入和显示输出,但我无法理解为什么会有这么多不同的方式。

如果我在使用 I/O 功能时出现任何错误,请随时告诉我,以便我进行修改。

谢谢

【问题讨论】:

  • 一些有趣的阅读:stackoverflow.com/questions/1694036/…
  • 现在我明白为什么gets 如此危险了。所以如果没有正确使用,并且你不允许它足够的内存,它会在不知情的情况下溢出,并且可能会覆盖其他重要的内存?
  • fgets 只是通过忽略超出数组限制的任何字符来避免该问题。

标签: c io user-input gets puts


【解决方案1】:

fgets - 从指定的流中读取最多SIZE-1 个字符到缓冲区,如果有空间,包括尾随的换行符。在缓冲区末尾添加一个 0 终止符,使其成为有效的 C 字符串:

char buffer[SIZE];

if ( fgets( buffer, sizeof buffer, stdin ) ) // read from standard input
  do_something_with( buffer );
else
  error();

成功时,fgets 返回输入缓冲区的地址。在失败或文件结束时,它返回NULL

fgetc - 从指定的输入流中读取一个单个字符并返回:

FILE *input_stream = fopen( "some_file", "r" );
int c;
while ( (c = fgetc( input_stream )) != EOF )
  do_something_with( c );

gets - 在 C99 之后被弃用,从 C2011 中完全删除。与fgets 一样,它将标准输入中的字符序列读取到缓冲区中并添加一个0 终止符,但与fgets 不同的是,它没有提供限制输入的机制,使其成为流行的恶意软件攻击。此外,它不会将尾随换行符存储到缓冲区。使用它可以保证在您的代码中引入一个故障点。假装你从未听说过它。

getc - 与fgetc 相同,不同之处在于它可以作为宏实现。

getchar - 从标准输入读取单个字符:

int c;
...
while( (c = getchar()) != EOF )
  do_something_with( c );

fputs - 将字符串写入指定的输出流:

char str[SIZE];
...
fputs( str, output_stream ); 

fputc - 将单个字符写入指定的输出流:

while ( i < strsize )
  fputc( str[i], output_stream );

putc - 与fputc 相同,不同之处在于它可以作为宏实现

putchar - 将单个字符写入标准输出。

【讨论】:

  • 感谢您的回答,现在这一切对我来说更有意义了。我还有几个问题。如果fgetcgetchar 都从输入中读取单个字符,它们有何不同(除了语法)以及何时应该使用它们(fputcputchar 的问题相同)?另外,“标准输出”和“输出流”之间是否有区别,因为我查过它们,但我发现它们可以互换使用?
  • getchar 仅从标准输入流 (stdin) 中读取。 fgetc 从您指定的任何流中读取。 stdinstdoutstderr 是预定义的输入和输出流,通常在交互式会话中引用您的控制台。
  • 哦,好吧,那么fgets/fgetcfputs/fputc 最适合通用标准I/O?
  • @kashveyron:这真的取决于你想做什么。如果你想读/写 formatted 文本,或处理非字符类型(整数、浮点数等),你会使用 fscanf/fprintfscanf/printf(同样的处理;第一个对读取或写入您指定的流,第二个使用标准输入和输出)。如果你想读取或写入 二进制 数据,你会使用fread/fwrite。没有万能的解决方案;这取决于您要解决的问题。这就是为什么一开始就有这么多不同的 I/O 例程。
  • 这对我来说更有意义了,看来我必须随着时间的推移学习所有这些不同的方法,因为很难一口气全部理解 :) 所以谢谢你的帮助。
【解决方案2】:

getch()是一个提示按键的功能,其中字符不回显。

相比之下,getche() 会回显字符。

gets() 将从stdin 读取字符但不安全(请改用fgets())。

getchar() 将返回它从stdin 读取的下一个字符,这与使用stdin 作为参数调用getc() 相同。

fgets() 从流中读取字符(如文件或stdin),并将它们作为C 字符串存储到str 中,直到读取(num-1)个字符或换行或到达EOF .

putch() 将一个字符写入stdout。这与使用stdout 作为参数调用putc() 相同。

puts()str 指向的C 字符串写入stdout 并附加一个换行符。它开始复制,直到到达空终止符(\0)。不打印空终止符。

fputs()str 指向的C 字符串写入流,本质上类似于puts()

至于您的代码,尽量避免使用gets(),因为它不安全并使用scanf()puts() 也是如此。请改用printf()

在这里,阅读:http://www.cplusplus.com/reference/cstdio/

我知道它是 C++ 参考,但库函数是相同的

【讨论】:

  • 非常感谢,这消除了所有功能的一些困惑。当您说“getchar() 将返回它从标准输入读取的下一个字符”时,这到底是什么意思?
  • 这意味着你在循环中使用getchar()。像这样:#include &lt;stdio.h&gt; int main() { int nc = 0; for(;;) { do ++nc; while (getchar() != '\n'); printf("Character count is:%d\n%d\n", nc - 1); nc = 0; } }
【解决方案3】:
fgets
char * fgets ( char * str, int num, FILE * stream );
Get string from stream

从流中读取字符并将它们作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件结尾,以先到者为准。 换行符使 fgets 停止读取,但它被认为是有效字符,因此它包含在复制到 str 的字符串中。 在读取的字符之后会自动在 str 中附加一个空字符,以表示 C 字符串的结束。

fputs

int fputs ( const char * str, FILE * stream );
Write string to stream

将 str 指向的字符串写入流。 该函数从指定的地址 (str) 开始复制,直到到达终止空字符 ('\0')。这个最后的空字符不会复制到流中。

getchar

function
<cstdio>
int getchar ( void );

从标准输入中获取字符。 从标准输入 (stdin) 返回下一个字符。 相当于 getc 以 stdin 为参数。

putchar


function
<cstdio>
int putchar ( int character );

将字符写入标准输出 将字符写入标准输出 (stdout) 中的当前位置,并将内部文件位置指示器前进到下一个位置。 相当于 putc(character,stdout)。

gets: 从标准输入到内存

puts: 从内存到标准输入

Example : 

#include<stdio.h> 
void main( ) 
{ 
char name[10]; 
printf("What is your first and last name?"); 
gets(name); 
puts(name); 
}

【讨论】:

  • 哦,这就是为什么使用fgets,如果我指定一个包含 50 个元素的数组并且在我的程序中输入 50 个字符,它只打印 49 个字符?因为换行符是最后一个字符?
  • 在我的代码中,当我使用name 作为变量并将其作为参数传递给fgets 时,str 实际上是指向name 的指针?
  • fgets 应该能够从磁盘上的任何文件中读取,而不仅仅是从用户的键盘(或其他“标准输入”设备)。每当我们调用 fgets 时,我们只会传入一个名为 stdin 的变量,该变量在 stdio.h 中定义,它指的是“标准输入”。这有效地告诉程序从键盘读取。 fgets 将读取输入,直到它没有更多空间来存储数据或直到用户按下回车键。
  • 哦,好的,现在我明白了,所以标准输入只是任何一种常见的输入。谢谢。
猜你喜欢
  • 2021-05-25
  • 1970-01-01
  • 2015-04-08
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 2011-06-28
  • 2016-05-23
相关资源
最近更新 更多