退出while循环时fscanf失败

时间:2014-07-18 14:18:13

标签: c scanf

编辑:问题与使用fscanf的while循环没有直接关系,但在用于包含使用fscanf加载的变量的结构分配中是错误的

我正在从文件中读取值并使用它们使用fscanf在结构中设置参数。我使用Eclipse作为编辑器,并使用gcc作为编译器(来自Eclipse中)。

我在下面介绍的内容包括三个部分: 1)我正在从文件中读取变量的结构声明。 2)我正在阅读的文件和 3)实际从文件中读取的代码。

不幸的是,这是一个非常具体的问题。但我变得绝望了。

1)我正在阅读的结构声明如下:

struct StSimuParam{

    // Control parameters

    int HeatSource; // Kind of internal heat source? // 0: No internal heat source, 1: Constant internal heat source, 2: Varying internal heat source

    // Simulation parameters

    double TotTime;
    double dt;
    double CurrentTime;

    int TotIter; // Calculated as TotTime/dt
    double beta; // Weighting between forwards and backwards euler time scheme

    double TCastInit; // Initial casting temperature
    double TMouldInit; // Initial mould temperature

    // Physical parameters
    double Thickness; // Element thickness, constant for all elements
    double HeatCondNumber[3]; // Heat conduction number. Index 0: melt, index 1: solidified alloy, index 2: mould
    double Cp[3]; // Specific heat capacity. Index 0: melt, index 1: solidified alloy, index 2: mould
    double TConvec; // The temperature at infinity that controls the convection cooling
    double HeatTransfCoef; // Heat transfer coefficient.

    // Average density of element
    double *AvgRho;
    double *AvgCp;
    double *AvgHeatCondNumber;

    };

2)我正在阅读的文件是以下.txt文件

Input for thermal solver. Need descriptions of all quantities  

Thickness           0.01    Thickness of elements  

HeatCondNumLiq      100     Heat conduction number for liquid  
HeatCondNumSol      100     Heat conduction number for solid alloy  
HeatCondNumMould    10      Heat conduction number for mould  

CpLiq               500     specific heat capacity of liquid  
CpSol               500     specific heat capacity of solid alloy  
CpMould             50      specific heat capacity of mould  
TCastInit           1260    Casting initial temperature  
TMouldInit          20      Mould initial temperature  

TConvec             500     Convective cooling temperature (T_infinity)  

dt                  0.01    Time step size  
TotTime             0.04    Total time  
beta                0.5     Parameter for the time stepping proceedure (0.5 : Crank - Nicholson)  

HeatTransfCoef      50000   Heat transfer coefficient between mould and convectively cooling airInput for thermal solver. Need descriptions of all quantities

3)以下函数将文件中的值读入结构如下:

struct StSimuParam *set_simu_param(char *SimuParamFileName){

    struct StSimuParam *pStSimuParam =  malloc(sizeof(struct StBCData));

        FILE *fp;

        fp = fopen(SimuParamFileName,"r");

        if (fp == NULL){ // Check if file could be opened
                fprintf(stderr, "Can't open file %s!\n",SimuParamFileName);
                exit(EXIT_FAILURE);
        }



        char str1[50]; // string for comparison to struct element keywords
        char str2[20]; // string containing the value according to the keyword in str1

