int c = getchar()?

11 minutos de lectura

ok, estoy leyendo este libro: El lenguaje de programación C – Por Kernighan y Ritchie (segunda edición) y uno de los ejemplos. Tengo problemas para entender cómo funcionan las cosas.

#include <stdio.h>

#define MAXLINE 1000

int getline(char line[], int maxline);
void copy(char to[], char from[]);

int main(int argc, char *argv[])
{
    int len;

    int max;
    char line[MAXLINE];
    char longest[MAXLINE];

    max = 0;
    while((len = getline(line, MAXLINE)) > 1)
    {
        if(len > max)
        {
            max = len;
            copy(longest, line);
        }
    }
    if(max > 0)
        printf("%s", longest);

    getchar();
    getchar();
    return 0;   
}

int getline(char s[], int lim)
{
    int c, i;

    for(i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
        s[i] = c;
    if(c == '\n')
    {
        s[i] = c;
        ++i;     
    }
    s[i] = '\0';

    return i;
}

void copy(char to[], char from[])
{
    int i;

    i = 0;
    while((to[i] = from[i]) != '\0')
        ++i;
}

la línea : for(i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
donde dice c = getchar(), ¿cómo se puede ingresar un número entero = caracteres desde la línea de comando? Números enteros, sí, pero ¿cómo se almacenan los caracteres que escribo?

Gracias por adelantado

  • Vea también lo que sucede si usa char c = getchar() en lugar de int

    – Antti Haapala — Слава Україні

    13 de febrero de 2016 a las 9:17

  • Posible duplicado de ¿Por qué la variable utilizada para contener el valor de retorno de getchar debe declararse como int?

    – phuclv

    22 de febrero de 2019 a las 2:00

  • La regla general es mantener la pregunta con la mejor colección de respuestas.. La diferencia horaria no es relevante. ¿Cómo deben manejarse las preguntas duplicadas?

    – phuclv

    22 de febrero de 2019 a las 2:48

A diferencia de otros lenguajes que puede haber usado, los caracteres en C están números enteros char es solo otro tipo de número entero, generalmente de 8 bits y más pequeño que intpero sigue siendo un tipo entero.

Entonces, no necesitas ord() y chr() funciones que existen en otros idiomas que puede haber utilizado. En C puedes convertir entre char y otros tipos de enteros usando una conversión, o simplemente asignando.

A menos que ocurra EOF, getchar() se define para devolver “un carácter sin firmar convertido en un int” (igual que fgetc), así que si te ayuda, puedes imaginar que lee algunos caracteres, cluego regresa (int)(unsigned char)c.

Puede volver a convertir esto en un unsigned char solo por un reparto o asignación, y si está dispuesto a aceptar una pequeña pérdida de portabilidad teórica, puede convertirlo en un char con un elenco o asignándolo a un char.

  • entonces, en C, los caracteres y los números enteros son “lo mismo”, por así decirlo. y al hacer algo como myInt = myChar; que funciona debido a que hay valores ascii?

    – Rexis

    19 de agosto de 2011 a las 9:31

  • @Flyphe: más o menos, sí. En lo que respecta a C, un carácter es su valor numérico. De hecho, los caracteres literales en C, como 'a'tiene tipo int en lugar de escribir char. El valor numérico no es estrictamente tener para ser ASCII, las implementaciones de C en realidad pueden usar otra codificación como EBCDIC, pero es bastante poco probable que alguna vez encuentre eso.

    –Steve Jessop

    19 de agosto de 2011 a las 9:44


  • Tenga en cuenta que el tipo char es un tipo propio: el tipo entero más pequeño posible, generalmente de 1 byte de ancho. Por lo tanto, no solo se usa para almacenar letras ASCII, también se usa comúnmente cuando se trabaja con números pequeños 0-255 (sin signo) o -128 a 127 (con signo), para ahorrar memoria. Si hubiera usado un int, necesitaría 2 o 4 bytes en lugar de 1.

    – Lundin

    19 de agosto de 2011 a las 11:59


avatar de usuario
paxdiablo

los getchar() La función devuelve un número entero que es la representación del carácter ingresado. Si ingresa el carácter Aconseguirás 'A' o 0x41 devuelto (actualizado a un int y suponiendo que esté en un sistema ASCII, por supuesto).

La razón por la que devuelve un int preferible a char es porque necesita poder almacenar cualquier carácter más el indicador EOF donde se cierra el flujo de entrada.

Y, por lo que vale, ese no es realmente un buen libro para principiantes. Es de los días en que la eficiencia importaba más que la legibilidad y la facilidad de mantenimiento.

Si bien muestra cuán inteligentes fueron los gustos de K&R, probablemente debería buscar algo más… amigable para los novatos.

En cualquier caso, la última edición cubrió C89 y muchas cosas han cambiado desde entonces. Hemos pasado por C99 y ahora tenemos C11 y el libro no se ha actualizado para reflejar ninguno de ellos, por lo que está terriblemente desactualizado.

  • pero entonces, ¿cómo llegar al final imprime los caracteres escritos?

    – Rexis

    19 de agosto de 2011 a las 9:22

  • Oh esta bien. así que s[i] =c; en el ciclo for está agarrando cada carácter y almacenándolo en “s” mientras se asegura de que no sea EOF o \n

    – Rexis

    19 de agosto de 2011 a las 9:26

  • ¿Puede recomendar un libro C moderno que sea realmente bueno, en el sentido de tener algo que se aproxime al rigor que damos por sentado de gente como K&R, o de cualquiera de las 20 o 30 personas en SO que con frecuencia responden C? preguntas más correctamente de lo que parecen manejar los libros de texto corrientes?

    –Steve Jessop

    19 de agosto de 2011 a las 9:39

  • No hay nada malo con el libro que estoy usando, Dennis Ritchie creó el lenguaje C. Seguir el contenido es razonablemente sencillo. Estoy seguro de que con el tiempo lo conseguiré todo y lo entenderé todo. Honestamente, sin embargo, el libro está bien para principiantes.

    – Rexis

    19 de agosto de 2011 a las 10:14

  • No estoy de acuerdo: el libro es no bien para los principiantes, debería aprender a escribir código legible y mantenible, no frases innecesariamente complejas como ese ejemplo. Un compilador decente le dará el mismo código de máquina subyacente, ya sea que lo alimente con esa monstruosidad o con las cinco líneas equivalentes de código fuente decente. Avíseme cómo van las cosas en su primera revisión de código si produce algo así 🙂

    – pax diablo

    19 de agosto de 2011 a las 12:02

avatar de usuario
cdhowie

La C char El tipo es de 8 bits, lo que significa que puede almacenar el rango de enteros desde (dependiendo de si está firmado o no y el estándar C no dicta cuál es si no lo especifica) ya sea -128 a 127 o 0 a 255 (255 valores distintos; este es el rango de ASCII). getchar() devoluciones int, que será de al menos 16 bits (generalmente 32 bits en las máquinas modernas). Esto significa que puede almacenar el rango de charasí como más valores.

La razón por la cual el tipo de retorno es int es porque el valor especial EOF se devuelve cuando se alcanza el final del flujo de entrada. Si el tipo de devolución fuera charentonces no habría forma de indicar que se encontró el final de la transmisión (a menos que se necesitara un puntero a una variable donde se registró esta condición).

  • los C no se garantiza que el tipo char esté firmado, y no es tan inusual que no esté firmado. Por ejemplo, eso es predeterminado en ARM con gcc y otros compiladores.

    –Steve Jessop

    19 de agosto de 2011 a las 9:32


  • Tampoco se garantiza que no esté firmado, según tengo entendido.

    – cdhowie

    19 de agosto de 2011 a las 9:33

  • Correcto, tampoco se garantiza que no esté firmado. Se garantiza que será la misma representación que uno de signed char y unsigned char, por lo que su rango es el mismo que uno de esos. Simplemente no puede decir con certeza que sea de -128 a 127. Tampoco puede decir con certeza que sea de 8 bits, pero está muy de moda que sea de 8 bits, las excepciones son los mainframes antiguos de 9 bits y algunos chips DSP. que tienen caracteres de 16 o 32 bits.

    –Steve Jessop

    19 de agosto de 2011 a las 9:33


  • No necesita enviar un puntero, hay feof() y ferror(), pero desafortunadamente no hay versiones macro rápidas de ellos. Expandir los caracteres a int solo para poder incluir un valor de retorno EOF especial parece una elección de optimización realmente mala, lo que hace que C sea más complicado y restringido. Como NULL y cadenas terminadas en ‘\0’. C++ corrigió el error EOF/char/int: prueba la transmisión, no el “carácter”.

    – Potrzebie

    9 de junio de 2014 a las 15:04

  • La C char No se garantiza que el tipo sea exactamente de 8 bits. Se garantiza que sea por lo menos 8 bits, pero CHAR_BIT Puede que no sea exactamente 8.

    –Govind Parmar

    22 de febrero de 2019 a las 17:47

Ahora vamos a jugar un juego de lógica.

Char es también un tipo de entero que tiene un rango menor que int, más concretamente 8 bits, es decir 1 byte. Como todos sabemos, los tipos enteros consisten en firmados (predeterminados) y sin firmar. En cuanto al carácter, el rango de caracteres firmados es de -127 ~ 128 y el rango de caracteres no firmados es de 0 ~ 255. Ahora conocemos el tipo y la “capacidad” de los caracteres firmados y no firmados.

Los humanos entendemos los caracteres, mientras que la computadora reconoce solo la secuencia binaria. Por lo tanto, todo tipo de lenguaje de programación debe proporcionar un modelo para lidiar con la transición de caracteres a secuencia binaria. El código ASCII es el estándar para el mapeo que se aplica en C y muchos otros lenguajes de programación. Se necesita 0 – 255 para codificar caracteres básicos como 0-9, az y AZ, así como los especiales habituales.

Puede preguntarse si el carácter sin firmar es la elección exacta. Sin embargo, la programación debe saber cuándo parar. La forma más sencilla es cumplir con un valor especial, uno negativo es una buena opción ya que se pueden usar valores positivos más grandes para otros idiomas. Finalmente, C eligió -1, que es más comúnmente llamado EOF.

Ahora tenemos el punto. El carácter firmado no será suficiente para codificar caracteres ASCII, mientras que el carácter no firmado no deja espacio para el valor de terminación. Requerimos un rango más grande para equilibrar esto, es decir, el tipo int. Sabio?

Gracias por la respuesta de @cdhowie, realmente me encendió.

Cada carácter (incluidos los números) ingresado en la línea de comando se lee como un carácter y cada carácter tiene un valor entero basado en su código ASCII http://www.asciitable.com/.

  • El estándar C en realidad no garantiza que ASCII sea el conjunto de caracteres utilizado por la implementación, aunque haría un largo camino, posiblemente hasta un museo, para encontrar una implementación C donde no lo es.

    –Steve Jessop

    19 de agosto de 2011 a las 9:30

  • Sí, pero por simplicidad pensé que se suponía

    – Mate

    19 de agosto de 2011 a las 9:33

  • @Steve: err, trabajamos en máquinas todos los días que usan EBCDIC. De hecho, le garantizo que cada una de sus transacciones bancarias termina en esa máquina. Los venerables mainframes de System z, siguen dirigiendo las finanzas del planeta después de tantas décadas 🙂

    – pax diablo

    19 de agosto de 2011 a las 9:41

  • @paxdiablo: excelente, no me había dado cuenta. Con suerte, no dejan que la gente simplemente entre por la puerta y comience a programar aquellos específicos que ejecutan el sistema bancario. Mi punto es solo que tienes que hacer un esfuerzo para alejarte de ASCII, probablemente no sucederá por accidente mientras no estés mirando.

    –Steve Jessop

    19 de agosto de 2011 a las 9:53


avatar de usuario
Yogeesh Seralathan

La respuesta a su pregunta está respondida. Pero solo agrega 1 cosa más.

Como estás declarando variable c como int. Está bastante claro que estás tomando valores de 0 to 9 teniendo un valor ascii de 48-57. Entonces solo puede agregar 1 línea más al código-

c = c-48.

  • El estándar C en realidad no garantiza que ASCII sea el conjunto de caracteres utilizado por la implementación, aunque haría un largo camino, posiblemente hasta un museo, para encontrar una implementación C donde no lo es.

    –Steve Jessop

    19 de agosto de 2011 a las 9:30

  • Sí, pero por simplicidad pensé que se suponía

    – Mate

    19 de agosto de 2011 a las 9:33

  • @Steve: err, trabajamos en máquinas todos los días que usan EBCDIC. De hecho, le garantizo que cada una de sus transacciones bancarias termina en esa máquina. Los venerables mainframes de System z, siguen dirigiendo las finanzas del planeta después de tantas décadas 🙂

    – pax diablo

    19 de agosto de 2011 a las 9:41

  • @paxdiablo: excelente, no me había dado cuenta. Con suerte, no dejan que la gente simplemente entre por la puerta y comience a programar aquellos específicos que ejecutan el sistema bancario. Mi punto es solo que tienes que hacer un esfuerzo para alejarte de ASCII, probablemente no sucederá por accidente mientras no estés mirando.

    –Steve Jessop

    19 de agosto de 2011 a las 9:53


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad