c - 如何用 .txt 文件中的元素填充数组
问题描述
我有一个动态二维浮点数组和一个包含字符串、整数(行中的浮点数)和浮点数的文件。
M = (float**)malloc(num_lines * sizeof(float));
for(int i = 0; i < num_lines; i++){
M[i] = (float*)malloc(num_columns * sizeof(float));
}
例子:
2
John 3 5.5 89.5 30.67 0.00
Mary 4 78.9 67.4 67.3 9.0 0.00
(null)
行数是文件中的行数 + 1,列数是最大整数 + 1(在本例中为 5),因为 0.00 标记每行的结尾。如何仅将浮点数加载到内存中?我尝试了不同类型的循环,fgets
但strtok
由于变量类型不同,它不起作用。
代码是这样的:
for(int i = 0; i < num_lines; i++){
fgets(buf, 1000, aux);
name = strtok(buf, " ");
col = atoi(strtok(NULL, " "));
for(j = 0; j < num_columns; j++){
M[i][j] = atof(strtok(NULL, " "));
if(M[i][j] == 0.00){
break;
}
}
}
解决方案
这种解析有点痛苦,但不时地做一个很好的练习。这相对容易scanf
,但scanf
不适合玩具以外的任何东西。(实际上不可能正确处理任何事情,因为即使是简单的"%d"
格式说明符也会在某些输入上导致未定义的行为。)除非您愿意读取文件两次以确定列的最大大小,否则您不能预先分配整个阵列。取而代之的是,我建议您执行以下操作:
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* sample input
2
John 3 5.5 89.5 30.67 0.00
Mary 4 78.9 67.4 67.3 9.0 0.00
*/
FILE * xfopen(const char *, const char *);
void * xmalloc(size_t);
int get_row_count(FILE *in, char **line, size_t *cap, const char *name);
float * parse_line(const char *s, int lc);
int
main(int argc, char **argv)
{
int lc = 0;
char *line = NULL;
size_t cap = 0;
FILE *in = argc > 1 ? xfopen(argv[1], "r") : stdin;
int rows = get_row_count(in, &line, &cap, argv[1]);
float **M = xmalloc(rows * sizeof *M);
for( lc = 0; lc < rows && getline(&line, &cap, in) > 0; lc += 1 ){
M[lc] = parse_line(line, lc + 1);
}
if( lc != rows ){
warnx("invalid input: missing some rows");
}
for( int i = 0; i < lc; i++ ){
float *f = M[i];
for( int j = 0; j < f[0]; j++ ){
printf("%f\t", f[j + 1]);
}
putchar('\n');
}
}
float *
parse_line(const char *s, int lc)
{
/* Skip the name */
char *end;
while( *s && ! isspace(*s) ){
s += 1;
}
int siz = strtol(s, &end, 10);
if( siz <= 0 || ! isspace(*end) ){
errx(EXIT_FAILURE, "Invalid input on line %d", lc);
}
float *f = xmalloc((1 + siz) * sizeof *f);
f[0] = siz;
for( int i = 1; i < siz + 1; i += 1 ){
f[i] = strtof(end, &end);
}
while( isspace(*end) ){
end += 1;
}
if( *end == '\0' || strcmp(end, "0.00\n") ){
errx(EXIT_FAILURE, "Invalid input on line %d", lc);
}
return f;
}
int
get_row_count(FILE *in, char **line, size_t *cap, const char *name)
{
if( getline(line, cap, in) <= 0 ){
if( feof(in) ){
errx(EXIT_FAILURE, "Empty input");
} else {
err(EXIT_FAILURE, "%s", name);
}
}
char *end;
int rows = strtol(*line, &end, 10);
if( rows <= 0 ){
errx(EXIT_FAILURE, "invalid row count: %d", rows);
}
if( *end != '\n' ){
errx(EXIT_FAILURE, "unexpected input on line 1");
}
return rows;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}
推荐阅读
- sql - 在 Laravel 中使用 ORM 在 SQL 中有 vs. Where
- php - 将 PHP 代码放在 Glassfish docroot 文件夹中
- android - 如何连续播放原始文件夹中的歌曲,并且不循环播放
- tensorflow - 我可以使用 Pytorch 或 Tensorflow 获得推导的表达式吗?
- c - C中的字典输出
- angular - 绑定到 ngModel 但得到“未定义”(Angular 8)
- node.js - npm 错误!EPROTO:协议错误,符号链接 '../@babel/parser/bin/babel-parser.js' -> '/home/vagrant/code/proadco.test/node_modules/.bin/parser'
- css - 如何使用 CSS 或 Vuetify 独立于侧面的 div 垂直堆叠 div?
- javascript - 如何将我的 django like 按钮连接到 ajax 以自动刷新
- python - 尝试在 Python 中使用随机数为数独创建矩阵