首页 > 解决方案 > 如何用 .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 标记每行的结尾。如何将浮点数加载到内存中?我尝试了不同类型的循环,fgetsstrtok由于变量类型不同,它不起作用。

代码是这样的:

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;
                }   
            }
        }

标签: c

解决方案


这种解析有点痛苦,但不时地做一个很好的练习。这相对容易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;                                                                 
} 
  

推荐阅读