嗨,我正在尝试编写一个将在运行时创建内存的程序,以便该程序可以在生成内存以存储字符串时连续运行,直到用户决定退出。但是,当我运行程序时,我可以正确输入字符串,但是打印出来是另一回事。我相信问题是在循环中我覆盖了通过每次迭代创建的内存。这是我到目前为止所拥有的:
int main(){
char **lines = NULL;
char sentence[1000];
int numOfLines = 1;
int i;
int j;
printf("Enter the sentence:n");
lines = (lines, numOfLines * sizeof *lines);
for (i=0; i <= numOfLines; i++){
fgets(sentence, 1000, stdin);
lines[i] = malloc (sizeof(char) * strlen(sentence) +1);
if (strcmp(sentence, ".n") == 0){ //exits loops if entered string is "."
break;
}
strcpy(lines[i], sentence);
numOfLines++;
printf("%s", lines[i]); // attempt at a Debug statement
}
numOfLines = numOfLines - 1;
for (j = numOfLines; j>=0; j--){ //prints out the lines in reverse
printf("%sn", lines[j]);
}
return 0;
}
我可能会补充一点,当用户退出循环时,我遇到了分段错误。
lines[i] = malloc (sizeof(char) * strlen(sentence + 1));
这是一个问题。应该是
lines[i] = malloc (sizeof(char) * strlen(sentence) + 1);
问题
您可以在每个循环中执行此操作
lines = malloc(sizeof(char *) * numOfLines);
如果你退出早期不使用的线路充满了随机的垃圾
尝试(注意:修复纽约指数)
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
int main(){
char sentence[1000]; // NYI - fix magic
int numOfLines = 0;
int maxNumOfLines = 10;
char **lines=malloc(sizeof(char *) * maxNumOfLines); // NYI - calloc
bzero(lines, sizeof(char *) * maxNumOfLines); // NYI - calloc
printf("Enter the sentence:n");
for (int i=0; i < maxNumOfLines; i++) {
fgets(sentence, 1000, stdin);
lines[i] = malloc (sizeof(char) * strlen(sentence) + 1);
if (strcmp(sentence, ".n") == 0){
strcpy(lines[i], ".n");
break;
}
strcpy(lines[i], sentence);
numOfLines++;
//printf("%s", lines[i]); // intial Debug statement
}
for (int j = numOfLines-1; j>=0; j--){
printf("%sn", lines[j]);
}
return 0;
}
请注意,您需要设置最大值并在达到最大值之前退出循环,或者让用户输入最大值并动态设置它。
lines = malloc(sizeof(char *) * numOfLines);
在每次迭代中,您都会分配一个全新的数组,而旧数组将丢失(未释放,并且不再可寻址)。 这里你想要的是 realloc(3)。
lines[i] = malloc (sizeof(char) * strlen(sentence + 1));
正如安德鲁詹金斯提到的,你想要strlen(sentence) + 1
。 您的代码分配的字节比您需要的少 2 个字节。 (考虑一下sentence + 1
是什么。 一个不太容易出错的成语是1 + strlen(sentence)
.
Posix 定义了一个更方便的功能,strdup
(3),有助于避免这种栅栏错误。
如果可以的话,有一句忠告:您没有检查您的分配是否返回有效值。 尽管现在内存很大(在 Linux 上,内存通常比实际内存大),但正确的逻辑处理来自任何函数调用的错误。
修复代码的另一种方法(尚未提及)是更改:
lines = malloc(sizeof(char *) * numOfLines);
自:
lines = realloc(lines, numOfLines * sizeof *lines);
(注意,我使用推荐的sizeof
习语来提高代码健壮性)。并在循环之前,char **lines = NULL;
.
然后,包含行指针的内存块将根据需要增加大小。
请注意,您应该检查 malloc
和 realloc
的返回值,如果它返回 NULL,则采取适当的操作。如果您希望能够在 realloc 发生故障的情况下恢复程序,请参阅此处。