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 intemperatur
completely. You shouldn't use the firstfloat
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 todurchschnittsTemp
.
#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);
}