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] = '\0';
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("%s\n", words[d]);
}
我需要创建一个单词矩阵,但我不知道每个单词的大小以及会有多少单词。这就是我在每次迭代malloc
开始和之后使用realloc (size+1)
的原因,但是在第一次迭代之后,我得到了一个内存错误。我做错了什么,问题在哪里?
答案 0 :(得分:2)
虽然您可以一次使用面向字符的输入读取和索引字符,但有更容易的方法来解决此问题。例如,使用面向行的输入函数(例如fgets
或getline
),您可以一次读取/存储用户输入的整行数据。 / p>
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 quit\n\n");
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 ("\n\nInput provided by user:\n\n");
for (i = 0; i < idx; i++) /* print strings */
printf (" words[%2zu] : %s\n", 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)\n\n");
while (printf (" input ") && (nchr = getline (&line, &n, stdin)) > 1)
{ ...
我觉得有时候会更方便。
答案 1 :(得分:0)
其中一个主要错误是:
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 *));
这是因为单词指向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] = '\0';
你需要这样做:
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] = '\0';