Home > Software design >  .exe program crashes when I try to work with a .txt file
.exe program crashes when I try to work with a .txt file

Time:06-20

I'm trying to read a .txt file. The task is to read temperatures and give out min, max and average values. The txt file is called Temp.txt and it looks like this :

5 76 56 34 35 10
4 45 23 24 14
0
2 32 34 

Here is the code that I've written. I have also tried to run it using just the file name like 'fopen("Temp.txt","r")' but I get the same result.

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

int ReadTempFile(FILE *fp, float temperatur[]);
float maxTemp(int anzahl, float temperatur[]);
float minTemp(int anzahl, float temperatur[]);
float mittlereTemp(int anzahl, float temperatur[]);
float fahrenheit(float celsius);

int ReadTempFile(FILE *fp, float temperatur[])    //For reading individual rows from txt file
{
    int i=0;
    fscanf(fp,"%f", &temperatur[0]);
    for(i = 0; i < temperatur[0];   i)
    {
        fscanf(fp, "%f", &temperatur[i 1]);
    }
    return temperatur[0];
}

float maxTemp(int anzahl, float temperatur[])    //Maximum Temperature
{
    int i = 0;
    float max;
    max = temperatur[i 1];
    for(i = 1; i < anzahl; i  )
    {
        if(temperatur[i 1] > max)
        {
            max = temperatur[i 1];
        }
    }
    return max;
}

float minTemp(int anzahl, float temperatur[])    //Minimum Temperature
{
    int i = 0;
    float min;
    min = temperatur[i 1];
    for(i = 1; i < anzahl; i  )
    {
        if(temperatur[i 1] < min)
        {
            min = temperatur[i 1];
        }
    }
    return min;
}

float mittlereTemp(int anzahl, float temperatur[])    //Average Temperature
{
    int i, sum = 0;
    float mit;
    for (i = 0; i <= anzahl; i  )
    {
        sum  = temperatur[i];
    }
    mit = sum/temperatur[0];
    return mit;
}

float fahrenheit(float celsius)    //Celsius to Fahrenheit
{
    float f;
    f = (celsius*9/5)   32;
    return f;
}


int main()
{
    int end, n, Zeile=1;
    float temperatur[20], max, min, mit, fmax, fmin, fmit;
    char eingabe[20];
    FILE *fp=NULL;
    do
    {
        printf("Enter File name: \n");    //Enter file name
        fflush(stdout);
        scanf("%s", eingabe);
        fp = fopen(eingabe, "r" );
        if(fp == NULL) printf ("Error: File %s can't be opened!\n", eingabe);    //Error message for File cant be opened
    }while(fp != NULL);

    do{
        n = ReadTempFile(fp, temperatur);

        max = maxTemp(n, temperatur);
        printf("Das Maximum der Zeile %d ist: %.3fC \t",Zeile, max);

        fmax = fahrenheit(max);
        printf("In Fahrenheit: %.3fF\n", fmax);

        min = minTemp(n, temperatur);
        printf("Das Minimum der Zeile %d ist: %.3fC \t",Zeile, min);

        fmin = fahrenheit(min);
        printf("In Fahrenheit: %.3fF\n", fmin);

        mit = mittlereTemp(n, temperatur);
        printf("Der Mittelwert der Zeile %d ist: %.3fC \t",Zeile, mit);

        fmit = fahrenheit(mit);
        printf("In Fahrenheit: %.3fF\n", fmit);

          Zeile;

        end = feof(fp);
        printf("\n\n");
    }while (end == 0);

    fclose(fp);
    return 0;
}

This is what happens after I run the above program.

Thank you in advance.

CodePudding user response:

The most immediate problem that is likely causing the crash is the logic for opening a file:

do
{
    printf("Enter File name: \n");    //Enter file name
    fflush(stdout);
    scanf("%s", eingabe);
    fp = fopen(eingabe, "r" );
    if(fp == NULL) printf ("Error: File %s can't be opened!\n", eingabe);
}while(fp != NULL);   // <- Loops until it fails

This will guarantee that the loop will not end until a file fails to open. When you later try to fscanf from fp set to NULL, you'll have undefined behavior (and this may manifest itself as a crash).

Suggested fix:

for(;;) {
    puts("Enter File name:");
    if(scanf("s", eingabe) == 1) { // make sure scanf succeeds
        fp = fopen(eingabe, "r" );
        if(fp) break;                 // break out when it succeeds to open
        perror(eingabe);
    } else {
        fprintf(stderr, "Error: No filename entered.\n");
        return 1;
    }
}

