使用C,从textFile打印出一个数组

我正在尝试创建一个从纺织品中读取的代码,然后将数据存储到内存中,打印到屏幕上以便用户可以读取它,但它仍然保存在内存中,以便您可以将其用于其余部分该计划..

这是纺织品的样本

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 

列表继续,它总共有150个单词,如果包含第一个数字,则为151行。 75用于告诉你有多少对。

无论如何,这是我到目前为止编写的代码,它使用这个结构

  typedef struct { char *English; char *TextSpeak; }Pair; 

我到目前为止编写的代码是:

  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); 

我不断得到的输出是:

  nevermind - atm by - definitely def - - - - - - 

它一直持续75行。

现在我不确定是否应该使用2D数组或者是否可以接受。 任何帮助将不胜感激! 谢谢

 phrases[i].English = malloc(sizeof(char)); 

这里的问题在于,您正在分配一个字节,然后尝试将字符串塞入其中,这会导致未定义的行为:

 fscanf(infile,"%s", phrases[i].English); 

通常,您应该假设一个合理的缓冲区长度并读取它,并检查是否包含新行。 如果不是这种情况,请再次读入另一个缓冲区或放大旧缓冲区(使用realloc )。 或者使用像getline这样的非标准function,已经为你做了这个。

鉴于你的行是非常短的句子,一个恒定的缓冲区大小就足够了(我们称之为MAX_LINE ),这为我们提供了一种更简单的方法来实现相同的目的:

 fscanf(infile, "%*[^\n]s", MAX_LINE, buf); 

MAX_LINE长度为MAX_LINE的字符串读入缓冲区buf并在遇到'\n'之前终止。

在读取字符串时,您应该避免使用fscanf("%s", buf)并使用fgets()scanf("%*s", MAX_LINE, ...)代替。 这样可以确保不会尝试写入比指定数据更多的数据,从而避免缓冲区溢出。

编辑:嵌套循环不应该在那里。 你基本上覆盖了phrases[i].TextSpeak总共phrases[i].TextSpeak phraseCounter时间没有任何好处。 在这个过程中你会泄漏很多记忆。

有很多方法可以做到这一点。 但是,我想要的一个建议是利用fgetsgetlineline-input工具来使文件读取更加健壮。 将fscanf用于离散变量是很好的(我把它留给了读取phraseCounter ),但是为了读取未知长度/内容的字符串数据,应该使用行输入。

下面是使用此代码的代码示例。 对代码进行了注释以解释逻辑。 这里真正的逻辑是你将为每个分配的结构读取2行。 使用% (mod)作为切换的简单行计数器可以帮助您跟踪何时分配新结构。 我还添加了代码来接受文件名作为程序的第一个参数。 (运行,例如./progname )。 如果您有任何疑问,请与我们联系:

 #include  #include  #include  #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; } 

输入

 $ 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 

产量

 $ ./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 

validation没有内存泄漏

 $ 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==  ==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)