int i=0, ii=1, j, k, choose=0;
char q='a';
char **words = (char **)malloc(sizeof(char));
words[i] = (char *)malloc(sizeof(char)+1);
do {
printf("you want again(0, 1)n");
scanf("%d", &choose);
j = 0; k = 1;
do {
fflush(stdin);
q = getchar();
*words[j] = q;
words[j] = (char *)realloc(words[j], (k+1) * sizeof(char));
j++; k++;
} while (q != 'n');
*words[k] = ' ';
i++; ii++;
words = (char**)realloc(words ,ii*sizeof(char));
} while (choose);
puts("pRINT");
int d = 0, t = 0;
for (d = 0; d < i; d++) {
printf("%sn", words[d]);
}
我需要创建一个单词矩阵,但我不知道每个单词的大小以及会有多少个。这就是为什么我在开始时和每次迭代后使用 malloc
realloc (size+1)
,但在第一次迭代之后,我收到内存错误。我做错了什么,问题出在哪里?
虽然您可以自由地使用面向字符的输入读取和一次索引字符,但有更简单的方法可以解决此问题。例如,使用面向行的输入函数(如fgets
或getline
),您可以一次读取/存储用户输入的整行数据。
getline
的优点是分配足够的内存来保存用户输入的每个字符串(由您来实施任何长度的健全性检查)。但是,如果您使用 getline
,则只需在达到初始指针数时关注重新分配。此外,如评论中所述,没有理由为每个输入realloc
(您可以,它只是效率很低)。您可以分配一些合理数量的指针,然后仅在达到该限制时才realloc
。
下面是一个显示替代方案的简短示例。查看一下,如果您有任何问题,请告诉我。 (注意:与其在手动生成的EOF
上停止循环,不如简单地检查是否nchr = 1
,如果用户只需按 Enter 而不输入数据,则自动退出。这取决于你。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NPTR 32
int main (void) {
char *line = NULL;
char **words = NULL;
size_t i, n, idx = 0, nptr = NPTR;
ssize_t nchr = 0;
/* initially allocate NPTR pointers */
if (!(words = malloc (sizeof *words * NPTR))) {
fprintf (stderr, "error: virtual memory exhausted.n");
return 1;
}
printf ("nEnter data [ctrl+d] ([crtl+z] on windows) to quitnn");
while (printf (" input ") && (nchr = getline (&line, &n, stdin)) != -1)
{ /* for each line read */
while (nchr && (line[nchr-1] == 'n' || line[nchr-1] == 'r'))
line[--nchr] = 0; /* strip newline or carriage rtn */
words[idx++] = strdup (line);
if (idx == nptr) { /* if limit reached -- realloc */
void *tmp = realloc (words, 2 * nptr * sizeof *words);
if (!tmp) {
fprintf (stderr, "error: realloc - memory exhausted.n");
exit (EXIT_FAILURE);
}
words = tmp;
nptr *= 2;
}
}
free (line);
printf ("nnInput provided by user:nn");
for (i = 0; i < idx; i++) /* print strings */
printf (" words[%2zu] : %sn", i, words[i]);
putchar ('n');
for (i = 0; i < idx; i++) /* free memory */
free (words[i]);
free (words);
return 0;
}
使用情况/输出
$ ./bin/getline_input
Enter data [ctrl+d] ([crtl+z] on windows) to quit
input my
input dog
input has
input fleas
input
Input provided by user:
words[ 0] : my
words[ 1] : dog
words[ 2] : has
words[ 3] : fleas
当用户在空白行上按 [Enter] 时退出
如上所述,使用输入后退出循环的另一种简单方法是检查getline
的返回值是否大于 1
。例如,您可以将初始提示和条件替换为:
printf ("nEnter data, ([Enter] on blank line to quit)nn");
while (printf (" input ") && (nchr = getline (&line, &n, stdin)) > 1)
{ ...
我发现有时更方便。
主要错误之一是:
char **words = (char **)malloc(sizeof(char));
和
words = (char**)realloc(words ,ii*sizeof(char));
您需要将其更改为
char **words = (char **)malloc(sizeof(char *));
和
words = (char**)realloc(words ,ii*sizeof(char *));
这是因为单词指向字符 *。
第二个问题是:
j = 0; k = 1;
do {
fflush(stdin);
q = getchar();
*words[j] = q;
words[j] = (char *)realloc(words[j], (k+1) * sizeof(char));
j++; k++;
} while (q != 'n');
*words[k] = ' ';
您需要改为执行以下操作:
j = 0;k = 1;
do {
fflush(stdin);
q = getchar();
words[i][j] = q;
j++; k++;
words[i] = (char *)realloc(words[i], (k+1) * sizeof(char));
} while (q != 'n');
words[i][j] = ' ';