        while (fscanf(fp,"%s %s %*[^\n]",str1,str2) == 2){

            printf("str1: ");
            puts(str1);
            printf("str2: ");
            puts(str2);

            if (strcmp(str1,"Thickness") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->Thickness));
                printf("Thickness = %f\n",pStSimuParam->Thickness);
            }
            else if (strcmp(str1,"HeatCondNumLiq") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->HeatCondNumber[0]));
                printf("HeatCondNumber = %f\n",pStSimuParam->HeatCondNumber[0]);
            }
            else if (strcmp(str1,"HeatCondNumSol") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->HeatCondNumber[1]));
                printf("HeatCondNumber = %f\n",pStSimuParam->HeatCondNumber[1]);
            }

            else if (strcmp(str1,"HeatCondNumMould") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->HeatCondNumber[2]));
                printf("HeatCondNumber = %f\n",pStSimuParam->HeatCondNumber[2]);
            }

            else if (strcmp(str1,"CpLiq") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->Cp[0]));
                //printf("RhoCp = %f\n",pStSimuParam->RhoCp);
            }

            else if (strcmp(str1,"CpSol") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->Cp[1]));
                //printf("RhoCp = %f\n",pStSimuParam->RhoCp);
            }
            else if (strcmp(str1,"CpMould") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->Cp[2]));
                //printf("RhoCp = %f\n",pStSimuParam->RhoCp);
            }

            else if (strcmp(str1,"beta") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->beta));
                //printf("beta = %f\n",pStSimuParam->beta);
            }
            else if (strcmp(str1,"dt") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->dt));
                //printf("dt = %f\n",pStSimuParam->dt);
            }

            else if (strcmp(str1,"TotTime") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->TotTime));
                printf("TotTime = %f\n",pStSimuParam->TotTime);
            }

            else if (strcmp(str1,"HeatSource") == 0){
                sscanf(str2, "%d", &(pStSimuParam->HeatSource));
                //printf("HeatSource = %d\n",pStSimuParam->HeatSource);
            }

            else if (strcmp(str1,"TConvec") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->TConvec));
                printf("TConvec = %f\n",pStSimuParam->TConvec);
            }

            else if (strcmp(str1,"HeatTransfCoef") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->HeatTransfCoef));
                printf("HeatTransfCoef = %f\n",pStSimuParam->HeatTransfCoef);
            }

            else if (strcmp(str1,"TCastInit") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->TCastInit));
            }

            else if (strcmp(str1,"TMouldInit") == 0){
                sscanf(str2, "%lf", &(pStSimuParam->TMouldInit));
            }

        }
fclose(fp);

    return pStSimuParam;
}

函数调用如下:

char SimuParamFileName[50]; 

sprintf(SimuParamFileName,"SimuParam_solidification.txt");


/****** Set simulation parameters for thermal solver  **************/

struct StSimuParam *pStSimuParam;
pStSimuParam = set_simu_param(SimuParamFileName);

问题是,当fscanf读取字符串" TConvec"时,它会将读取的值放入它应该的变量中,但是然后退出while循环,即使文件的末尾没有到达。我可以在包含TConvec的输入文件中移动该行,并且while循环在到达TConvec时终止。

如果我将输入文件的TConvec部分放在文件的末尾,则调试器结束于

/* We add the additional test for EOF here since otherwise
inchar will restore the old errno value which might be
EINTR but does not indicate an interrupt since nothing
was read at this time.  */
    if (__builtin_expect ((c == EOF || inchar () == EOF)

在vfscanf中。

在评论有关TConvec的部分时,while循环以fscanf中的此行中的分段错误结束:

  

_IO_acquire_lock_clear_flags2(stream);

我无法看到

else if (strcmp(str1,"TConvec") == 0){
    sscanf(str2, "%lf", &(pStSimuParam->TConvec));
    printf("TConvec = %f\n",pStSimuParam->TConvec);
}

与其他"有很大不同,否则如果"语句,这里可能还有多个错误。对此有任何帮助或想法非常感谢!

2 个答案:

答案 0 :(得分:0)

我认为我发现这个问题是我的朋友。

看,你的功能:

char str1[50]; // string for comparison to struct element keywords

你的声明很好,但是在你的代码中我解决了问题:

while (fscanf(fp,"%s %s %*[^\n]",str1,str2) == 2){

正如我所看到的,你的str1和str2都与==2进行了比较,并且你没有使用strlen来过滤字符串中的空字符。如果你尝试过它可能会解决问题。

可能的另一点是你的%*[^\n]这种格式在你比较时可能会对str1和str2造成麻烦。

我希望对此提示有所帮助。 如果可能的话,回答我: 您使用什么操作系统和Copiler?它只是日食的GCC吗?

答案 1 :(得分:0)

正如@Strigidis在评论中指出的那样,我正在分配错误使用的结构:

struct StSimuParam *pStSimuParam = malloc(sizeof(struct StBCData));

应该是

struct StSimuParam *pStSimuParam = malloc(sizeof(struct StSimuParama));

不知怎的,这导致了fscanf期间的错误。虽然我不确定为什么会这样......