Ignoring # comments in the input for a C program - c

I'm trying to write a program which will read from text files and then output the minimum, maximum and average values. The trouble I am having is ignoring comments in the text files that begin with a hashtag. Here is my working code so far. Can anyone help?
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char ch, filename[20];
FILE *lun;
int num, min, max, sum, count, first;
printf("Please enter the name of file to load:");
scanf ("%s", filename);
lun=fopen(filename, "r");
if ( lun != NULL)
{
for ( sum= count= first= 0; fscanf( lun, "%d", &num ) == 1; sum += num, ++count )
if ( !first ) { min= max= num; first= 1; }
else if ( num > max ) max= num;
else if ( num < min ) min= num;
fclose( lun );
printf( " Minimum value: %d\n Maximum value: %d\n Average value: %lf\n",
min, max, sum / (double) count );
}
else
printf( "Unable to read file.\n" );
return 0;
}

Read the data in lines (use fgets()).
If the line contains a #, terminate the string there by replacing the '#' with '\0'. Then scan the line for numbers.
See also How to use sscanf() in loops?
And don't forget to check that the file was opened.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char filename[20];
printf("Please enter the name of file to load: ");
if (scanf("%19s", filename) != 1)
{
fprintf(stderr, "Failed to read file name\n");
return 1;
}
FILE *lun = fopen(filename, "r");
if (lun == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return 1;
}
char line[4096];
int min = 0; // Avoid compilation warnings (may be used uninitialized)
int max = 0; // Ditto
int sum = 0;
int count = 0;
while (fgets(line, sizeof(line), lun) != NULL)
{
char *hash = strchr(line, '#');
if (hash != NULL)
*hash = '\0';
int pos;
int num;
int off = 0;
while (sscanf(line + off, "%d%n", &num, &pos) == 1)
{
if (count == 0)
min = max = num;
if (num > max)
max = num;
if (num < min)
min = num;
sum += num;
count++;
off += pos; // Skip through line
}
}
fclose(lun);
printf("Minimum value: %d\nMaximum value: %d\nAverage value: %lf\n",
min, max, sum / (double)count);
return 0;
}
If your compiler doesn't support C99 or later, you will have to move variable declarations to the start of a block (immediately after a {).
Handling doubles isn't really any harder:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char filename[20];
printf("Please enter the name of file to load: ");
if (scanf("%19s", filename) != 1)
{
fprintf(stderr, "Failed to read file name\n");
return 1;
}
FILE *lun = fopen(filename, "r");
if (lun == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return 1;
}
char line[4096];
double min = 0.0; // Avoids 'used when uninitialized' warnings
double max = 0.0; // Avoids 'used when uninitialized' warnings
double sum = 0;
int count = 0;
while (fgets(line, sizeof(line), lun) != NULL)
{
char *hash = strchr(line, '#');
if (hash != NULL)
*hash = '\0';
int pos;
double num;
int off = 0;
while (sscanf(line + off, "%lf%n", &num, &pos) == 1)
{
if (count == 0)
min = max = num;
if (num > max)
max = num;
if (num < min)
min = num;
sum += num;
count++;
off += pos; // Skip through line
}
}
fclose(lun);
printf("Minimum value: %f\nMaximum value: %f\nAverage value: %f\n",
min, max, sum / count);
return 0;
}

Related

.exe program crashes when I try to work with a .txt file

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.
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("%19s", 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);
}

Storing numbers as (x, y) cordinates from a file at a specific point

