c - puerto - php serial extension
Lectura de un archivo y almacenamiento en matriz (4)
He escrito el siguiente programa para leer línea por línea desde un archivo y almacenarlo en la matriz de palabras. La salida debe ser de dos palabras aleatorias de la matriz. Pero, sorprendentemente, la matriz de palabras contiene solo la última palabra leída repetidamente. ¿Alguna ayuda sobre lo que salió mal?
int main(){
int i = 0;
char line_buffer[BUFSIZ];
char* words[20];
FILE *fp = fopen("input.txt", "r");
while (fgets(line_buffer, sizeof(line_buffer), fp)) {
//printf("%s", line_buffer);
words[i] = line_buffer;
i = i + 1;
}
printf("%d", i);
int j = rand()%8;
int k = (j+1)%8;
printf("%s %s", words[j], words[k]);
fclose(fp);
return 0;
}
input.txt
nematode knowledge
empty bottle
nevertheless
claustrophobia
metamorphosis
acknowledgement
impossibility
never gave up
¿Inicializaste el generador de números aleatorios con srand
? Una explicación, con un ejemplo de cómo usarla, está disponible aquí .
Sobreescribe repetidamente la memoria en line_buffer. La matriz de palabras contiene solo punteros esta variable.
Debería usar una matriz multidimensional o asignar memoria en tiempo de ejecución.
Por cierto: sucederán cosas malas cuando pase más de 20 líneas a su código ...
Usted lee cada línea de datos en el mismo buffer, por lo que la última línea sobrescribe todas las líneas anteriores. strdup()
que asignar espacio para cada línea de una u otra forma: asignación de memoria dinámica con malloc()
(o posiblemente strdup()
), o utilizando una matriz de tamaño fijo (lo que limita la cantidad de datos que su programa puede manejar con seguridad). También necesitará lidiar con nuevas líneas en la lectura de datos.
Obtienes algún crédito por usar fgets()
y no usar gets()
; esa es una decisión 100% correcta.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
enum { MAXLINES = 30 };
int main(void)
{
int i = 0;
char lines[MAXLINES][BUFSIZ];
FILE *fp = fopen("input.txt", "r");
if (fp == 0)
{
fprintf(stderr, "failed to open input.txt/n");
exit(1);
}
while (i < MAXLINES && fgets(lines[i], sizeof(lines[0]), fp))
{
lines[i][strlen(lines[i])-1] = ''/0'';
i = i + 1;
}
fclose(fp);
printf("%d/n", i);
srand(time(0));
int j = rand() % i;
int k = (j+1) % i;
printf("%s %s/n", lines[j], lines[k]);
return 0;
}
Esto verifica que el archivo se haya abierto con éxito, cierra el archivo tan pronto como se completa la lectura y garantiza que no desencadene un desbordamiento de la pila leyendo más líneas de las que la matriz puede contener. Se desperdicia mucho espacio asignando demasiado espacio, por lo que cada línea puede ser muy larga (aunque las líneas suelen ser bastante cortas). Si una línea es más larga que BUFSIZ, se leerá en un par de entradas adyacentes en lines
. No supone que haya 8 líneas en el archivo de datos. Desplaza la nueva línea al final de cada línea (a menos que una línea se divida, en cuyo caso elimina el último carácter antes de la división en la primera de las dos líneas). Siembra el generador de números aleatorios con la hora actual. Parece extraño que solo quieras líneas adyacentes del archivo.
int main(){
int i = 0;
int BUFSIZE = 1000;
char* words[20];
FILE *fp = fopen("input.txt", "r");
if (fp == 0){
fprintf(stderr, "Error while opening");
exit(1);
}
words[i] = malloc(BUFSIZE);
while (fgets(words[i], BUFSIZE, fp)) {
i++;
words[i] = malloc(BUFSIZE);
}
printf("Output: /n");
srand(time(NULL));
int j = rand()%i;
int k = (j+1)%i;
fflush(stdout);
printf("%d - %s %d -%s", j, words[j], k, words[k]);
int x;
for(x = 0; x<i; x++)
free(words[x]);
scanf("%d", x);
fclose(fp);
return 0;
}
PD. Verificar el resultado de malloc