views:

192

answers:

2

I am writing a program to read info from a text file and I had everything working. The problem is that I am trying to add the functionality to calculate the mean of some of fields and have to convert the strings to doubles. I noticed that atof would work in some cases but would return -1 for the most part. i then realized that I didn't include stdlib, so I added that, but now I am getting a segmentation fault with just that one change.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

main(int argc, char *argv[]){

    int numParts=10;
    long numTests=49000;

    char filename[] = "sweep_data.txt";
    FILE *fp= fopen(filename,"r");
    FILE *out= fopen("TesterData.csv", "w+");
    FILE *meanf= fopen("meanData.txt", "w+");

    char delims[] = " <>";
    char *result = NULL;
    char line [128];

    char *TestNum=NULL;
    char *TestName=NULL;
    char *TestName2=NULL;
    char *SequencerName=NULL;
    char *lowlim=NULL;
    char *hilim=NULL;
    char *value=NULL;
    char *units=NULL;
    char *DeviceNum=NULL;

    char ValueArray[numTests][10];
    char ***ValuePtr = NULL;
    char InfoArray[numTests][20];
    char ***InfoPtr = NULL;

    double mean[numTests];
    long sum;
    int intResult;
    int count=0;
    int DeviceCount=-1;
    int i,j, m,n,k,a,b, len, mLen;

    /*Allocate Memory for 2D arrays*/
    ValuePtr = malloc(numParts * sizeof *ValuePtr);

    for(i=0; i<numParts;i++){
        ValuePtr[i]=malloc(numTests*sizeof *ValuePtr);


        for(j=0; j<numTests; j++){
            ValuePtr[i][j] = malloc(strlen(ValueArray[j]) +1);
        }
    }

    InfoPtr = malloc(6 * sizeof *InfoPtr);

    if(InfoPtr != NULL){
        for(a=0; a<6;a++){
            InfoPtr[a]=malloc(numTests*sizeof *InfoPtr);

            for(b=0; b<numTests; b++){
                InfoPtr[a][b]= malloc(strlen(InfoArray[b]) +1);
            }
        }
    }

    while(fgets(line, sizeof line, fp) != NULL){
        result = strtok(line, delims);
        TestNum=result;

        intResult = strtol(result, NULL, 10);
        if(intResult ==0){
            if(strcmp(result, "Device:")==0){
                DeviceCount++;
                count=0;
            }
            continue; //if doesn't start with a number go to next line
        }

        result = strtok(NULL, delims);
        TestName= result;
        result = strtok(NULL, delims);
        TestName2= result;
        result = strtok(NULL, delims);
        SequencerName = result;
        lowlim=SequencerName;

        if(atof(SequencerName)>1 || atof(SequencerName)<-1){
            result= strtok(NULL, delims);     
            lowlim=result;
            strcat(TestName, TestName2);
        }
        else
            SequencerName= TestName2;     


        if(strstr(TestName, "%")!=NULL || strcmp(TestName,"PTgen")==0 || strcmp(TestName,"mode")==0){
            units="NA";
        }

        else if(strstr(TestName, "2nd") == NULL && strstr(TestName, "3rd") == NULL){
            result= strtok(NULL, delims);
            units = result;
        }

        result= strtok(NULL, delims);
        value=result;

        if(strstr(TestName, "%")==NULL &&  strcmp(TestName,"PTgen")!=0 && strcmp(TestName,"mode")!=0){
            result=strtok(NULL, delims);
            if(strstr(TestName, "2nd") != NULL || strstr(TestName, "3rd") != NULL)
                units = result;
        }

        result=strtok(NULL, delims);
        hilim=result;
        if(hilim[strlen(hilim)-1]=='\n'){
            hilim[strlen(hilim)-1]='\0';
            hilim[strlen(hilim)-1]='\0';
        }

        if(DeviceCount==0){
            strcpy(InfoPtr[0][count], TestNum);
            strcpy(InfoPtr[1][count], TestName);
            strcpy(InfoPtr[2][count], SequencerName);
            strcpy(InfoPtr[3][count], lowlim);
            strcpy(InfoPtr[4][count], hilim);
            strcpy(InfoPtr[5][count], units);
        }

        strcpy(ValuePtr[DeviceCount][count],value);

        count++;
    }

    for(b=0;b<numTests;b++){
        sum=0;
        for(a=0;a<numParts;a++){
            fprintf(meanf, "%s\n", ValuePtr[a][b]);
            sum=atof(ValuePtr[a][b]);
            fprintf(meanf, "%f\n",sum);
        }
        mean[b]=sum/numParts;
        for(n=0; n<2;n++){
            fprintf(meanf, "%s ", InfoPtr[n][b]);
        }
        fprintf(meanf, "%f\n",mean[b]);
    }
    printf("NumTests: %i\n",count); //number of tests run
    printf("NumParts: %i\n", DeviceCount+1);//number of parts run
    fprintf(out,"Test#, TestName,SeqName,LowLim,UpLim,Units,");

    for(j=1; j<=numParts;j++){
        fprintf(out," Device#%i,", j);
    }
    fprintf(out, "\n");

    for (n = 0; n < numTests; n++) {
        for(a=0;a<6;a++){
            fprintf(out, "%s", InfoPtr[a][n]);

            fprintf(out, ", ");
        }

        for (m =0; m < numParts ; m++) {
            fprintf(out, "%s, ", ValuePtr[m][n]);
        }
        fprintf(out, "\n");
    }
}

The part where I was needing to convert to a double is

for(b=0;b<numTests;b++){
    sum=0;
    for(a=0;a<numParts;a++){
        fprintf(meanf, "%s\n", ValuePtr[a][b]);
        sum+=atof(ValuePtr[a][b]);
        fprintf(meanf, "%f\n",sum);
    }
    mean[b]=sum/numTests;
    for(n=0; n<2;n++){
        fprintf(meanf, "%s ", InfoPtr[n][b]);
    }
    fprintf(meanf, "%f\n",mean[b]);
}
+1  A: 

The following line doesn't seem correct. It is using strlen on something that has not been initialized. So the results would be nondeterministic:

ValuePtr[i][j] = malloc(strlen(ValueArray[j]) +1);

The use of that later in the calls to atof() would quite possibly not produce consistent results. And depending on the actual allocation size, it could result in a seg fault when storing data in it.

Mark Wilkins
A: 

Not that this has anything to do with the segfault, but:

ValuePtr = malloc(numParts * sizeof **ValuePtr);

  ...

InfoPtr = malloc(6 * sizeof **InfoPtr);
Ignacio Vazquez-Abrams