Fallo al dar valores a un array de chars

Iniciado por fileteruso, 16 Mayo 2020, 00:37 AM

0 Miembros y 1 Visitante están viendo este tema.

fileteruso

Hola, estoy intentando dar un valor a algunas posiciones de un array de chars y estoy teniendo un problema al final a la hora de devolverlo. Cuando le meto los valores se ve que lo está haciendo bien pero después, a la hora de imprimirlos, me devuelve, para cada posición que he escrito, el valor que le di al último. El código que llevo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

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

int n = 0;
char line[80], input[80];
char *array[25];

for(;fgets(line, 80, stdin);){
       if(!strcmp(line, "Exit\n")){
    break;
       }

   //  Leer de la entrada estándar
   sscanf(line, "%s", input);
   array[n] = input;
   printf("%s\n", array[n]);
   n++;
}

for(int i=0; i<n; i++){
printf("%s\n", array[i]);
}
}


Para la siguiente ejecución:

fileteruso@vbox-ubuntu:~/Escritorio/Pruebas$ ./prueba
ESTO
ESTO
ES
ES
UNA
UNA
PRUEBA
PRUEBA
Exit
PRUEBA
PRUEBA
PRUEBA
PRUEBA


Si alguien puede ayudarme le estaría muy agradecido.

K-YreX

Hay varias incorrecciones pero digamos que el problema principal está en el operador =. Cuando se trabaja con punteros el operador = hace que el puntero de la izquierda apunte a la dirección de memoria que se especifique a la derecha.
En tu caso, cada uno de los punteros del array <array> están apuntando a la dirección de memoria de <input> e <input> contiene la última cadena introducida por la entrada estándar. Por lo tanto, todos los punteros del array están apuntando a una misma cadena, cuando muestras todas en el último bucle estás mostrando la misma cadena (<input>) n veces.

Otro error es el de usar un array de punteros. Como ves esto no sirve pues todos los punteros acabarán apuntando a un mismo sitio y cuando cambies el valor de esa variable, perderás todos los anteriores.
La solución: usar una matriz. Cada fila será una entrada y cada columna un carácter.

#define MAX_ENTRADAS 20 // Numero maximo de entradas por teclado
#define MAX_LONGITUD 50 // Longitud maxima de cada entrada

int main(){
  char matriz[MAX_ENTRADAS][MAX_LONGITUD];
}

Aprovecho el código para decirte que utilices mejor constantes. Así si en algún momento quieres cambiar un valor, solo tendrás que cambiarlo en el lugar en el que lo has declarado.

Además de eso, otra incorrección es utilizar sscanf() para eliminar el salto de línea final (que supongo que lo haces para eso). Esto no es válido porque sscanf() no recoge los espacios por lo que una cadena con espacios (ej: "hola mundo") la truncará al primer espacio que encuentre ("hola").
Una alternativa para hacerlo es la siguiente:

#define SIZE 100
//...
char entrada[SIZE];
fgets(entrada, SIZE, stdin);
if(entrada[strlen(entrada)-1] == '\n') // el ultimo caracter siempre es '\0'. Entonces si el anterior es un salto de linea '\n'...
  entrada[strlen(entrada)-1] = '\0'; // ... le pones el fin de cadena uno antes para eliminar el '\n'


Otra cuestión es el tema de comparar cadenas. Si utilizas strcmp() y usas una longitud máxima de 5, al escribir "exit\n" solo se va a guardar "exit" y al compararlo no va a coincidir. Por esto es más seguro utilizar strncmp():
strncmp(matriz[n], "exit\n", strlen(matriz[n]))
Así compararás tantos caracteres como tenga la primera cadena. Si introduces "exit\n" y solo se guarda "exit", se compararán los 4 primeros caracteres de cada cadena y por tanto saldrá del bucle. Además si introduces "ex" pensando que va a comparar los dos primeros de la cadena, no saldrá porque comparará "ex\n" con "exi".

Y para futuras ocasiones, para copiar el contenido de una cadena en otra, tienes que utilizar las funciones strcpy() o strncpy(). Recomendable usar la segunda ya que puedes especificar la longitud.

Dicho esto puedes utilizar algo así:

while(n < MAX_ENTRADAS && fgets(matriz[n], MAX_LONGITUD, stdin) && strncmp(matriz[n], "exit\n", strlen(matriz[n]))){
    if(matriz[n][strlen(matriz[n])-1] == '\n')
        matriz[n][strlen(matriz[n])-1] = '\0';
    ++n;
}

Como puedes ver te ahorras los otros arrays auxiliares. Y debes comprobar primero que n no sobrepase el límite de entradas para que matriz[n] no produzca un error en memoria al intentar acceder a espacio de memoria no permitido.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

fileteruso