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
1offset intemperaturcompletely. You shouldn't use the firstfloatto store the count of temperatures which is an integer value. - Your
mittlereTempdidn't use this offset, so it gave the wrong answers too. mittlereTempdidn'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);
}
