C、指针数组中的值消失(指针)
C, values in array of pointers dissapear (pointers)
我在这里似乎失去了对我的指针的引用。我不知道为什么,但我怀疑是 fgets 返回的指针把事情搞砸了。
有人告诉我从文件中读取单词的一个好方法是获取行然后用笔划分隔单词,但是如果我在单词 [i] 中的指针不断消失,我该怎么办呢。
文字
Natural Reader is
john make tame
我得到了结果。
array[0] = john
array[1] = e
array[2] =
array[3] = john
array[4] = make
array[5] = tame
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
int ch;
int count = 0;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n' || ch == ' ')
count++;
}
fseek(file, 0, SEEK_END);
size_t size = ftell(file);
fseek(file, 0, SEEK_SET);
char** words = calloc(count, size * sizeof(char*) +1 );
int i = 0;
int x = 0;
char ligne [250];
while (fgets(ligne, 80, file)) {
char* word;
word = strtok(ligne, " ,.-\n");
while (word != NULL) {
for (i = 0; i < 3; i++) {
words[x] = word;
word = strtok(NULL, " ,.-\n");
x++;
}
}
}
for (i = 0; i < count; ++i)
if (words[i] != 0){
printf("array[%d] = %s\n", i, words[i]);
}
free(words);
fclose(file);
return 0;
}
strtok 不分配任何内存,它 returns 指向缓冲区中分隔字符串的指针。
因此,如果要在循环迭代之间保留单词,则需要为结果分配内存
例如
word = strdup(strtok(ligne, " ,.-\n"));
您也可以通过对读取的每一行使用唯一的 ligne
来处理此问题,因此将其设为字符串数组,如下所示:
char ligne[20][80]; // no need to make the string 250 since fgets limits it to 80
然后你的 while 循环变为:
int lno = 0;
while (fgets(ligne[lno], 80, file)) {
char *word;
word = strtok(ligne[lno], " ,.-\n");
while (word != NULL) {
words[x++] = word;
word = strtok(NULL, " ,.-\n");
}
lno++;
}
根据文件最大大小的需要调整第一个下标,或者如果您不想要这么低的限制,则在每次迭代期间动态分配行缓冲区。如果您的实现支持,您也可以使用 getline
而不是 fgets
;它可以处理分配,但您需要在完成后释放块。
如果您正在处理 real-world 散文,您可能希望在列表中包含其他分隔符,例如冒号、分号、感叹号和问号。
我在这里似乎失去了对我的指针的引用。我不知道为什么,但我怀疑是 fgets 返回的指针把事情搞砸了。 有人告诉我从文件中读取单词的一个好方法是获取行然后用笔划分隔单词,但是如果我在单词 [i] 中的指针不断消失,我该怎么办呢。
文字
Natural Reader is
john make tame
我得到了结果。
array[0] = john
array[1] = e
array[2] =
array[3] = john
array[4] = make
array[5] = tame
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
int ch;
int count = 0;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n' || ch == ' ')
count++;
}
fseek(file, 0, SEEK_END);
size_t size = ftell(file);
fseek(file, 0, SEEK_SET);
char** words = calloc(count, size * sizeof(char*) +1 );
int i = 0;
int x = 0;
char ligne [250];
while (fgets(ligne, 80, file)) {
char* word;
word = strtok(ligne, " ,.-\n");
while (word != NULL) {
for (i = 0; i < 3; i++) {
words[x] = word;
word = strtok(NULL, " ,.-\n");
x++;
}
}
}
for (i = 0; i < count; ++i)
if (words[i] != 0){
printf("array[%d] = %s\n", i, words[i]);
}
free(words);
fclose(file);
return 0;
}
strtok 不分配任何内存,它 returns 指向缓冲区中分隔字符串的指针。
因此,如果要在循环迭代之间保留单词,则需要为结果分配内存
例如
word = strdup(strtok(ligne, " ,.-\n"));
您也可以通过对读取的每一行使用唯一的 ligne
来处理此问题,因此将其设为字符串数组,如下所示:
char ligne[20][80]; // no need to make the string 250 since fgets limits it to 80
然后你的 while 循环变为:
int lno = 0;
while (fgets(ligne[lno], 80, file)) {
char *word;
word = strtok(ligne[lno], " ,.-\n");
while (word != NULL) {
words[x++] = word;
word = strtok(NULL, " ,.-\n");
}
lno++;
}
根据文件最大大小的需要调整第一个下标,或者如果您不想要这么低的限制,则在每次迭代期间动态分配行缓冲区。如果您的实现支持,您也可以使用 getline
而不是 fgets
;它可以处理分配,但您需要在完成后释放块。
如果您正在处理 real-world 散文,您可能希望在列表中包含其他分隔符,例如冒号、分号、感叹号和问号。