fputc - fgetc c
Diferencia entre int y char en getchar/fgetc y putchar/fputc? (2)
Siempre use int para guardar caracteres de getchar() ya que la constante EOF es de tipo int . Si usa char , la comparación con EOF no es correcta.
putchar() embargo, puede pasar de manera segura char a putchar() ya que se promocionará a int automáticamente.
Nota : Técnicamente, usar char funcionará en la mayoría de los casos, pero luego no se puede tener el carácter 0xFF, ya que se interpretará como EOF debido a la conversión de tipo. Para cubrir todos los casos, siempre use int . Como @Ilja lo puso - int es necesario para representar los 256 valores de caracteres posibles y el EOF , que son 257 valores posibles en total, que no se pueden almacenar en el tipo de caracteres.
getchar aprender C por mi cuenta y estoy un poco confundido con getchar y putchar :
1
#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;
}
La función de biblioteca C int putchar(int c) escribe un carácter (un carácter sin signo) especificado por el argumento char a stdout.
La función de biblioteca C int getchar(void) obtiene un carácter (un carácter sin signo) de stdin. Esto es equivalente a getc con stdin como argumento.
¿Significa que putchar() acepta tanto int como char o cualquiera de ellos y para getchar() deberíamos usar un int o char ?
TL; DR:
-
char c; c = getchar();está mal, roto y con errores . -
int c; c = getchar();es correcto
Esto también se aplica a getc y fgetc , si no aún más, porque uno leería a menudo hasta el final del archivo.
getchar siempre el valor de retorno de getchar ( fgetc , getc ...) (y putchar ) inicialmente en una variable de tipo int .
El argumento para putchar puede ser cualquiera de int , char , signed char o unsigned char ; su tipo no importa, y todos funcionan de la misma manera, aunque uno puede dar como resultado números enteros positivos y otros en números enteros negativos que se pasan para los caracteres anteriores e incluyen /200 (128).
La razón por la que debe usar int para almacenar el valor de retorno de getchar y putchar es que cuando se alcanza la condición de fin de archivo (o se produce un error de E / S), ambos devuelven el valor de la macro EOF que es una constante entera negativa, (generalmente -1 ) .
Para getchar , si el valor de retorno no es EOF , es el unsigned char lectura zero-extended a un int . Es decir, suponiendo caracteres de 8 bits, los valores devueltos pueden ser 0 ... 255 o el valor de la macro EOF ; asumiendo de nuevo el carácter de 8 bits, no hay forma de exprimir estos 257 valores distintos en 256 para que cada uno de ellos pueda identificarse de manera única.
Ahora, si lo almacena en char , el efecto dependerá de si el tipo de carácter está firmado o no de manera predeterminada . Esto varía de compilador a compilador, arquitectura a arquitectura. Si se firma EOF y suponiendo que EOF se define como -1 , entonces tanto EOF como el carácter ''/377'' en la entrada se compararían con EOF ; se extenderán a (int)-1 .
Por otro lado, si char no está firmado (como lo es de forma predeterminada en los procesadores ARM, incluidos los sistemas Raspberry PI , y parece ser cierto también para AIX ), no hay ningún valor que pueda almacenarse en c que compare igual a -1 ; incluido EOF ; en lugar de irrumpir en EOF , su código generaría un único /377 caracteres.
El peligro aquí es que con las char firmadas el código parece estar funcionando correctamente aunque todavía esté terriblemente roto: uno de los valores de entrada legales se interpreta como EOF . Además, C89, C99, C11 no exige un valor para EOF ; solo dice que EOF es una constante entera negativa; por lo tanto, en lugar de -1 , podría decirse -224 en una implementación particular, lo que haría que los espacios se comporten como EOF .
gcc tiene el -funsigned-char que se puede usar para hacer que el char no esté firmado en esas plataformas donde se registra por defecto:
% cat test.c
#include <stdio.h>
int main(void)
{
char c;
printf("Enter characters : ");
while((c= getchar()) != EOF){
putchar(c);
}
return 0;
}
Ahora lo ejecutamos con char firmado:
% gcc test.c && ./a.out
Enter characters : sfdasadfdsaf
sfdasadfdsaf
^D
%
Parece estar funcionando bien. Pero con char sin signo:
% gcc test.c -funsigned-char && ./a.out
Enter characters : Hello world
Hello world
���������������������������^C
%
Es decir, intenté presionar Ctrl-D varias veces, pero se imprimió un for por cada EOF lugar de romper el ciclo.
Ahora, de nuevo, para el caso char firmado, no se puede distinguir entre char 255 y EOF en Linux, rompiéndolo para datos binarios y cosas por el estilo:
% gcc test.c && echo -e ''Hello world/0377And some more'' | ./a.out
Enter characters : Hello world
%
Solo la primera parte hasta el escape /0377 fue escrita en stdout.
Tenga en cuenta que las comparaciones entre las constantes de caracteres y un int contiene el valor del carácter sin firmar podrían no funcionar como se esperaba (por ejemplo, la constante de carácter ''ä'' en ISO 8859-1 significaría el valor con signo -28 . Por lo tanto, suponiendo que escriba código que leería hasta que ''ä'' en la página de códigos ISO 8859-1, harías
int c;
while((c = getchar()) != EOF){
if (c == (unsigned char)''ä'') {
/* ... */
}
}
Debido a la promoción entera, todos los valores char encajan en un int , y se promueven automáticamente en llamadas a función, por lo que puedes dar cualquiera de int , char , signed char o unsigned char a putchar como argumento (no para almacenar su valor de retorno), y funcionaría como se esperaba.
El valor real pasado en el entero puede ser positivo o incluso negativo; por ejemplo, la constante de caracteres /377 sería negativa en un sistema de 8 bitchar, donde char está firmado; sin embargo, putchar (o fputc realidad) arrojará el valor a un char sin signo. C11 7.21.7.3p2 :
2 La función fputc escribe el carácter especificado por
c(convertido a un carácter sin signo) en la secuencia de salida a la que apunta el flujo [...]
(énfasis mío)
Es decir, se garantiza que el fputc convertirá la c dada como si fuera (unsigned char)c