在getchar函数/龟etc和的putchar / INT的fputc和char的区别?

问题描述:

我想学习C我自己,我是那种与的getchar 的困惑和的putchar

I am trying to learn C on my own and I'm kind of confused with getchar and putchar:

#include <stdio.h>

int main(void)
{
    char c;
    printf("Enter characters : ");
    while((c = getchar()) != EOF){
      putchar(c);
    }
    return 0;
}

2

#include <stdio.h>

int main(void)
{
    int c;
    printf("Enter characters : ");
    while((c = getchar()) != EOF){
      putchar(c);
    }
    return 0;
}

C库函数 INT的putchar(INT C)写入由参数字符到stdout指定的字符(unsigned char类型)。

The C library function int putchar(int c) writes a character (an unsigned char) specified by the argument char to stdout.

C库函数 INT的getchar(无效)获取从标准输入一个字符(unsigned char类型)。这相当于是:标准输入作为其参数GETC。

The C library function int getchar(void) gets a character (an unsigned char) from stdin. This is equivalent to getc with stdin as its argument.

这是否意味着的putchar()同时接受 INT 字符或其中之一,并为的getchar()我们应该使用 INT

Does it mean putchar() accepts both int and char or either of them and for getchar() should we use an int or char?

TL; DR:


  • 字符℃; C =的getchar(); 错了,坏了,车

  • INT℃; C =的getchar(); 正确

  • char c; c = getchar(); is wrong, broken and buggy.
  • int c; c = getchar(); is correct.

这适用于 GETC 龟etc 还有,如果更加并非如此,因为你希望总是得到一个 EOF 读取文件时。

This applies to getc and fgetc as well, if not even more so, because you'd expect to always get an EOF when reading a file.

总是存储的getchar 的返回值(龟etc GETC ...)(和的putchar )开始到类型的变量 INT
参数的putchar 可以是任何 INT 的char 符号字符 unsigned char型;它的类型并不重要,和他们都工作相同,即使一个可能导致以正和负整数其他传递上面,并包括 \\ 200 字符( 128)。

Always store the return value of getchar (fgetc, getc...) (and putchar) initially into a variable of type int. The argument to putchar can be any of int, char, signed char or unsigned char; its type doesn't matter, and all of them work the same, even though one might result in positive and other in negative integers being passed for characters above and including \200 (128).

为什么你的原因必须使用 INT 来存储的返回值 的getchar 的putchar 是当达到 EOF 情况下,它们都返回宏 EOF 这是一个负的整型常量和(通常) 1 ;如果返回值不是 EOF ,它是读的无符号字符的零扩展为整数。也就是说,假设8位字符,返回可值 0 ... 255 或特殊的宏 EOF ;再次假定8位字符,没有办法去挤这257不同的值到256。

The reason why you must use int to store the return value of both getchar and putchar is that when EOF condition is reached, both of them return the macro EOF which is a negative integer constant, and (usually) -1; if the return value is not EOF, it is the read unsigned character zero-extended to an integer. That is, assuming 8-bit characters, the values returned can be 0...255 or the special macro EOF; again assuming 8-bit char, there is no way to squeeze these 257 distinct values into 256.

现在,如果你把它存储到字符代替,效果将取决于是否的字符类型是有符号或默认符号!这种由不同的编译器编译器,架构架构。如果字符签订并假设 EOF 定义为 1 两个 EOF 和字符'\\ 377'上的投入将比较等于 EOF ;他们会被符号扩展为(INT)-1

Now, if you stored it into char instead, the effect would depend on whether the character type is signed or unsigned by default! This varies from compiler to compiler, architecture to architecture. If char is signed and assuming EOF is defined as -1, then both EOF and character '\377' on input would compare equal to EOF; they'd be sign-extended to (int)-1.

在另一方面,如果字符是无符号的,还有的可能被存储在 C 的值/ code>将比较等于 1 ;包括 EOF ;而不是打破了上 EOF ,您的code将输出一个 \\ 377 字符。

On the other hand, if char is unsigned, there is no value that could be stored in c that would compare equal to -1; including EOF; instead of breaking out on EOF, your code would output a single \377 character.

这里的危险在于,与签署字符 S中的code的似乎是正确的,即使它是仍在工作可怕的破 - 合法的输入值之一是PTED为 EOF 间$ p $ 此外,C89,C99,C11并不强制为 EOF ;它只是说 EOF 是负的整型常量;从而代替 1 它可以同时是说 -224 在一个特定的实现,这将导致空间表现得像 EOF

The danger here is that with signed chars the code seems to be working correctly even though it is still horribly broken - one of the legal input values is interpreted as EOF. Furthermore, C89, C99, C11 does not mandate a value for EOF; it only says that EOF is a negative integer constant; thus instead of -1 it could as well be say -224 on a particular implementation, which would cause spaces behave like EOF.

GCC 具有可用于使开关 -funsigned-CHAR 符号在这些平台上它默认为签署

gcc has the switch -funsigned-char which can be used to make the char unsigned on those platforms where it defaults to signed:

% cat test.c
#include <stdio.h>

int main(void)
{
    char c;
    printf("Enter characters : ");
    while((c= getchar()) != EOF){
      putchar(c);
    }
    return 0;
}

现在,我们与运行它签署字符

Now we run it with signed char:

% gcc test.c && ./a.out
Enter characters : sfdasadfdsaf
sfdasadfdsaf
^D
%

似乎是工作的权利。但随着无符号字符

% gcc test.c -funsigned-char && ./a.out                   
Enter characters : Hello world
Hello world
���������������������������^C
%

这就是我试图preSS 按Ctrl-D 有很多次,但一个 印刷每个 EOF 而不是打破循环。

That is, I tried to press Ctrl-D there many times but a was printed for each EOF instead of breaking the loop.

现在,再次为签署字符的情况下,它不能字符 255 EOF 在Linux上,打破它的二进制数据和这样的:

Now, again, for the signed char case, it cannot distinguish between char 255 and EOF on Linux, breaking it for binary data and such:

% gcc test.c && echo -e 'Hello world\0377And some more' | ./a.out 
Enter characters : Hello world
%

只有第一部分到 \\ 0377 逃脱被写入stdout。

Only the first part up to the \0377 escape was written to stdout.

要注意的是字符常量和 INT 包含无符号字符值可能无法按预期工作(如字符常量',以'在ISO 8859-1将意味着符号值 -28 ,所以假设你写code,将读取输入直到在ISO 8859-1 codePAGE',以',你会做

Beware that comparisons between character constants and an int containing the unsigned character value might not work as expected (e.g. the character constant 'ä' in ISO 8859-1 would mean the signed value -28. So assuming that you write code that would read input until 'ä' in ISO 8859-1 codepage, you'd do

int c;
while((c = getchar()) != EOF){
    if (c == (unsigned char)'ä') {
        /* ... */
    }
}


由于整型提升,所有的字符价值观匹配到 INT ,并自动在函数调用提升,因此,你可以给任何 INT 字符的符号字符 unsigned char型的putchar 参数(而不是存储它的返回值) ,它会正常工作。


Due to integer promotion, all char values fit into an int, and are automatically promoted on function calls, thus you can give any of int, char, signed char or unsigned char to putchar as an argument (not to store its return value), and it would work as expected.

在整数传递的实际值可能是正的或甚至负的;例如字符常量 \\ 377 的一个8位字符的系统上,其中字符签署;然而的putchar (或的fputc 实际上)将值转换为unsigned char类型。

The actual value passed in the integer might be positive or even negative; for example the character constant \377 would be negative on a 8-bit-char system where char is signed; however putchar (or fputc actually) will cast the value to an unsigned char.