我正在尝试创建一个从纺织品中读取的代码,然后将数据存储到内存中,打印到屏幕上以便用户可以读取它,但它仍然保存在内存中以便您可以使用它对于该计划的其余部分..
以下是纺织品的样本
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数组,或者这是否可以接受。任何帮助将不胜感激!感谢
答案 0 :(得分:0)
phrases[i].English = malloc(sizeof(char));
问题在于,您正在分配单个字节,然后尝试将字符串填入其中,这会导致未定义的行为:
fscanf(infile,"%s", phrases[i].English);
通常,您应该假定一个合理的缓冲区长度并读取它,并检查是否包含新行。如果不是这种情况,请再次读入另一个缓冲区或放大旧缓冲区(使用realloc
)。
或者使用像getline这样的非标准函数来为你做这件事。
鉴于你的行是相当短的句子,一个恒定的缓冲区大小就足够了(我们称之为MAX_LINE
),这为我们提供了一种更简单的方法来实现同样的目标:
fscanf(infile, "%*[^\n]s", MAX_LINE, buf);
这会将长度为MAX_LINE
的字符串读入缓冲区buf
,并在遇到'\n'
之前终止。
在阅读字符串时,您应该避免使用fscanf("%s", buf)
并使用fgets()
或scanf("%*s", MAX_LINE, ...)
。这样可以确保不会尝试写入比指定数据更多的数据,从而避免缓冲区溢出。
编辑:嵌套循环不应该在那里。您基本上覆盖phrases[i].TextSpeak
总共phraseCounter
次没有任何好处。在这个过程中你会泄漏很多记忆。
答案 1 :(得分:0)
有很多方法可以做到这一点。但是,我建议的一个建议是使用line-input
或fgets
等getline
工具来使文件读取更加健壮。可以将fscanf
用于离散变量(我将其保留为读取phraseCounter
),但是为了读取未知长度/内容的字符串数据,应该使用行输入。
下面是使用此代码的代码示例。对代码进行了评论以解释逻辑。这里真正的逻辑是你将为每个分配的结构读取2行。使用%
(mod)作为切换的简单行计数器可以帮助您跟踪何时分配新结构。我还添加了代码来接受文件名作为程序的第一个参数。 (运行,例如./progname <filename>
)。如果您有疑问,请告诉我们:
#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;
}
<强>输入强>
$ 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
确认没有内存泄漏
$ 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)