嵌套在for循环中的fprintf不会写第一个元素

时间:2018-05-17 18:24:37

标签: c printf

描述

我正在尝试编写一个csv表tablepath,我需要在其中包含变量的名称,这些变量位于文本文件filepath中。我使用第一个函数read_par来检索filepath中的名称和第二个函数store,以便在表中写入。

问题

创建的表系统地缺少文本文件中第一个变量的名称read_par函数是有效的并产生预期的输出:包含变量名称的字符串,我也将其包含在上下文中。

filepath

  • 以下是文本文件的结构:

par1 0 1 0.5 par2 1 1 1 par3 0 1 1 par4 0 1 1 par5 0 1 1 par6 0 1 1

store

  • 以下是store函数:

    int store(int par_num, float sim_num, float **tab_param, char *filepath, char *tablepath){
    
    int j;
    char *name = NULL;
    FILE* sim_table = NULL;
    sim_table = fopen(tablepath, "w");  
    
    // Start the first line in the table
    fprintf(sim_table,"simulation_number");
    
    for(j=1; j < par_num+1; j++){
    
        // If it is the last parameter -> create a new line
        if(j == par_num){
    
            name = read_name(j, filepath);
            fprintf(sim_table,",%s\n", name);
        }else{
            /* If it is not the last parameter -> continue writing on 
             * the same line */
            name = read_name(j, filepath);
            fprintf(sim_table,",%s", name);
        }
    }
    fclose(sim_table);
    return 0;
    }
    

read_name

  • 以下是read_name函数:

    char *strtok(char *line, char *eof);    
    
    char *read_name(int par_id, char *filepath){
    
    char *par_name;
    int count = 0;
    
    FILE *file = fopen(filepath, "r");
    
    if ( file != NULL ){
    
        char line[256]; /* or other suitable maximum line size */
        while (fgets(line, sizeof line, file) != NULL){ /* read a line */
    
            if (count == (2*par_id)-2){
    
                // strtok removes the \n character from the string line
                strtok(line, "\n");
                par_name = line;
    
                fclose(file);
            }
            else{
                count++;
            }
        }
    }
    else
    {
        printf("\n\n ERROR IN FUNCTION READ_PAR\n\nTEXT FILE IS EMPTY\n\n");
    }
    return par_name;
    }
    

tablepath

我获得的表格如下:

┌─────────────────┬┬────┬────┬────┬────┬────┐
│simulation_number││par2│par3│par4│par5│par6│
└─────────────────┴┴────┴────┴────┴────┴────┘

缺少par1名称,但成功打印了所有其他变量名称。我不知道问题出在哪里。这是for循环条件中的问题还是与par1字符串本身有关的问题?

感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:0)

问题是read_name返回局部变量的地址(line)。当函数返回时,该局部变量超出范围(并且在技术上不再存在)。因此,使用返回的指针会产生undefined behavior

更清楚地看到问题,这里是read_name的简化版本,只显示了相关的行:

char *read_name(int par_id, char *filepath){

    char *par_name;

        char line[256];             // line is a local variable
        while (fgets(line, sizeof line, file) != NULL){

                par_name = line;    // par_name now points to the local variable
        }
    }
    return par_name;                // returning the address of the local variable
}

在问题的评论中注意到read_name已经过测试并被发现具有功能性。那怎么可能是错的?这是关于C中未定义行为的最糟糕的事情。有时代码似乎在测试期间工作,即使它在技术上是不正确的。从技术角度来看,我的意思是在某个时刻中断。例如,在store函数中,如果您在调用read_name和调用fprintf之间添加其他函数调用,则name很可能会被损坏,并且无法正确打印。

在这种情况下,一个简单的解决方案是使用line关键字声明static

static char line[256];

这样,line具有静态存储持续时间,这意味着它会在read_name返回后继续存在。