Note: In your example-run, you showed that you entered Temp to open Temp.txt. You must enter Temp.txt to successfully open Temp.txt.


Here is your program with some other fixes too. I've commented inline so you see why I suggest the changes.

Notes:

  • I've removed the 1 offset in temperatur completely. You shouldn't use the first float to store the count of temperatures which is an integer value.
  • Your mittlereTemp didn't use this offset, so it gave the wrong answers too.
  • mittlereTemp didn't calculate the median temperature (which I think "mittlereTemp" means). It tried to calculate the average temperature, so I changed the name to durchschnittsTemp.
#include <math.h>
#include <stdio.h>
#include <string.h>

// For reading individual rows from txt file
// max_anzahl added to not try to read too many
int ReadTempFile(FILE* fp, float temperatur[], int max_anzahl) {
    int count;
    // return -1 on failure
    if(fscanf(fp, "%d", &count) != 1) return -1;

    // we can't read all the entries if count > max_anzahl
    if(count > max_anzahl || count < 0) return -1;

    for(int i = 0; i < count;   i) {
        if(fscanf(fp, "%f", &temperatur[i]) != 1) {
            return -1; // could not read count floats, failure
        }
    }

    return count;
}

// The idiomatic way is to have the array pointer first and
// the count second so I swapped the order of temperatur and anzahl:
float maxTemp(float temperatur[], int anzahl) {
    if(anzahl == 0) return NAN; // if we have no values, we have no max temp

    float max = temperatur[0];

    for(int i = 1; i < anzahl; i  ) {
        if(temperatur[i] > max) {
            max = temperatur[i];
        }
    }
    return max;
}

float minTemp(float temperatur[], int anzahl) {
    if(anzahl == 0) return NAN; // if we have no values, we have no min temp

    float min = temperatur[0];

    for(int i = 1; i < anzahl; i  ) {
        if(temperatur[i] < min) {
            min = temperatur[i];
        }
    }
    return min;
}

// I changed the name to durchschnittsTemp
float durchschnittsTemp(float temperatur[], int anzahl) {
    if(anzahl == 0) return NAN; // if we have no values, we have no average temp

    float sum = 0.f;            // use the proper type for sum

    for(int i = 0; i < anzahl; i  ) {
        sum  = temperatur[i];
    }
    return sum / (float)anzahl;
}

float fahrenheit(float celsius) {
    float f;
    f = (celsius * 9 / 5)   32;
    return f;
}

// since opening the file is a lot of code, make a function
FILE* open_file_supplied_by_the_user() {
    char eingabe[FILENAME_MAX]; // make plenty of room for the filename
    for(;;) {
        puts("Enter File name:");
        // use fgets instead of scanf to make it easier to read filenames with spaces
        if(fgets(eingabe, sizeof eingabe, stdin)) {
            size_t len = strlen(eingabe);
            eingabe[len - 1] = '\0';
            FILE* fp = fopen(eingabe, "r");
            if(fp) return fp; // break out when it succeeds to open
            perror(eingabe);  // give the user a proper error message
        } else {
            fprintf(stderr, "Error: No filename entered.\n");
            return NULL;
        }
    }
}

#define Size(x) (sizeof(x) / sizeof *(x))

int main() {
    FILE* fp = open_file_supplied_by_the_user();
    if(fp == NULL) return 1; // exit if no file was opened

    float temperatur[20];

    // loop until ReadTempFile() returns -1 (failure)
    for(int n, Zeile = 1;
        (n = ReadTempFile(fp, temperatur, Size(temperatur))) != -1;
          Zeile)
    {
        float max = maxTemp(temperatur, n);
        printf("Das Maximum der Zeile %d ist: %.3fC \t", Zeile, max);
        printf("In Fahrenheit: %.3fF\n", fahrenheit(max));

        float min = minTemp(temperatur, n);
        printf("Das Minimum der Zeile %d ist: %.3fC \t", Zeile, min);
        printf("In Fahrenheit: %.3fF\n", fahrenheit(min));

        float mit = durchschnittsTemp(temperatur, n);
        printf("Der Durchschnittswert der Zeile %d ist: %.3fC \t", Zeile, mit);
        printf("In Fahrenheit: %.3fF\n", fahrenheit(mit));

        printf("\n\n");
    }

    fclose(fp);
}
  •  Tags:  
  • c
  • Related