Mensaje de error: la conversión puede perder dígitos significativos

C Programa para aceptar y mostrar "5" caracteres usando las funciones getchar () y putchar ():

#include<stdio.h>
void main()
{
  char ch[6];

  ch[0]=getchar();
  ch[1]=getchar();
  ch[2]=getchar();
  ch[3]=getchar();
  ch[4]=getchar();

  putchar(ch[0]);
  putchar(ch[1]);
  putchar(ch[2]);
  putchar(ch[3]);
  putchar(ch[4]);
}

Cuando estoy compilando este código en lenguaje "C", aparece este mensaje de error: "La conversión puede perder dígitos significativos", ¿cuál podría ser el motivo?

preguntado el 08 de noviembre de 11 a las 19:11

2 Respuestas

getchar devuelve un int y lo estás almacenando en un char.

Puede solucionar esto cambiando char ch[6]; a int ch[6];.

respondido 08 nov., 11:23

Estoy usando "Boreland C ++" versión 4.5 - Gautham

getchar() devuelve un int, para permitir pasar valores adicionales que no están en el rango de caracteres válidos. Esto permite que las fallas y los códigos de error se devuelvan como valores sin sobrecargar un carácter en particular con múltiples significados. En el funcionamiento normal se puede devolver cualquier carácter válido, en el funcionamiento de error un int que es demasiado grande para caber en un char es regresado.

El mensaje de advertencia indica que solo va a mirar el char parte del valor devuelto, y como tal, extrañamente puede lanzar un error o un valor de retorno especial en un char que en realidad no fue capturado.

--- Editado a petición de gautham para demostrar una buena detección de errores ---

La falta de verificación de errores por fallas de entrada se puede solucionar de dos maneras. El primero es más común y funciona en todos los sistemas donde el tamaño de un número entero es mayor que el tamaño de un carácter.

  // an ok approach which works for most systems
  // provided that sizeof(int) != sizeof(char)
  int c = getchar();
  if (EOF != c) {
    ch[0] = (char)c;
  } else {
    // some error occurred during input capture
    // which resulted in getchar returning EOF
  }

La segunda solución para la verificación de errores en busca de fallas de entrada no se basa en que el tamaño de un número entero sea mayor que el tamaño de un carácter. Funcionará en todos los sistemas.

  // a better approach which works for all systems
  // even where sizeof(int) == sizeof(char)
  c = getchar();

  if (!feof(stdin) && !ferror(stdin)) {
    // even if c was EOF, we know it's a char value, not an error value
    ch[0] = c;
  } else {
    // c's value is EOF because of an error capturing the input, and
    // not because a char value equaling EOF was read.
  }

ponerlo todo junto para reescribir su programa

#include<stdio.h>
int main(int argc, char** argv)
{
  char ch[6];

  ch[0]=getchar();
  ch[1]=getchar();
  ch[2]=getchar();
  ch[3]=getchar();
  ch[4]=getchar();

  putchar(ch[0]);
  putchar(ch[1]);
  putchar(ch[2]);
  putchar(ch[3]);
  putchar(ch[4]);

  return 0;
}

o si ha sido introducido a los procedimientos, la versión mucho mejor de lo anterior

#include<stdio.h>

char getInput() {
  int c = getchar();

  if (!feof(stdin) && !ferror(stdin)) {
    return (char)c;
  } else {
    exit(EXIT_FAILURE);
  }
}

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

  ch[0]=getInput();
  ch[1]=getInput();
  ch[2]=getInput();
  ch[3]=getInput();
  ch[4]=getInput();

  putchar(ch[0]);
  putchar(ch[1]);
  putchar(ch[2]);
  putchar(ch[3]);
  putchar(ch[4]);

  return 0;
}

y si ha aprendido un poco sobre bucles, puede reescribirlo con un bucle como este.

#include<stdio.h>

char getInput() {
  int c = getchar();

  if (!feof(stdin) && !ferror(stdin)) {
    return (char)c;
  } else {
    exit(EXIT_FAILURE);
  }
}

int main(int argc, char** argv)
{
  char ch[6];
  int index;

  for (index = 0; index < 5; index++) {
    ch[index] = getInput();
  }

  for (index = 0; index < 5; index++) {
    putchar(ch[index]);
  }

  return 0;
}

Hay otras comprobaciones que quizás desee agregar, como comprobar si su putchar falló debido a un error durante la salida; pero, si no tiene un medio alternativo para presentar el error (como escribirlo en un archivo), agregar dichas comprobaciones solo aumentará la complejidad del código sin proporcionar un medio para comunicar el error al usuario final.

La verificación de errores es uno de los elementos más importantes al escribir programas robustos, pero en la mayoría de los cursos de programación se trata muy a la ligera (si es que se cubre). Si no tiene mucha discusión sobre la verificación de errores, hágase un favor y lea de forma independiente <errno.h>. Se puede encontrar una descripción decente de cómo manejar errores en C en las páginas de GNU discutiendo el manejo de errores. Un controlador de errores básico "imprimir en stderr" podría verse como

 // this defines errno
 #include <errno.h>
 // this defines perror
 #include <stdio.h>
 // this defines strerror
 #include <string.h>

 extern volatile int errno;

 void printError(int value) {
   perror(strerror(value));
 }

respondido 10 nov., 11:03

Funcionó bien porque las condiciones que podrían generar un error no ocurrieron durante esa ejecución del programa. - Edwin Buck

@gautham, el mundo está lleno de eventos inesperados. Normalmente, getchar responde con un char; pero, a veces, las cosas salen mal. Cuando algo sale mal, getchar responderá con un non-char. De esa manera, sabrá que es algo que salió mal, y no la entrada. Los errores incluyen el uso de getchar en algo que no se puede leer (stdin inválido), redirigir a través del shell un directorio como stdin, la computadora no tiene suficiente memoria para almacenar en búfer la entrada, el hardware falla y muchas otras condiciones en las que no es posible leer la entrada . - Edwin Buck

@gautham, no sé si hay un problema de idioma; pero parece que estás ignorando lo que he escrito. Intente leerlo de nuevo con atención. Su código puede funcionar por un tiempo, pero no verifica posibles condiciones de error. Cuando existe una condición de error, su código fallará gravemente. Esto no es un error de programación como elegir la función o el tipo incorrecto, es un error de programación como no verificar si ocurrió un error. Así que es como dar marcha atrás en un coche. No es que esté operando mal la máquina, es que no está mirando hacia atrás. - Edwin Buck

@gautham, lo siento si no estaba claro. Mi punto era no asumir que getchar funciona todo el tiempo. Es por eso que devuelve un int, para que sea más fácil de detectar cuando no funciona. La publicación se ha actualizado para reflejar su solicitud de un nuevo código. - Edwin Buck

La única diferencia es cuando se marca la condición de repetición. La declaración while se parece a while (condition) { block } y el do-while parece do {block} while (condition). En while, se comprueba la condición de repetición antes de ejecutar el bloqueo. En do-while se comprueba la condición de repetición después de ejecutar el bloqueo. Dado que do-while verifica que la condición se repita después de ejecutar el bloque, SIEMPRE ejecutará el bloque al menos una vez. El ejemplo más simple de una apariencia temporal se parece a while (true) { printf("hi"); } y dado que la condición nunca es falsa, este ciclo nunca terminará. - Edwin Buck

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.