I have an Instance File from which I need to store the NUM_PT and all the respective co-ordinates in the form of a 2D array system (personal choice so I can access them easily). I am able to retrieve the NUM_PT but I am stuck at reading the successive cordinates into my array.
HERE IS WHAT I HAVE DONE
/* Assignment 2 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define MAXS 256
int main(int argc, char *argv[])
{
int num_pt;
int inputfile = 0, outputfile = 0, i;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-i") == 0)
inputfile = i+1;
if (strcmp (argv[i], "-o") == 0)
outputfile = i+1;
}
if (inputfile == 0)
{
/* invalid command line options */
printf("\nIncorrect command-line...\n");
printf("> %s [-i inputfile [-o outputfile]]\n\n", argv[0]);
exit(0);
}
FILE *fp;
fp = fopen(argv[inputfile], "r");
int count = 0;
if (fp == 0)
{
printf("\nCould not find %s\n", argv[inputfile]);
exit(0);
}
char line[MAXS];
while (fgets(line, sizeof line, fp) != NULL)
{
if (count == 4)
{
fscanf(fp, "%d", &num_pt);
break;
}
else
count++;
}
int arr[num_pt][1];
while (fgets(line, sizeof line, fp) != NULL)
{
if (count == 5)
{
int k, j, cord;
for (k = 0; k < num_pt; k++)
{
for (j = 0; j < num_pt; j++)
{
while (fscanf(fp, "%d%d", &cord) > 0)
{
arr[k][j] = cord;
j++;
}
}
}
}
}
fclose(fp)
return 0;
}
After retrieving NUM_PT i tried reinitializing the count to 5 because the cordinates start from **LINE 6* in the file.
ERROR FROM COMPILER
Language: c99 ; Compiler: gcc
sample for "Storing numbers as (x, y) cordinates from a file" (It is better not to fix the reading position)
#include <stdio.h>
typedef struct point {
int x, y;
} Point;
int readPoint(FILE *fp, Point *p);
int readInt(FILE *fp, int *n);
int main(void){
FILE *fp = fopen("instance10_001.txt", "r");
Point p;
int MAX_X, MAX_Y;
readPoint(fp, &p);
MAX_X = p.x;
MAX_Y = p.y;
printf("MAX_X:%d, MAX_Y:%d\n", MAX_X, MAX_Y);
int NUM_PT;
readInt(fp, &NUM_PT);
printf("NUM_PT:%d\n", NUM_PT);
Point arr[NUM_PT];
for(int i = 0; i < NUM_PT; ++i){
readPoint(fp, &arr[i]);
printf("Point(%d, %d)\n", arr[i].x, arr[i].y);
}
fclose(fp);
}
int readLine(FILE *fp, char *buff, int buff_size){
while(fgets(buff, buff_size, fp)){
if(*buff == '#' || *buff == '\n')
continue;
return 1;
}
return 0;
}
#define LINE_MAX 128
int readPoint(FILE *fp, Point *p){
char buff[LINE_MAX];
if(readLine(fp, buff, sizeof buff)){
return 2 == sscanf(buff, "%d %d", &p->x, &p->y);
}
return 0;
}
int readInt(FILE *fp, int *n){
char buff[LINE_MAX];
if(readLine(fp, buff, sizeof buff)){
return 1 == sscanf(buff, "%d", n);
}
return 0;
}

C fork and pipe add numbers from a file

