Consider the file,
L,12/5/2008,Blacktown
C,Willy Wonker,10.00
C,Adolph Hitler,20.00
C,Attila the Hun,30.00
C,Idi Amin,40.00
C,Ghengis Khan,50.00
T,150.00
L,13/5/2008,Parramatta
C,Attila the Hun,100.10
C,Willy Wonker,200.20
C,Ghengis Khan,300.30
T,600.60
L,14/5/2008,Mount Druitt
C,Adolph Hitler,1000.00
T,2000.00
L,15/5/2008,Penrith
T,0.00
L,16/5/2008,Chatswood
C,Ghengis Khan,1.00
C,Idi Amin,10.00
C,Adolph Hitler,100.00
C,Attila the Hun,1000.00
T,1111.00
I need to write a program that opens the file Collections.txt, reads it and formats it in the given order, and writes it to another file called Reports.txt. I need to have the date, a tab, and then the name. Then a new line and the names, a tab, and the amount. Repeat until a T is detected; this signals we have no more collections for the above location. Then rinse and repeat for every location until it reaches the end of the file and a final total must be displayed.
Here is the code I have written,
/*
This program collects data and writes it to a specific file.*/
#include <stdio.h>
#include <stdlib.h>
void debt_calculator();
void main()
{
printf("This is a debt collection program:\n ");
debt_calculator();
scanf("%*c");
}
void debt_calculator()
{
char code;
int date [40];
char location [40];
char name [40];
float amount = 0;
float total = 0;
float grand_total;
int ctr = 0;
FILE * Collections;
Collections=fopen("C:\\Users\\Nick\\Documents\\Visual Studio 2010\\Projects\\Assignment2\\Assignment2\\Collections.txt","r");
if(Collections==NULL)
{
printf("file not open:\n");
exit(1);
}
FILE * Report;
if((Report=fopen("C:\\Users\\Nick\\Documents\\Visual Studio 2010\\Projects\\Assignment2\\Assignment2\\Report.txt","w"))==NULL)
{
printf("can not open file: \n");
exit(1);
}
fscanf(Collections,"%c,",&code);
while(code == 'L')
{
fscanf(Collections,"%[^,],%s%*c",date,location);
fprintf(Report,"Date: %s \t Location: %s \n\n",date, location);
fscanf(Collections,"%c,",&code);
}
for(code == 'C'; ctr < 5; ctr++)
{
fscanf(Collections,"%[^,], %f %*c",name, & amount);
if(amount == 0)
{
fprintf(Report,"### No Collections for %s \n", location);
fprintf(Report,"total: \t 0.00\n");
}
fprintf(Report,"\n Name: %s \t Amount: %.2f \n",name, amount);
fscanf(Collections,"%c,",&code);
}
code == 'T';
while(code == 'T')
{
fprintf(Report,"Hello");
fscanf(Collections,"%f",& amount);
total += amount;
grand_total += total;
fprintf(Report,"Total: \t %.2f \n",& total);
fprintf(Report,"Grand Total of all Collections is: $ %.2f", grand_total);
fscanf(Collections,"%c" , & code);
}
fclose(Collections);
fclose(Report);
}
When I run the above program it displays the printf() statement and when I hit enter and it exits. Than I open my report.txt file and find the date tab location new line and all the names and costs up until the T. Once it gets to the 'T' it stops, I cant get it to go into the last while loop, read the total and print it to the file than repeat by checking the code again. The code after the T is a L so it should go back into the first while loop and read than write the date and location but it does not. Any ideas what I'm doing wrong?
Also if there's any better way you think I should be doing this please let me know.
Have you tries stepping in the debugger and observing the variable state while doing so?
This line:
fprintf(Report,"Total: \t %.2f \n",& total);
is certainly incorrect, %f does not expect a pointer.
If the expectation is that code == 'T'; will force it to enter the loop, you are mistaken, code = 'T'; would work.
Similarly in this loop:
for(code == 'C'; ctr < 5; ctr++)
The initialising expression shpuld be code = 'C'
Try setting your compiler warning level to \W4 and \Wx (all warnings are errors), then the compiler may help you spot such errors.
Related
I'm using Dev-C++ (we're required to use either Turbo-C++ or Dev-C++). I'm supposed to delete one student (DATA 2) from a student record. Here is the data that we were given:
DATA 1:
2021-10-693
Clarisse
BSCS 1
1.00, 1.00, 1.00, 1.25, 1.25
DATA 2:
2021-10-705
Kricel
BSCS 1
1.00, 1.25, 1.00, 1.00, 1.25
DATA 3:
2021-01-256
Rafael
BSCS 1
1.00, 1.00, 1.00, 1.00, 1.25
We were given a student.dat file created using Turbo-C++ but I can't open it in Dev-C++ so I created my own student.dat by copy-pasting my teacher's code from Turbo-C++ to Dev-C++. The only thing I changed in this code is removing clrscr(); and replacing it with system("cls");:
/* This program will allow saving of records in the disk */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
typedef struct{
char No[12];
char Name[25];
char Crsyr[10];
float Grade[5];
}Student_Record;
int main()
{
FILE *STUDFILE; /* defining FILE variable */
Student_Record STUDENT[50],TEMPREC;
int i,j,ns;
float TGrade;
char Temp,FName[15];
do{
system("cls");
printf("How many student records (max. of 50) ? ");
scanf("%d",&ns);
if ((ns<1)||(ns>50))
{
printf("\nInvalid Input!!!");
printf("\n\nPress Any Key To Continue...");
getch();
}
}while((ns<1)||(ns>50));
scanf("%c",&Temp);
for(i=0;i<ns;i++)
{
system("cls");
printf("<## STUDENT's INFORMATION ##>\n\n");
printf("Student No. : ");
gets(STUDENT[i].No);
printf("Student Name : ");
gets(STUDENT[i].Name);
printf("Course and Year: ");
gets(STUDENT[i].Crsyr);
printf("List of grades:\n");
for(j=0;j<5;j++)
{
printf("\tGrade No. %d => ",j+1);
scanf("%f",&TGrade);
STUDENT[i].Grade[j]=TGrade;
}
printf("\nPress any key to continue...");
getch();
scanf("%c",&Temp);
}
printf("\n\nEnter Filename where records will be saved => ");
gets(FName);
printf("\n\nSaving of Records being process...");
STUDFILE=fopen(FName,"w"); /* fopen-file opening; "w" - generate new file or overwrite existing file */
for(i=0;i<ns;i++)
{
TEMPREC=STUDENT[i];
fwrite(&TEMPREC,sizeof(TEMPREC),1,STUDFILE); /* fwrite - save records in the disk */
}
fclose(STUDFILE); /* fclose - file closing */
printf("Saving of Records Completed!!!\n\n");
printf("Press Any Key To Exit...");
getch();
return (0);
}
Here is the student.dat file:
2021-10-693 Clarisse þÿÿÿÿÿÿÿþÿÿÿÿBSCS 1 €? €? €? ? ?2021-10-705 Kricel Po `Of°û BSCS 1 €? ? €? €? ?2021-10-256 Rafael °û ˜im°û ˜im°ûBSCS 1 €? €? €? €? ?
My plan is to:
Open student.dat for reading
Open temp.dat for writing
Read content of student.dat
Compare studNo to data in student.dat
If studNo is not equal to student no. of Kricel, write it in temp.dat
If studNo is equal to student no. of Kricel, don't write in temp.dat
Close both files
Open temp.dat for reading
Open student.dat for writing
Overwrite student.dat with content from temp.dat
Close both files
Open student.dat for reading
Display student.dat
And here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef struct
{
char no[12];
char name[25];
char crsYr[10];
float grade[5];
} studentRecord;
int main()
{
FILE *studFile, *tempFile;
studentRecord student[50], tempStudRec, tempFileRec;
int i = 0, j = 0, k = 0, found = 0;
float tGrade = 0.00;
char temp, fName[15], studNo[12], resp1, resp2;
system("cls");
printf("Enter file name of the record you want to alter: ");
gets(fName);
printf("Enter student no. of student you want to delete: ");
gets(studNo);
printf("Are you sure you want to remove this student (Y/N)? ");
scanf("%c", &resp1);
if (toupper(resp1) == 'Y')
{
printf("\nRetrieving records from %s...", fName);
//Sleep(2000);
printf("\nDeleting student %s from %s...", studNo, fName);
//Sleep(2000);
// Opens both files
studFile = fopen(fName, "r");
if (studFile == NULL)
{
printf("File opening is unsuccessful.");
return 1;
}
tempFile = fopen("temp.dat", "w");
// Reads student.dat
k = 0;
fread(&tempStudRec, sizeof(studentRecord), 1, studFile);
while(!feof(studFile))
{
student[k] = tempStudRec;
fread(&tempStudRec, sizeof(studentRecord), 1, studFile);
k++;
}
// Compare studNo to data in student.dat
for (i = 0; i < k; i++)
{
// If content is not equal to student no. of Kricel
if (strcmp(studNo, student->no) != 0)
{
// Write in temp.dat
tempFileRec = student[i];
fwrite(&tempFileRec, sizeof(studentRecord), 1, tempFile);
}
}
// Closes both files
fclose(studFile);
fclose(tempFile);
// Opens both files again
tempFile = fopen("temp.dat", "r");
if (tempFile == NULL)
{
printf("File opening is unsuccessful.");
return 1;
}
studFile = fopen(fName, "w");
// Reads temp.dat
k = 0;
fread(&tempFileRec, sizeof(studentRecord), 1, tempFile);
while(!feof(studFile))
{
student[k] = tempFileRec;
fread(&tempFileRec, sizeof(studentRecord), 1, tempFile);
k++;
}
// Copies temp.dat content to student.dat
for (i = 0; i < k; i++)
{
// Write in student.dat
tempStudRec = student[i];
fwrite(&tempStudRec, sizeof(studentRecord), 1, studFile);
}
// Closes both files
fclose(studFile);
fclose(tempFile);
// Opens student.dat for reading
studFile = fopen(fName, "r");
// Displaying records
printf("Student deleted!");
printf("\nDo you want to view record (Y/N)? ");
scanf("%c", &resp2);
if (toupper(resp2) == 'Y')
{
for(i = 0; i < k; i++)
{
system("cls");
printf("<## STUDENT INFORMATION ##>\n\n");
printf("Student No. : %s\n", student[i].no);
printf("Student Name : %s\n", student[i].name);
printf("Course and Year: %s\n", student[i].crsYr);
printf("List of Grades:\n");
for(j = 0; j < 5; j++)
{
printf("\tGrade No. %d => %0.2f\n", j + 1, student[i].grade[j]);
}
printf("\nPress any key to continue...");
}
}
// Closes student.dat
fclose(studFile);
}
return 0;
}
This is what the output looks like:
Enter file name of the record you want to alter: student.dat
Enter student no. of student you want to delete: 2021-10-705
Are you sure you want to remove this student (Y/N)? Y
Retrieving records from student.dat...
Deleting student 2021-10-705 from student.dat...
--------------------------------
Process exited after 16.78 seconds with return value 3221225477
Press any key to continue . . .
I checked student.dat after running the code and it's empty. Meanwhile, temp.dat contains all the contents of student.dat I showed above, including the student I'm supposed to delete. Can anyone give me an idea why is student.dat empty after running this program? And why wasn't student 2021-10-705 deleted? I'm having a hard time understanding online tutorials since we kinda just skimmed over pointers and we haven't discussed malloc(), etc. yet.
Rather than analyzing your two programs for you, I'll try to suggest how you can figure out what's going on.
Check library function call return values
Library function calls don't always succeed! When you try to open a new file - the directory might not be writeable; when you write data to disk - the disk may be full; etc. I'm not saying this is what happens in your case, but you should rarely, or perhaps never, assume a library function succeeds, if its return value can indicate an error.
Always check that return value; and if it doesn't indicate success, print a message describing the failure. See, for example, answers to this question:
Error handling in C code
on how that looks.
Use a debugger
It is often not sufficient to just scrutinize the code, or deduce from the output what actually happens when the program runs. You can, and probably should, actively debug a misbehaving program by tracking its execution with a debugger program.
Here are two Stackoverflow questions about debugging on Linux and on Windows:
How to debug a C program
How do you debug a C program on Windows?
(other platforms also have debugging tools available.)
Consider flushing the standard output stream
When your program does not seem to run to conclusion, you could insert fflush() calls at relevant 'suspicious' points in your code to ensure that whatever you printed up to that point does actually become visible on the output, rather than waiting in the output stream's buffers.
Note that, other than for debugging purposes, we generally want to avoid flushing.
I am making a program that saves information about vehicles in an array made of structs and then prints it to a file. Included in the program are options to add and delete vehicles as well as printing out the saved vehicles and deleting vehicles. When choosing a vehicle to delete or print out I have to make sure the input from the user is an integer to prevent it from crashing, and if it is not an integer to give a custom error message and give the user another chance at the input. I have tried a couple of different approaches and the latest seemed promising but when running these functions I get "Segmentation fault: 11" regardless of if I input an integer or a character.
The functions seem to work just fine without the lines of code that are supposed to prevent crashing. Could someone please tell me what is causing the error or possible fixes to the problem. Thanks!
These are the functions that are causing the problem:
Function to remove vehicle:
This function takes in the array of structs as well as the int counter which counts the number of occupied spots in the array. The function then takes input from the user in the form of an int to choose which position to delete. The position can't be greater than counter or smaller than 0.
//Ta bort ett fordon
void del(int counter, fordon_t reg[])
{
int pos;
int i;
do{
printf("Vilken position ska tas bort?:");
char *tmp;
scanf("%s", tmp);
pos = atoi(tmp);
if (pos == 0)
{
printf("Var god och skriv en siffra\n");
}
}
while(pos == 0);
if(pos<0 || pos>=counter)
{
printf("Ogiltig position\n");
}
else
{
for(i=pos+1; i<counter; i++)
{
reg[i-1]=reg[i];
}
counter--;
for(i=0; i<counter; i++)
{
printf("%s %d %s %s %s\n", reg[i].owner.name, reg[i].owner.age, reg[i].type, reg[i].brand, reg[i].regnum);
}
}
}
Function to print out chosen vehicle:
This function works in the same way as the previous function but instead of deleting the chosen position it prints out the information on that position.
//Skriv ut specifikt fordon
void print_out(int counter, fordon_t reg[])
{
int val;
do
{
char *tmp;
printf("Vilken postition vill du se?:");
scanf("%s", tmp);
val = atoi(tmp);
if (val == 0)
{
printf("Var god och skriv en siffra\n");
}
}
while(val == 0);
if(val<0 || val>=counter)
{
printf("Ogiltig position\n");
}
else
{
printf("%s %d %s %s %s\n", reg[val].owner.name, reg[val].owner.age, reg[val].type, reg[val].brand, reg[val].regnum);
}
}
If additional information about my program is needed to solve the program please tell me and I will provide more of the code.
here is the problem i am having. basically the structure is defined properly, but the compiler is throwing out an error when it tries to read input from the given file. I can get through the menu in the while loop before the case and then do option 'a' or 'A' and get the patient number. Then I can open the file but I cannot read any information from the file into the structure variables. it just terminates the code. The files I am trying to read in from are formatted as follows:
time BP_diastolic BP_systolic
01 80 120
02 81 124
03 78 118
etc.
time temp
01 98.7
02 99.0
03 98.5
etc.
time rate
01 68
02 70
03 65
etc.
I am supposed to read info in from the files, put them into variables and then determine the health score for a given day according to this equation:
𝑓(𝑡𝑖𝑚𝑒,𝑡𝑒𝑚𝑝,𝑝𝑟𝑒𝑠𝑠,𝑟𝑎𝑡𝑒) = 15∗𝑡𝑒𝑚𝑝+35∗𝑝𝑟𝑒𝑠𝑠+25∗𝑟𝑎𝑡𝑒 +25
where:
temp is based on the body temperature at time t, and is defined as: 𝑡𝑒𝑚𝑝 = {1 𝑖𝑓 97𝐹 ≤ 𝐵𝑇 ≤ 99 0 𝑜𝑡ℎ𝑒𝑟𝑤𝑖𝑠𝑒
press is based on the blood pressure at time t, and is defined as:
𝑝𝑟𝑒𝑠𝑠 = {
1 𝑖𝑓 𝐵𝑃𝐷 ≤ 80 𝑎𝑛𝑑 𝐵𝑃𝑆 ≤ 120 0.5 𝑖𝑓 80 < 𝐵𝑃𝐷 ≤ 89 𝑜𝑟 120 < 𝐵𝑃𝑆 ≤ 139 0 𝑖𝑓 𝐵𝑃𝐷 ≥ 90 𝑜𝑟 𝐵𝑃𝑆 ≥ 140
rate is based on the heart rate ending at time t based on some ∆t, usually 15 to 60 seconds, and is defined as: 𝑟𝑎𝑡𝑒 = {1 𝑖𝑓 60 ≤ 𝐻𝑅 ≤ 100 0 𝑜𝑡ℎ𝑒𝑟𝑤𝑖𝑠𝑒
I have not gotten to that section yet as I can't figure out how to get the info into the variables. Therefore I am not able to do any calculations with said data.
If option d) is chosen, the program should ask the user for a time point to calculate the Health Score. After entering a valid time (i.e. should be within the given time interval), the program should display:
a. a table with the values for BT, BP, and HR,
b. a report on the detection of any conditions (i.e., normal / prehypertension /
hypertension) described above, and
c. the HealthScore value obtained using Eq. 1.
If option e) is chosen, a table with the statistical parameters (over the time interval) for each variable should be displayed. This includes the Min, Max, Avg, and Standard Dev.
There should also be tests done to ensure all entries to the program are within the proper range.
I hope this is a better explanation of the problems I am having. Also, at this point the assignment is late but I would still like to understand what I am doing wrong. Any help would be much appreciated.
#include<stdio.h>
#include<stdlib.h>
struct bloodPressure{
int time;
double pressD;
double pressS;
};
struct temp{
int time;
double temp;
};
struct rate{
int time;
double r;
};
struct bloodPressure BP[55];
struct temp T[55];
struct rate R[55];
int main()
{
int timeStart,
timeEnd,
timeSelect;
double minTemp,
maxTemp,
avgTemp,
stdTemp,
minPressD,
maxPressD,
avgPressD,
stdPressD,
minpressS,
maxPressS,
avgPressS,
stdPressS,
minRate,
maxRate,
avgRate,
stdRate,
score;
char fileName[140],
fileNameBuffer[150],
patientNum[5],
menuSelect = "a";
FILE *fp;
while (menuSelect)
{
printf("Please select from the following list:\n");
printf("a/A: Enter patient number\n");
printf("b/B: Enter file folder location\n");
printf("c/C: Enter time interval\n");
printf("d/D: Get health score\n");
printf("e/E: Get statistical data\n");
printf("f/F: Exit the program\n");
scanf("%c", &menuSelect);
switch(menuSelect)
{
// code to enter patient ID number
case 'a':
case 'A':
{
// ask user for the patient's ID number
printf("Please enter the Patient's ID number:\n");
scanf("%s", &patientNum);
printf("%s", patientNum);
// break out of switch statement and return to main
// menu
break;
}
// code to enter file location
case 'b':
case 'B':
{
printf("Please enter the file location:\n");
scanf("%s", &fileName);
// if file for blood pressure does not open, display
// error and return to main menu
sprintf(fileNameBuffer, "%sBP_%s.txt", fileName,
patientNum);
fp = fopen(fileNameBuffer, "r");
printf("%s \n", fileNameBuffer);
if (fp == NULL)
{
printf("cannot open file");
}
// if file opens, read information from the file
// else
{
printf("file is being read\n");
// read in variables from blood pressure file into
// blood pressure structure
while (!feof (fp))//int i = 0; i < 55; i++)
{
int i = 0;
fscanf(fp, '%d %lf %lf', BP[i].time,
BP[i].pressD, BP[i].pressS);
printf("%d", BP[i].time);
if (++i >= 55)
{
break;
}
}
// close the blood pressure file
fclose(fp);
}
// if file for blood temperature does not open, display
// error and return to main menu
if (fp = fopen(("%sBT_%d.txt", fileName, patientNum),
'r') == NULL)
{
printf("cannot open file");
}
// if file opens, read information from the file
else
{
// read in variables from heart rate file into blood
// pressure structure
while (!feof (fp))
{
int i = 0;
fscanf(fp, '%d %lf', &(T[i].time), &(T[i].temp));
if (++i >= 55)
{
break;
}
}
// close the heart rate file
fclose(fp);
}
// if file for heart rate does not open, display error
// and return to main menu
if (fp = fopen(("%sHR_%d.txt", fileName, patientNum),
'r') == NULL)
{
printf("cannot open file");
}
// if file opens, read information from the file
else
{
// read in variables from heart rate file into blood
// pressure structure
while (!feof (fp))
{
int i = 0;
fscanf(fp, '%d %f', &(R[i].time), &(R[i].r));
if (++i >= 55)
{
break;
}
}
// close the blood pressure file
fclose(fp);
}
// break out of switch statement and return to main
// menu
break;
}
// code to enter time interval
case 'c':
case 'C':
{
// ask user for start and end times for the time
// interval
printf("Please enter the starting time:\n");
scanf('%d', timeStart);
printf("Please enter the ending time:\n");
scanf('%d', timeEnd);
// break out of switch statement and return to main
// menu
break;
}
// code to calculate health score
case 'd':
case 'D':
{
break;
}
// code to calculate statistical data
case 'e':
case 'E':
{
break;
}
// code to exit the program
case 'f':
case 'F':
{
printf("You have chosen to exit the program\n");
exit(1);
}
default:
{
printf("Error: Please enter a valid menu option (a-f or
A-F)");
break;
}
}
}
return 0;
}
Edited after question was changed -- see below
Quite a few things in your code would not be accepted by compilers - here are some improvements you could make:
Strings need double quotes in C, so " instead of '
Variables should be declared before use. In your code, for instance, fp and fileName were not declared, and BP was declared as a type-alias (with typedef) instead of a variable.
There were a few minor mistakes, like commenting out the else statement and not ending the if-part of that condition with a brace }.
fopen() does not accept the construction for the filename you gave it - you must first do that in a separate function call to sprintf().
My compiler wasn't too thrilled about the construction if (fp = fopen(...) == NULL), though perhaps other compilers may accept it. The statement can be split.
In the fscanf() statement, there were three things:
The indexes [i] were in the wrong places,
i was not defined and didn't get increased to the next value, and there was no check on it reaching its maximum value
Minor point: to read values of type double, you'd use the scan string %lf (long float).
C is a pretty hard language when you start, so don't worry... Here is what I made of it (which worked correctly on my computer):
#include <stdio.h>
// structure definitions
struct bloodPressure{
int time[55];
double pressD[55];
double pressS[55];
};
// declarations
struct bloodPressure BP;
char fileName[100], fullname[110];
int i = 0;
const int patientNum = 1;
FILE *fp;
// start of problem
int main() {
printf("Please enter the file location:\n");
scanf("%s", fileName);
sprintf(fullname, "%sBP_%d.txt", fileName, patientNum);
// if file for blood pressure does not open, display error and
// return to main menu
fp = fopen(fullname, "r");
if (fp == NULL)
{
printf("cannot open file");
}
// if file opens, read information from the file
else
{
// read in variables from blood pressure file into blood
// pressure structure
while (!feof (fp)) //int i = 0; i < 55; i++
{
fscanf(fp, "%d %lf %lf", &(BP.time[i]), &(BP.pressD[i]), &(BP.pressS[i]));
if (++i >= 55) break;
}
// close the blood pressure file
fclose(fp);
}
}
You might consider changing the definition of struct bloodPressure so it holds pressure data of one measurement, and then create an array of such structs, like
struct bloodPressure BP[55];
instead of what you have here, a struct holding arrays. It seems more logical to me.
EDIT
As you have rewritten your question and your program (and improved it a lot I think), I'm editing the answer.
I can open the file but I cannot read any information from the file into the structure variables. it just terminates the code.
In line 109, your fscan scanning pattern is still single-quoted (quotes should be "). Same in some other places, like line 188.
By the way, your else statement in line 101 is still commented out.
Generally your coding is improving fast. It might help if you tell your compiler to warn you when you do something that may lead to errors. Many compilers accept an option -Wall (Warn at all things it doesn't like).
I'm trying to make a program that can store certain information in a text file. The problem I have though is that with the code I've written so far, the information stored is a bunch of weird symbols and characters. I've managed to kind of find out where it happens from but I can't seem to solve it. It seems like in my register_item function, both item number and balance get weird values for some reason. If anyone can see what mistake I've made, that would be appreciated.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 20
struct vara
{
int itemnumber[20];
char name[30];
int balance[20];
};
open_file(FILE *ange_filnamn, char filnamn[], struct vara varor[], int *antal_varor)
{
int mainmenu = 0;
while (mainmenu != 1 && mainmenu != 2)
{
printf("Do you want to open an existing file (1) or create a new one (2)?\n");
scanf("%d", &mainmenu);
//system("CLS");
if(mainmenu==1)
{
printf("Choose filename (ex. .txt).\n");
scanf("%s", filnamn);
ange_filnamn=fopen(filnamn, "r+");
while(!feof(ange_filnamn))
{
fread(&varor[*antal_varor], sizeof(struct vara), 1, ange_filnamn);
if(!feof(ange_filnamn))
{
*antal_varor=*antal_varor + 1;
}
}
printf("\nNumber of items: %d \n",*antal_varor);
fclose(ange_filnamn);
}
if(mainmenu==2)
{
printf("What name do you want for your new file?\n");
scanf("%s", filnamn);
ange_filnamn=fopen(filnamn, "w+");
printf("File is created!\n");
*antal_varor = 0;
fclose(ange_filnamn);
}
}
}
register_item(struct vara *varor, int *antal_varor)
{
printf("Item number:\n");
scanf("%d", varor[*antal_varor].itemnumber);
printf("Name:\n");
scanf("%s", varor[*antal_varor].name);
printf("Balance:\n");
scanf("%d", varor[*antal_varor].balance);
*antal_varor+=1;
}
print_item(struct vara varor[], int antal_varor)
{
int i;
for (i=0; i < antal_varor; i++)
{
printf("%d. Item number: %d Name: %s Balance: %d\n", i, varor[i].itemnumber, varor[i].name, varor[i].balance);
}
}
quit_program(char filnamn[], struct vara varor[], int *antal_varor)
{
FILE *fil;
//printf("%s", filnamn);
fil=fopen(filnamn, "w+");
fwrite(varor, sizeof(struct vara), *antal_varor, fil);
fclose(fil);
}
int main(void)
{
FILE *ange_filnamn;
struct vara varor[MAX];
int mainmenu, menu, antal_varor=0;
char filnamn[20], filen[30];
open_file(ange_filnamn,filnamn, varor, &antal_varor);
//Second menu
while(menu!=7)
{
printf("\n");
printf("1. Register new items to inventory.\n");
printf("2. Print all items from inventory.\n");
printf("3. Search for item.\n");
printf("4. Change inventory.\n");
printf("5. Sort inventory.\n");
printf("6. Deregister item from inventory.\n");
printf("7. Quit.\n");
scanf("%d", &menu);
if(menu==1)
{
register_item(varor, &antal_varor);
}
if (menu==2)
{
print_item(varor, antal_varor);
}
if (menu==3)
{
printf("test");
}
if (menu==4)
{
printf("test");
}
if (menu==5)
{
printf("test");
}
if(menu==6)
{
printf("test");
}
if (menu==7)
{
quit_program(filnamn, varor, &antal_varor);
}
}
}
You have an array of structures. The array contains antal_varor number of structures, and each structure contains members (elements) itemnumber, name, and balance.
Before we get started, a little side note: I think your structure definition has some bugs. Based on the way you're using it, I think you want
struct vara
{
int itemnumber;
char name[30];
int balance;
};
But your question was about writing the file out. When you call
fwrite(varor, sizeof(struct vara), *antal_varor, fil);
you are writing out the entire array, all at once, in "binary", which is why you can't read it. If you want to write it out in a more human-readable form, you can do something like this. Here I have an explicit loop over the elements of the array, and each time through the loop, I print out all the members of that element:
int i;
for(i = 0; i < *antal_varor; i++ {
fprintf(fil, "varor %d:\n", i);
fprintf(fil, " itemnumber: %d\n", varor[i].itemnumber);
fprintf(fil, " name: %s\n", varor[i].name);
fprintf(fil, " balance: %d\n", varor[i].balance);
}
So, first try that. You should find that the output file is perfectly readable.
Now, the problem is that since you wrote the file out in this nicer, more readable format, your code that reads the data back in, that used to use
fread(&varor[*antal_varor], sizeof(struct vara), 1, ange_filnamn);
is not going to work any more. But here is the sort of code you could use to read the new-format file back in. This code reads the file line by line with fgets, figuring out what each line is, and plugging data items one by one into the varor array to rebuild it.
char line[80];
int i = 0;
*antal_varor = 0;
while(fgets(line, sizeof(line), ange_filnamn) != NULL) {
if(strncmp(line, "varor ", 6) == 0) {
sscanf(line, "varor %d:", &i);
if(i >= MAX) {
fprintf(stderr, "warning: index in file too large\n");
i = 0;
continue;
}
if(i + 1 > *antal_varor) *antal_varor = i + 1;
} else if(strncmp(line, " itemnumber:", 12) == 0) {
sscanf(line, " itemnumber: %d", &varor[i].itemnumber);
} else if(strncmp(line, " name:", 6) == 0) {
sscanf(line, " name: %s", varor[i].name);
} else if(strncmp(line, " balance:", 9) == 0) {
sscanf(line, " balance: %d", &varor[i].balance);
} else {
fprintf(stderr, "warning: unrecognized line in file\n");
}
}
printf("\nNumber of items: %d \n",*antal_varor);
fclose(ange_filnamn);
I haven't tested this, so there may be some little mistakes in it, but it should give you the idea.
(Also there are better ways of writing this sort of thing, but they're a little more elaborate or require more infrastructure, so I've stuck to something very simple and understandable, although it's less than robust.)
The commenters on your question have it right.
- What is displayed with printf (and written to a file with fprintf) is ASCII representation of the numbers.
- What is stored in memory (and written with fwrite) is the actual "binary" value.
In C, an int variable always takes up the same number of bytes in memory, regardless of the value stored. That is why your sizeof() works consistently. Reading and writing can be consistently done.
(Note that not all C implementations use the same size int though. It is 4 bytes in the x86 Linux I'm using right now).
When displaying the ASCII representation, the number of ASCII digit characters required depends on the value. So, if reading values in that have been stored this way, you have to 'parse' the text and build up the integer value from the digits read, and in general will be a variable number of digits. (This is what scanf does.) Hence, reading and parsing ASCII could be considered more complicated than just reading in a value stored as binary int that is always the same size.
IMPORTANT: If you are going to read the file as binary, you should open it with the "b" attribute like this:
ange_filnamn=fopen(filnamn, "r+b");
Similary, to open for binary write:
fil=fopen(filnamn, "w+b");
Run-Time Check Failure #2 - Stack around the variable 'filename' was corrupted.
My code works whenever I try to process the first memory location.
I can process the .txt file correctly, and I can print it.
Nevertheless, when I ask for a second memory location, the program crashes.
I tried to increase the size of filename, and I am also closing the first file, so I am clueless. Any help is acceptable! Thank you!!
This is a photo of the output
This is my code:
#include <stdio.h>
#define SIZE 100 //100 entries (100lines on a file)
#define SENSORN 100
int main()
{
FILE *fptr;
char filename[1000];
char dummy1[1];//dummy character that help me to erase what is the buffer when using gets()
int numberOfSensors;
int time[SENSORN][SIZE];
float powerConsumption[SENSORN][SIZE];
int sensor_num;
int count1 = 0;
printf("Please enter the number of sensors: ");
scanf("%d", &numberOfSensors);
//Asking for the link
//numberOfSensors - 1 because for example, if we want only 2 sensors we need sensor0 and sensor1 only
for (sensor_num = 0; sensor_num <= (numberOfSensors - 1); sensor_num++)
{
printf("Please enter the file location for sensor %d\n", sensor_num);
gets(dummy1);//clearing the buffer
gets(filename);
fptr = fopen(filename, "r");
//if file cannot be opened, then display and error message
if (fptr == NULL)
{
printf("Error opening the file! %s \n", filename);
printf("Please restart the program \n");
return 0; //exit the program
}
else
{
//Loop that let us read and print all the file by storing each value to its respective array
while (!feof(fptr))
{
//storing all the values in their respective array
//sensor_num is the sensor number
//count1 is the line number we are reading from the file
fscanf(fptr, "%d %f", &time[sensor_num][count1], &powerConsumption[sensor_num][count1]);
//making sure we have all the values stored
//Note: do not comment the following line in order to check that all values are stored
fprintf(stdout, "%d %6.2f \n", time[sensor_num][count1], powerConsumption[sensor_num][count1]);
count1++;
}
}
//closing file
fclose(fptr);
}
}
}
As Martin James said char dummy1[1]; is an absolute no-no.
Use fgets() instead of gets(), so instead of
gets(dummy1);//clearing the buffer
gets(filename);`
try,
fgets( filename, sizeof(filename) , stdin );