vectores una tridimensionales suma programacion matriz matrices llenar imprimir bidimensionales arreglos c arrays memory file-io struct

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.