我正在尝试使用fgets()
进行输入。我知道我会得到多少行,但它会改变,我会在变量var
中存储行数。我还有另一个名为part
的变量;它是我得到的线的长度,但由于值之间有空格我乘以2(我无法找到另一种解决方案;我可以使用一些建议)。
无论如何,我试着在下面的代码中获取输入,但当我进入第一行时,它会自动打开for
循环并打印随机内容。我认为这与循环中的fgets()
有关;我不知道是否有fgets()
这样的使用。
char inp[var][(2*part)];
int k,l;
for(k=0;k<=var;k++);
fgets(inp[k],(2*part),stdin);
printf("%c\n",inp[0]);
printf("%c\n",inp[1]);
printf("%c\n",inp[2]);
printf("%c\n",inp[3]);
答案 0 :(得分:1)
...因为值之间有空格我乘以2 ...
如果不需要将所有内容存储在堆栈中,则可以将字符串存储在动态分配的内存中。例如:
char* inp[var];
char buf[400]; // just needs to be long
for (k = 0; k < var; k++) {
fgets(buf, 400, stdin);
inp[k] = malloc(sizeof(char) * (strlen(buf) + 1));
strcpy(inp[k], buf);
}
虽然从技术上讲不符合标准,strdup
可以广泛使用,也可以使这更容易。
就实际问题而言,正如BLUEPIXY在上述评论中所说,你有一些错别字。
在for循环之后,分号使其意外动作。
for(k=0;k<=var;k++);
fgets(inp[k],(2*part),stdin);
实际上与
相同for(k=0;k<=var;k++) {
; // do nothing
}
fgets(...);
在for循环语句后删除该分号。事实上,你实际上并没有正确阅读,这就是你看垃圾的原因。
要打印整个字符串,printf
系列需要%s
格式标记。
使用k
上的边界,实际上会有var + 1
次迭代循环。如果var
为3
,则k = 0,1,2,3
- &gt;在k
检查4
后终止。
答案 1 :(得分:0)
通常,使用fgets
的最安全和最简单的方法是分配一个足够大的行缓冲区。用它来读取该行,然后将其复制到正确大小的缓冲区中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
// Allocate just the space for the list, not the strings themselves.
int num_input = 5;
char *input[num_input];
// Allocate our reusable line buffer.
char line[1024];
for( int i = 0; i < num_input; i++ ) {
// Read into the line buffer.
fgets(line, 1024,stdin);
// Copy from the line buffer into correctly sized memory.
input[i] = strdup(line);
}
for( int i = 0; i < num_input; i++ ) {
printf("%s\n",input[i]);
}
}
请注意,strdup()不是ISO C函数,而是POSIX。它很常见且足够标准。不使用它太方便了。如有必要,请自己写。
负责不了解线路长度。
如果您不知道要存储的行数,则必须增加阵列。通常,这是使用realloc
来重新分配现有内存。从小的列表大小开始,然后根据需要增长。加倍是一个很好的粗略近似,它是速度(重新分配可能很慢)和内存效率之间非常有效的平衡。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void) {
// How big the input list is.
size_t input_max = 64;
// How many elements are in it.
size_t input_size = 0;
// Allocate initial memory for the input list.
// Again, not for the strings, just for the list.
char **input = malloc( sizeof(char*) * input_max );
char line[1024];
while( fgets(line, 1024,stdin) != NULL ) {
// Check if we need to make the input list bigger.
if( input_size >= input_max ) {
// Double the max length.
input_max *= 2;
// Reallocate.
// Note: this is only safe because we're
// going to exit on error, otherwise we'd leak
// input's memory.
input = realloc( input, sizeof(char*) * input_max );
// Check for error.
if( input == NULL ) {
fprintf(stderr, "Could not reallocate input list to %zu: %s", input_max, strerror(errno) );
exit(1);
}
}
input[input_size] = strdup(line);
input_size++;
}
for( size_t i = 0; i < input_size; i++ ) {
printf("%s\n",input[i]);
}
}
正如您所看到的,这有点复杂。现在,您需要跟踪数组,最大大小和当前大小。使用该阵列的任何人都必须记住检查它的大小并增长它,并记得错误检查它。你的下一个冲动将是创建一个结构来收集所有这些,并用于管理列表。
这是动态内存管理的一个很好的练习,我鼓励你这样做。但是对于生产代码,请使用预先存在的库。 GLib是个不错的选择。它包含C中缺少的各种方便的数据结构和函数,包括pointer arrays that automatically grow。在生产代码中使用它们或类似的东西。