是否存在类似于我在bash中编写的此实现的等效解决方案?通常情况下,我总是这样处理动态分配:
(我喜欢第二个实现,因为它很灵活,我不需要确切知道我需要多少输入,我可以按原样输入它们。我怎样才能在C中实现类似的方法?
C实施:
double* get_data(int* data_size)
{
double* data_set = NULL;
int size = get_size();
int i;
*data_size = size;
data_set = malloc(size * sizeof(double));
for(i = 0; i < size; i++)
{
printf("Enter statistical data: ");
scanf("%lf", &data_set[i]);
}
return data_set;
}
Bash实施:
data_set=()
while IFS= read -r -p 'Enter statistical data (empty line to quit):' input; do
[[ $input ]] || break
data_set+=("$input")
done
答案 0 :(得分:4)
最简单的解决方案是使用C ++。但那不是你要问的,所以我会留在那里。
以下内容虽然看起来很糟糕,但实际上通常非常有效(取决于你的C库的realloc
实现,但它是GNU代码中常见的习惯用法,因此realloc
实现是通常很适应它):
double* get_data(size_t *size_p) {
size_t n = 0;
double* data = NULL;
double val;
while (get_a_datum(&val)) {
double* newdata = realloc(data, (n + 1) * sizeof *data);
if (newdata == NULL) { free(data); report(error); }
data = newdata;
data[n++] = val;
}
if (size_p) *size_p = n;
return data;
}
如果您对这种方法不满意,可以滚动自己的指数realloc,跟踪分配的向量的大小,如果要超过它,则加倍。但是,这是更多的代码,realloc
很可能会为您做到这一点。
答案 1 :(得分:3)
scanf("%lf", &data_set[i]);
的问题在于scanf()
以静默方式跳过前导空格,包括空白行。
由于您希望在空行上终止,显而易见的解决方案似乎是使用fgets()
或getline()
来读取一行,然后使用sscanf()
来读取数据行不是空的。
因此:
char line[4096];
while ((fgets(line, sizeof(line), stdin) != 0)
{
if (line[0] == '\n')
break;
if (sscanf(line, "%lf", &data_set[i++]) != 1)
...format error...
}
请注意,每个I / O功能都会被检查。如果在空行上输入一个或两个空格,它们将进入“格式错误”代码。如果您愿意,可以使“空白行”的测试更加敏感(例如,考虑使用strspn()
和strlen()
。)
答案 2 :(得分:1)
根据需要重新分配。
double* data_set = NULL;
int size = 0;
int i = 0;
for(;;) {
printf("Enter statistical data: ");
double d;
// See @Jonathan Leffler for good idea on using blank line to terminate input
if (1 == scanf("%lf", &d)) {
break;
}
data_set = realloc(data_set, ++size * sizeof(double));
if (data_set == NULL) handle_error();
data_set[size-1] = d;
}
*data_size = size;
return data_set;