我必须从stdin读取一些字符(我不知道它们中有多少,但不超过MAX)并且我想将它们存储在一个数组中。这段代码片段是否正确?
char *c1 = (char*) malloc(MAX * sizeof(char)); //may be too much
fgets(c, MAX, stdin);
int size = strlen(c1);
char *c2 = (char*) realloc(c1, size * sizeof(char));
free(c1);
或者,当您不知道要存储多少元素时,是否有一种更优雅的方法来确定为阵列分配的内存量?
答案 0 :(得分:1)
在fgets()
中,您可能需要c1
,而不是c
。
你可以这样做(如果你坚持使用realloc()):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 50
int main() {
char *c1 = malloc(MAX * sizeof(char));
if(!c1) {
printf("malloc() failed\n");
return -1;
}
fgets(c1, MAX, stdin);
int size = strlen(c1);
char* c2;
if(c1[size - 1] == '\n') {
c1[size - 1] = '\0';
c2 = realloc(c1, (size) * sizeof(char));
} else {
c2 = realloc(c1, (size + 1) * sizeof(char));
}
if(!c2) {
printf("realloc() failed\n");
return -1;
}
c1 = NULL;
printf("Input was: %s\n", c2);
free(c2);
return 0;
}
以下是一些评论:
您希望读取字符串,因此您应该使用char*
,而不是。{
int*
。
通常,您不希望保留fgets()
读取的换行符,
因此我用了c1[size - 1] = '\0';
来覆盖它。但是,如果用户输入了允许的最大字符数,那么就没有空间,因此我们会检查换行符是否真的存储在缓冲区中。
在realloc()
中,您应该为大小分配空间
字符串,加上空终止者。这就是现在size+1
的原因。但是,在我们覆盖换行符的情况下,没有必要这样做,因为我们已经将字符串的大小减小了一个,因此size
就足够了。
永远不要忘记取消分配你的记忆。
但是,如果我是你,我会打印一条消息,警告用户输入MAX
字符并避免重新分配。
您会看到,ref of fgets()状态,函数将:
从流中读取字符并将它们作为C字符串存储到str中,直到读取(num-1)个字符或者到达换行符或文件结尾为止,以先发生者为准。
因此,即使用户输入更多,程序也不会崩溃。
正如Paul正确评论的那样,使用第二个指针是个好主意,这样如果realloc()
失败,我们就不会丢失数据。
另请注意,您不应该释放c1
,因为此指针无效且应设置为NULL
。 c1
可能指向c2
点的位置,因此如果我们释放c1
,则c2
将指向垃圾。或者可能是整个内存块被转移到其他地方,因此c1
指向垃圾,我们试图释放。