这个函数的任务相当简单。给定一个 char* 数组、一个指向文件的指针和一个最大字大小,它会读取文件并将每个单词逐个复制到 char* 数组中。由于文件中每行有一个单词,因此使用n
作为单词之间的分隔符是有意义的。因此,考虑到这一点,代码应该相当容易解释:
void loadDictionary(char* strDictionary[], FILE* filePointer, int nMaxLetters)
{
int nNameCount= 0, nCursor = 0;
char* strCurrent;
char cCurrent;
//allocate space for a word
strCurrent = malloc(nMaxLetters * sizeof(char));
while ((cCurrent = fgetc(filePointer)) != EOF) {
if(cCurrent != 'n')
{
strCurrent[nCursor] = cCurrent;
nCursor++;
} else { //then we've reached the end of the line (word)
//add null termination to string
strCurrent[nCursor] = ' '; //SEG FAULT
//copy string to dictionary
memcpy(strDictionary[nNameCount], strCurrent, strlen(strCurrent)+1);
//increment count
nNameCount++;
//reset the cursor
nCursor = 0;
}
}
}
这段代码在我调用strCurrent[nCursor] = ' ';
的行处生成分段错误。我不确定为什么,因为从表面上看,此操作似乎应该与我称之为strCurrent[nCursor] = cCurrent;
的另一个块中的操作没有什么不同。strCurrent 应该分配足够的空间来存储所有必要的字符。所以,我有些茫然。帮我弄清楚这个,伙计们。
注意:我想我可能会更容易使用fgets
而不是fgetc
来完成此任务。我很可能会转向这一点;但是,由于我遇到了一个我不理解的错误,因此在我理解它之前,我不想让它独自一人。
编辑:
有人指出,错误可能发生在memcpy
操作中,可能是由于strDictionary
分配不当。这是分配strDictionary
的main
块。也许我犯了一个错误:
int main(int argc, char* argv[])
{
char** strDictionary;
FILE* filePointer;
int nResults = 0, nLines = 0, nNumLines, nMaxChars, i;
filePointer = fopen("dictionary.txt", "r");
//obtain the number of lines and the maximum word size of the dictionary
countLines(filePointer, &nNumLines, &nMaxChars);
//allocate memory for strDictionary
strDictionary = malloc(nNumLines * nMaxChars * sizeof(char));
printf("%d words in dictionary. Longest word is %d lettersn",
nNumLines, nMaxChars);
//Output here correctly prints: 1000 and 21
//reset the file pointer (not sure if this is a necessary step, but oh well)
filePointer = fopen("dictionary.txt", "r");
//load dictionary into memory
loadDictionary(strDictionary, filePointer, nMaxChars);
for (i=0; i<10; i++)
printf("%dth element of dictionary: %sn", i, strDictionary[i]);
return 0;
}
编辑2:
好的,我决定使用fgets()
而不是fgetc()
来大大简化我的函数。我还做了我认为对strDictionary
的正确malloc()
操作。但是,我仍然遇到赛格错误。以下是更新的代码:
void loadDictionary(char* strDictionary[], FILE* filePointer, int nMaxLetters)
{
printf("Call to loadDictionary. nMaxLetters = %dn", nMaxLetters);
int nWordCount= 0, nCursor = 0;
char* strCurrent;
char cCurrent;
strCurrent = malloc(nMaxLetters); //allocate space for a word
while (fgets(strCurrent, nMaxLetters, filePointer) != NULL)
{
memcpy(strDictionary[nWordCount], strCurrent, strlen(strCurrent)+1);
nWordCount++;
}
}
int main(int argc, char* argv[])
{
char** strDictionary;
FILE* filePointer;
int nResults = 0, nLines = 0, nNumLines, nMaxChars, i;
filePointer = fopen("dictionary.txt", "r");
//count the lines in the file (works fine)
countLines(filePointer, &nNumLines, &nMaxChars);
//allocate space for the dictionary
strDictionary = malloc(nNumLines * sizeof(char*));
for (i = 0; i<nLines; i++)
strDictionary[i] = malloc(nMaxChars * sizeof(char));
printf("%d words in dictionary. Longest word is %d lettersn",
nNumLines, nMaxChars);
//load dictionary into array
filePointer = fopen("dictionary.txt", "r");
loadDictionary(strDictionary, filePointer, nMaxChars);
for (i=0; i<10; i++)
printf("%dth element of dictionary: %sn", i, strDictionary[i]);
return 0;
}
在这里:
char cCurrent;
...
while ((cCurrent = fgetc(filePointer)) != EOF) {
您正在将fgetc()
的类型为int
的值截断为char
。这可能会导致 while 条件无法正确识别EOF
。cCurrent
必须int
.
这里:
//allocate space for a word
strCurrent = malloc(nMaxLetters * sizeof(char));
nMaxLetters
必须考虑一个表示字符串 NUL 终止符的额外字符。有没有说明?
顺便说一句,sizeof(char)
始终是 1。
现在,此参数声明:
char* strDictionary[]
相当于这个:
char** strDictionary
或者,IOW,指向char
指针的指针。这是因为在 C 中,数组永远不会作为参数传递,只有指向它们的第一个元素的指针是,尽管括号中的欺骗性语法表明某些东西是数组。
这一行:
memcpy(strDictionary[nNameCount], strCurrent, strlen(strCurrent)+1);
将获取指向char
nNameCount
指针,并将字符数据写入它指向的位置。
但是调用函数是否至少分配了与文件中将要有行一样多的字符串缓冲区(长度为nMaxLetters
)?在将此数组传递到loadDictionary()
之前,它是否使用指向这些缓冲区的指针填充了一些指向 char 的指针数组?IOW,此代码期望调用方执行以下操作:
#define nMaxEntries 1000
char* dictionary[nMaxEntries];
int i;
FILE* f;
...
for (i = 0; i < nMaxEntries; i++)
dictionary[i] = malloc(nMaxLetters);
loadDictionary(dictionary, f, nMaxLetters);
必须在上面的代码中检查内存分配失败。另外,我强烈建议将nMaxEntries
传递到loadDictionary()
中或在中使用它,这样如果文件的行数多于nMaxEntries
行数,您就不会溢出指针数组。nNameCount
不应该超过nMaxEntries
.
更新到更新的问题...
这里:
char** strDictionary;
...
strDictionary = malloc(nNumLines * nMaxChars * sizeof(char));
您不是按照上述分析loadDictionary()
所期望的那样创建指向char
的指针数组,而是在创建char
的 2D 数组。正因为如此,段错误很可能不发生在这一行上:
strCurrent[nCursor] = ' '; //SEG FAULT
但是在下一个,在调试器中可能不明显,直到您放大并查看代码的反汇编:
//copy string to dictionary
memcpy(strDictionary[nNameCount], strCurrent, strlen(strCurrent)+1);
UPDATE2:
我不明白为什么你现在为nNumLines
指针分配空间:
strDictionary = malloc(nNumLines * sizeof(char*));
但是在那些nNumLines
指针中,您初始化nLines
指针(如果我正确阅读您的最新代码,nLines
永远不会变成 0 以外的任何东西):
for (i = 0; i<nLines; i++)
strDictionary[i] = malloc(nMaxChars * sizeof(char));
有什么诀窍?错字?