Totals different for same file when executed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_FILE_NAME 100
#define RUNS 1
int main() {
int num,i;
FILE *fp;
char*s, buf[1024];
int count =0;
char c;
char filename[MAX_FILE_NAME];
printf("Enter filename: ");
scanf ("%s",filename);
if ((fp =fopen(filename, "r")) == NULL) {
printf("Error");
exit(1);
}
fscanf(fp,"%d",&num);
for (c = getc(fp); c!= EOF; c = getc(fp))
{
if (c == '\n'){
count = count+1;
}
}
printf("%s has %d numbers \n", filename, count);
int f;
printf("Choose from the options how many processes you want to use [1,2,4]: ");
scanf("%i", &f);
printf("%i processes \n", f);
int fds[f+1][2];
int numb[count];
int x,k;
time_t start, finish;
start = time(NULL);
for(i = 0; i < RUNS; i++)
{
pipe(fds[f]);
for( x = 0; x<f; x++)
{
pipe(fds[x]);
int ind[2];
ind[0] = ((x)*(count/f));
ind[1] = ((x+1)*(count/f));
write(fds[x][1], &ind, 2* sizeof(int));
if (fork() ==0)
{
int t =0;
int ind2[2];
read(fds[x][0], &ind2, 2*sizeof(int));
for( k = ind2[0]; k<ind2[1]; k++)
{
t += numb[k];
}
write(fds[f][1], &t, sizeof(int));
exit(0);
}
}
int m, tmp, total;
total = 0;
for( m = 0; m < f; m++)
{
for( m = 0; m < f; m++)
{
read(fds[f][0], &tmp, sizeof(int));
sleep(5);
total += tmp;
}
printf("DOne calc \n");
printf("Total: %i \n", total);
}
finish = time(NULL);
float runtime = (float)((finish-start)/RUNS);
printf("runtime: %f \n", runtime);
fclose(fp);
return 0;
}
You get random result for the same input because the calculation based on uninitialized int numb[count]; values.
According to the C99 standard, section 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
Because of it int numb[count]; contains some random junk from memory. To get predictive results use explicit initialization:
#include <string.h> // memset
int numb[count];
memset (numb, 0, sizeof(numb)); // Zero-fills
Use the code bellow to put numbers from filename file into numb:
int i = 0;
char line[1024];
fseek(fp, 0, SEEK_SET);
while(fgets(line, sizeof(line), fp) )
{
if( sscanf(line, "%d", &numb[i]) == 1 ) // One number per line
{
++i;
}
}

Read .CSV file and store it in another file

Have made a program that reads a .csv file and stores the highest number in another file. The problem is that my program can't read comma separated numbers like 1,5,6,7,1,2. Here is the loop I need help to change
int i;
int max = 0;
int min = 0;
while (!feof(fp))
{
fscanf( fp, "%d", &i);
if (i < min)
min = i;
if (i > max)
max = i;
}
And this is what I print out:
fprintf(q,"%d",max);
printf("maximum value is %d \n", max);
fclose(q);
fclose(fp);
#include <stdio.h>
#include <limits.h>
int main(void){
FILE *fp = fopen("input.csv", "r");
FILE *q = fopen("max.txt" , "w");
int i;
int max = INT_MIN;
int min = INT_MAX;
while(1){
int state = fscanf(fp, "%d", &i);
if(state == 1){
if (i < min)
min = i;
if (i > max)
max = i;
} else if(state == EOF){
break;
} else {
char ch;
fscanf(fp, " %c", &ch);
if(ch != ','){
fprintf(stderr, "\nformat error\n");
break;
}
}
}
fprintf(q, "%d", max);
printf("maximum value is %d\n", max);
fclose(q);
fclose(fp);
return 0;
}

runtime error when trying to read data from file

I have a question on logical error, the error was
"Run-Time Check Failure #2 - Stack around the variable 'list' was corrupted."
there are a total of 60 lines in the in.txt file
this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILE_NAME 20
#define LIST_SIZE 50
//void getData(RECORD name[], RECORD score)
typedef struct
{
char *name;
int score;
}RECORD;
int main (void)
{
// Declarations
FILE *fp;
char fileName[FILE_NAME];
RECORD list[LIST_SIZE];
char buffer[100];
int count = 0;
int i;
// Statements
printf("Enter the file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if(fp == NULL)
printf("Error cannot open the file!\n");
while(fgets(buffer, 100, fp) != NULL)
{
list[count].name = (char*) calloc(strlen(buffer), sizeof(RECORD*));
if(count > 50)
{
}
if( count < 50)
{
sscanf(buffer,"%[^,], %d", list[count].name, &list[count].score);
for( i =1; i < (50 - count); i++)
{
list[count + i].name = 0;
list[count + i].score = 0;
}
}
count++;
}
printf("Read in %d data records\n", count);
fclose(fp);
return 0;
}
in this program I' m trying to read data from file to array of structures, so if the number of data is less than 50, structures that don't have data will be zero out and if the number of data is more than 50 the program will only read the first 50 structures.
how can i fix the runtime error?
Perhaps...
while(fgets(buffer, 100, fp) != NULL)
{
if( count >= 50)
{
break;
}
if( count < 50)
{
list[count].name = (char*) malloc(strlen(buffer)*sizeof(char));
sscanf(buffer,"%[^,], %d", list[count].name, &list[count].score);
count++;
}
}
for( i =0; i < (50 - count); i++)
{
list[count + i].name = 0;
list[count + i].score = 0;
}
What if count = 50?
Try with the following in your while loop bringing if block in the start or at the end;
if(count >= 50) //count should be checked for >= 50 before being used.
{
}
list[count].name = (char*) calloc(strlen(buffer), sizeof(RECORD*)); //list size is 50 so list[50] won't work. out of bound.

Resources