FILE *file;
file = fopen(argv[1], "r");
char *match = argv[2];
if (file == NULL) {
printf("File does not existn");
return EXIT_FAILURE;
}
int numWords = 0, memLimit = 20;
char** words = (char**) calloc(memLimit, sizeof(char));
printf("Allocated initial array of 20 character pointers.n");
char string[20];
while (fscanf(file, "%[a-zA-Z]%*[^a-zA-Z]", string) != EOF) {
words[numWords] = malloc(strlen(string) + 1 * sizeof(char));
strcpy(words[numWords], string);
printf("Words: %sn", words[numWords]);
numWords++; /*keep track of indexes, to realloc*/
if (numWords == memLimit) {
memLimit = 2 * memLimit;
words = (char**) realloc(words, memLimit * sizeof(char*)); /*Fails here*/
printf("Reallocated array of %d character pointers.n", memLimit);
}
}
代码应该打开并读取一个包含标点符号,空格等单词的文件,并存储在字符串中,但经过20次尝试后,它会抛出一个错误,我似乎无法让realloc()在这里工作,这是我期望的问题。数组被动态分配20个char指针,当达到限制时,它应该以双精度重新分配。我怎么才能避开这个问题呢?
注意两点。首先,不应该强制转换calloc/malloc/realloc的返回值。
第二,正如其他人在评论中指出的那样,第一个calloc语句使用了sizeof(char)
而不是sizeof(char*)
。
words
是指向指针的指针。其思想是分配一个指针数组。
下面的代码是错误的,因为它分配memLimit
字符而不是memLimit
指针。
这是主要问题
char** words = (char**) calloc(memLimit, sizeof(char)); // bad
所以使用一个简单的习惯用法:分配words
所指向的memLimit
组。它更容易编写、阅读和维护。
char** words = calloc(memLimit, sizeof *words);
避开while (scanf() != EOF)
孔。回想一下,scanf()
家族可以产生各种结果。它返回成功扫描字段的计数或EOF
。这通常是至少三种选择中的一种。所以不要测试一个你不想要的结果,测试一个你想要的结果。
// while (fscanf(file, "%[a-zA-Z]%*[^a-zA-Z]", string) != EOF) {
while (fscanf(file, "%[a-zA-Z]%*[^a-zA-Z]", string) == 1) {
上面的例子不一定都返回0,但是下面的例子很容易返回0。
int d;
while (fscanf(file, "%d", &d) == 1) {
@Enzo Ferber正确地建议使用"%s"
。进一步建议遵循上述习惯用法,并将输入宽度限制为小于缓冲区大小的1。
char string[20];
while (fscanf(file, "%19s", string) == 1) {
建议养成检查分配结果的习惯。
// better to use `size_t` rather than `int `for array sizes.
size_t newLimit = 2u * memLimit;
char** newptr = realloc(words, newLimit * sizeof *newptr);
if (newptr == NULL) {
puts("Out-of-memory");
// Code still can use old `words` pointer of size `memLimit * sizeof *words`
return -1;
}
memLimit = newLimit;
words = newptr;
}
错误信息
- 不要强制转换malloc/calloc返回。没有必要。 你的第一个
-
scanf()
格式字符串。%s
做得很好。
sizeof
是错误的。应该是sizeof(char*)
下面的代码为我工作(每行打印一个单词):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *file;
file = fopen(argv[1], "r");
char *match = argv[2];
if (file == NULL) {
printf("File does not existn");
return EXIT_FAILURE;
}
int numWords = 0, memLimit = 20;
char **words = calloc(memLimit, sizeof(char*));
printf("Allocated initial array of 20 character pointers.n");
char string[20];
while (fscanf(file, "%s", string) != EOF) {
words[numWords] =
malloc(strlen(string) + 1 * sizeof(char));
strcpy(words[numWords], string);
printf("Words: %sn", words[numWords]);
numWords++; /*keep track of indexes, to realloc */
if (numWords == memLimit) {
memLimit = 2 * memLimit;
words = realloc(words, memLimit * sizeof(char *));
printf
("Reallocated array of %d character pointers.n",
memLimit);
}
}
}
调用./realloc realloc.c
希望能有所帮助。
您的第一次分配是有问题的。分配20个字符,并将它们视为20个字符指针。您超出了分配的缓冲区并损坏了内存。
第二次分配失败,因为堆已损坏。