tridimensionales - Usando C, para imprimir una matriz desde textFile
suma de matrices en c (2)
Intento crear un código, que lea de textil, y luego almacene los datos en la memoria, los imprima en la pantalla para que el usuario pueda leerlos, pero aún se guardan en la memoria para que pueda usarlos para el resto Del programa..
Aquí está la muestra del textil
75
nevermind
nvm
not much
nm
no problem
np
people
ppl
talk to you later
ttyl
because
cuz
i don''t know
idk
as soon as possible
asap
yeah
ya
how are you
hru
you
la lista continúa, tiene un total de 150 palabras, 151 líneas si se incluye el primer número. El 75 sirve para decirle cuántas parejas hay.
de todos modos, aquí está el código que he escrito hasta ahora, usa esta estructura
typedef struct
{
char *English;
char *TextSpeak;
}Pair;
El código que he escrito hasta ahora es:
FILE *infile =fopen("dictionary.txt","r");
int phraseCounter;
fscanf(infile, "%i", &phraseCounter); //Now you have the number of phrase pairs
//Allocate memory
Pair *phrases=malloc(sizeof(Pair) * phraseCounter);
//Run loop
for(int i=0; i < phraseCounter; i++){
//Get the english word
phrases[i].English = malloc(sizeof(char));
fscanf(infile,"%s",phrases[i].English);
//run loop to read next line
for(int a=0; a < phraseCounter; a++){
phrases[i].TextSpeak = malloc(sizeof(char));
fscanf(infile,"%s",phrases[i].TextSpeak);
}
printf("%s - %s/n", phrases[i].English, phrases[i].TextSpeak);
}
fclose(infile);
for(int i=0; i < phraseCounter; i++)
free(phrases[i].English);
free(phrases);
El resultado que obtengo es:
nevermind - atm
by - definitely
def -
-
-
-
-
-
Y continúa por 75 líneas.
Ahora no estoy seguro de si debería usar una matriz 2D o si esto será aceptable. ¡Cualquier ayuda será apreciada! Gracias
hay muchas maneras de hacer esto. Sin embargo, una sugerencia que tendría sería hacer uso de herramientas de line-input
de line-input
como fgets
o getline
para hacer que la lectura del archivo sea más robusta. Está bien usar fscanf
para variables discretas (lo dejé para leer phraseCounter
), pero para leer datos de cadena de longitud / contenido desconocidos, la entrada de línea realmente debería ser utilizada.
A continuación se muestra un ejemplo de su código con esto empleado. El código se comenta para explicar la lógica. La lógica real aquí es el hecho de que leerá 2 líneas para cada estructura asignada. Un contador de línea simple usando %
(mod) como un alternar puede ayudarlo a mantener un registro de cuándo asignar una nueva estructura. También agregué código para aceptar el nombre del archivo como primer argumento del programa. (para ejecutar, por ejemplo ./progname <filename>
). Déjeme saber si usted tiene preguntas:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 128
typedef struct Pair
{
char *English;
char *TextSpeak;
} Pair;
int main (int argc, char** argv) {
if (argc < 2) {
fprintf (stderr, "error: insufficient input. Usage: %s filename/n", argv[0]);
return 1;
}
Pair **pair = NULL; /* pointer to array of pointers */
char line[MAXL] = {0}; /* variable to hold line read */
FILE* infile = NULL; /* file pointer for infile */
unsigned int phraseCounter = 0; /* count of pairs */
unsigned int index = 0; /* index to pairs read */
size_t nchr = 0; /* length of line read */
size_t lnum = 0; /* line number read */
/* open file and validate */
if (!(infile = fopen ((argv[1]), "r"))) {
fprintf (stderr, "error: file open failed ''%s''./n", argv[1]);
return 1;
}
/* read phraseCounter */
if (!fscanf (infile, "%u%*c", &phraseCounter)) {
fprintf (stderr, "error: failed to read phraseCounter./n");
return 1;
}
/* allocate phraseCounter number of pointers to Pair */
if (!(pair = calloc (phraseCounter, sizeof *pair))) {
fprintf (stderr, "error: memory allocation failed./n");
return 1;
}
/* read each line in file */
while (fgets (line, MAXL - 1, infile) != NULL)
{
nchr = strlen (line); /* get the length of line */
if (nchr < 1) /* if blank or short line, skip */
continue;
if (line[nchr-1] == ''/n'') /* strip newline from end */
line[--nchr] = 0;
if (lnum % 2 == 0) /* even/odd test for pair index */
{
/* allocate space for pair[index] */
if (!(pair[index] = calloc (1, sizeof **pair))) {
fprintf (stderr, "error: memory allocation failed for pair[%u]./n", index);
return 1;
}
pair[index]-> English = strdup (line); /* allocate space/copy to English */
}
else
{
pair[index]-> TextSpeak = strdup (line);/* allocate space/copy to TextSpeak */
index++; /* only update index after TextSpeak read */
}
lnum++; /* increment line number */
}
if (infile) fclose (infile); /* close file pointer after read */
/* print the pairs */
printf ("/n Struct English TextSpeak/n/n");
for (nchr = 0; nchr < index; nchr++)
printf (" pair[%3zu] %-24s %s/n", nchr, pair[nchr]-> English, pair[nchr]-> TextSpeak);
/* free memory allocated to pair */
for (nchr = 0; nchr < index; nchr++)
{
if (pair[nchr]-> English) free (pair[nchr]-> English);
if (pair[nchr]-> TextSpeak) free (pair[nchr]-> TextSpeak);
if (pair[nchr]) free (pair[nchr]);
}
if (pair) free (pair);
return 0;
}
Entrada
$ cat dat/pairs.txt
10
nevermind
nvm
not much
nm
no problem
np
people
ppl
talk to you later
ttyl
because
cuz
i don''t know
idk
as soon as possible
asap
yeah
ya
how are you
hru
Salida
$ ./bin/struct_rd_pairs dat/pairs.txt
Struct English TextSpeak
pair[ 0] nevermind nvm
pair[ 1] not much nm
pair[ 2] no problem np
pair[ 3] people ppl
pair[ 4] talk to you later ttyl
pair[ 5] because cuz
pair[ 6] i don''t know idk
pair[ 7] as soon as possible asap
pair[ 8] yeah ya
pair[ 9] how are you hru
Verificar que no haya pérdidas de memoria
$ valgrind ./bin/struct_rd_pairs dat/pairs.txt
==3562== Memcheck, a memory error detector
==3562== Copyright (C) 2002-2012, and GNU GPL''d, by Julian Seward et al.
==3562== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3562== Command: ./bin/struct_rd_pairs dat/pairs.txt
==3562==
<snip>
==3562==
==3562== HEAP SUMMARY:
==3562== in use at exit: 0 bytes in 0 blocks
==3562== total heap usage: 32 allocs, 32 frees, 960 bytes allocated
==3562==
==3562== All heap blocks were freed -- no leaks are possible
==3562==
==3562== For counts of detected and suppressed errors, rerun with: -v
==3562== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
phrases[i].English = malloc(sizeof(char));
Aquí el problema radica en que está asignando un solo byte y luego tratando de meter una cadena en él, lo que lleva a un comportamiento indefinido aquí:
fscanf(infile,"%s", phrases[i].English);
En general, debe asumir una longitud de búfer razonable y leer eso, y comprobar si la nueva línea está contenida. Si ese no es el caso, vuelva a leer en otro buffer o realloc
el anterior (usando realloc
). O eso o usa una función no estándar como getline que hace esto ya por ti bajo el capó.
Dado que las líneas son oraciones bastante cortas, un tamaño de búfer constante podría ser suficiente (llamémoslo MAX_LINE
), lo que nos proporciona una manera un poco más fácil de lograr lo mismo:
fscanf(infile, "%*[^/n]s", MAX_LINE, buf);
Esto lee una cadena de longitud MAX_LINE
en el buffer buf
y termina antes de que se encuentre ''/n''
.
Al leer cadenas, debe abstenerse de usar fscanf("%s", buf)
y usar fgets()
o scanf("%*s", MAX_LINE, ...)
lugar. Esto garantiza que no se intentará escribir más datos de los especificados, evitando los desbordamientos del búfer.
Editar: El ciclo anidado no debería estar allí. Básicamente está sobreescribiendo phrases[i].TextSpeak
un total de tiempos de phraseCounter
de phraseCounter
sin beneficio. Y en el proceso de eso pierdes mucha memoria.