Why can't I input a filename for opening in c? - c

I have been attempting to debug this program with my limited knowledge, and have compared it with other programs in which i've used the same methods to retrieve a filename for opening. However, it seems that for some odd reason the program does not recieve user input for filename, sometimes getting caught in some sort of an elusive loop.
I have used both:
scanf("%s\n", filename);
and:
gets(filename);
(i know gets is "dangerous" but this is a program that is not going to be distributed, it is an assignment in a college level class)
here is the main() function and the getssn() function (which does get user input successfully):
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define MAXS 19
#define MAXR 999
//structure defining a given client
typedef struct person {
unsigned int ssn, age, height, weight, income;
char name[MAXS+1], job[MAXS+1], religion[MAXS+1], major[MAXS+1], minor[MAXS+1], gender;
}PERSON;
//get and check for ssn validity
int getssn(){
int num;
printf("\nSSN: ");
scanf("%d", &num);
if(num<=99999999 || num>999999999){
printf("\nPlease input a valid SSN.\n");
return 0;
}
else
return num;
}
//read the specified file and check for the input ssn
int readfile(FILE *fptr, PERSON **rptr, int *count){
int v=0, i, j;
char n2[MAXS+1], b[2]=" ";
for(i=0; i<MAXR; i++){
j=i;
//read the file in chunks
if(fscanf(fptr, "%c\n%d\n%19s %19s\n%d\n%19s\n%d\n%19s\n%19s\n%d\n%d\n%19s\n\n",
&rptr[j]->gender, &rptr[j]->ssn, rptr[j]->name, n2, &rptr[j]->age,
rptr[j]->job, &rptr[j]->income, rptr[j]->major, rptr[j]->minor,
&rptr[j]->height, &rptr[j]->weight, rptr[j]->religion)==EOF)
i=MAXR;
//make first and last name one element
strcat(rptr[j]->name, b);
strcat(rptr[j]->name, n2);
//if we find a match, tell main the id
if(rptr[MAXR]->ssn==rptr[j]->ssn)
v=j;
}
//count how many clients we have
*count=j;
return v;
}
//commpare age and income
int cmpai(PERSON rec1, PERSON rec2){
int a=0, inc=0;
if(rec1.age<=(rec2.age+10) && rec1.age>=(rec2.age-10))
a=1;
if(rec1.income<=(rec2.income+10000) && rec1.income>=(rec2.income-10000))
inc=1;
if(a==1 && inc==1)
return 1;
else
return 0;
}
//compare hobbies
int cmph(PERSON rec1, PERSON rec2){
if(strcmp(rec1.major,rec2.major)==0 && strcmp(rec1.minor, rec2.minor)==0)
return 1;
else
return 0;
}
//compare weight, height, and religion
int cmpwhr(PERSON rec1, PERSON rec2){
int w=0, h=0, r=0;
double n1, n2;
n1=rec1.height;
n2=rec2.height;
if(n1<=(n2*1.1) && n1>=(n2*0.9))
h=1;
n1=rec1.weight;
n2=rec2.weight;
if(n1<=(n2*1.1) && n1>=(n2*0.9))
w=1;
if(strcmp(rec1.religion, rec2.religion)==0)
r=1;
if(r==1 && h==1 && w==1)
return 1;
else
return 0;
}
//sort the ids in ascending order by ssn for proper output
void sort(int *A, int count){
int i, j, temp;
for(i=0; i<count; i++)
for(j=0; j<count; j++)
if(A[i+1]<A[i]){
temp=A[i];
A[i]=A[i+1];
A[i+1]=temp;
}
}
//display the possible matches in ascending ssn order
void display(int matches[], PERSON rec[], int count){
int i;
for(i=0; i<count; i++){
if(matches[i]==rec[i].ssn)
printf("%s\n", rec[i].name);
}
}
int main(){
int valid=-1, i, counter=0, *c=&counter, id[MAXR-1], totalmatches;
char filename[MAXS];
FILE *fp;
PERSON record[MAXR+1], *rp[MAXR+1];
//get a ssn from the user
do{
record[MAXR].ssn=getssn();
}while(record[MAXR].ssn==0);
//get a filename
printf("Name of file of records: ");
scanf("%s", filename);
printf("%s", filename);
//open the file, if possible
if((fp=fopen(filename, "r"))==NULL)
perror(filename);
else{
printf("test");
for(i=0; i<=MAXR; i++){
rp[i]=&record[i];
id[i]=0;
}
//read the file, find the matching ssn
valid=readfile(fp, rp, c);
//check if the ssn is in the file, if not tell the user
if(valid<0){
printf("\nSSN %d is not found in file %s.\n", record[MAXR].ssn, filename);
return EXIT_FAILURE;
}
else {
//check for matches and count how many we have
for(i=0; i<counter; i++){
if(i!=valid)
if(record[valid].gender!= record[i].gender)
if(cmpai(record[valid], record[i])==1 || cmph(record[valid], record[i])==1 || cmpwhr(record[valid], record[i])==1){
id[i]=record[i].ssn;
totalmatches+=1;
}
}
//if we have matches sort them and display them, otherwise tell the user he has no match in this group
if(totalmatches>0){
sort(id, counter);
display(id, record, counter);
}
else
printf("\nNo matches.\n");
fclose(fp);
return EXIT_SUCCESS;
}
}
}
This is the current input(single quotes)/output:
run
[Switching to process 6956]
Running…
SSN: '111223333'
Name of file of records: 'clients.txt'
clients.txttest
Debugger stopped.
Program exited with status value:0.

You should your getssn() function. You need to put in a return statement.
int getssn(){
int num;
printf("\nSSN: ");
scanf("%d", &num);
return num; // You MUST put this in.
}
This will improve this code:
do{
record[MAXR].ssn=getssn();
}while(record[MAXR].ssn==0);
If you forget the return, then getssn() might return 0 forever.
You should also tell us what exact output you are seeing. You should copy all the output into your question also.

Never use any of the scanf family of functions; they don't give you nearly enough control over what happens on invalid input, and scanf("%s") is just as dangerous as gets.
But this is probably not your immediate problem. That's much more likely to be a case of trying to open a file by partial pathname when it's not in the current working directory. Try typing in the full pathname (/home/kabir/filename, C:\users\kabir\filename, sort of thing). Also, changing
printf("\nCould not open file\n");
to
perror(filename);
will give you more information when things go wrong.

It should be
scanf("%s", filename)
i.e. remove the \n
Unrelated, but you seem to have forgotten return num at the end of getssn().
Looking at your current code (8:10 pm Dublin/London time), you should use this instead:
//get a filename
printf("Name of file of records: ");
//scanf("%s", filename);
printf("scanned file: <%s>\n", filename);
//open the file, if possible
if((fp=fopen(filename, "r"))==NULL)
perror(filename);
else{
printf("test\n");
...

Related

how to check variable validity and how to send array of structure to function?

I'm working in library system, I've a lot of things going on:(. In addBook function I'm trying to add book information into Array of structure. First I don't know how to set a statement to check all the validity of title, author, isbn and others. I tried to write a statement but it wont work so I removed it! and didn't call the functions since I don't know how to make them work! secondly I want to send the book information to a file so I can store them inside the file and sort alphabetically. whenever I try to send the array and check the txt file it print the address please help :( I'm trying to keep it simple as possible as I can
#include <stdio.h>
#include <stdlib.h>
#define MAX_ISBN 11
#define MIN_ISBN 9
#define MAX_YEAR 2021
#define MIN_YEAR 1500
#define MAX_DAY 31
#define MIN_DAY 1
#define MAX_MONTH 12
#define MIN_MONTH 1
#define MIN_ISBN 9
#define MAX_Title 80
#define MAX_Author 80
struct Book{
int ISBN[MAX_ISBN], Edition[500], Year[MAX_YEAR],DD[MAX_DAY], MM[MAX_MONTH];
char Title[MAX_Title];
char Author[MAX_Author];
};
/*Check_Title function will check user input if it's a valid title or not! */
int Check_Title(char *Title){
int valid_Title = 1;
int len = 0;
int i= 0;
len = strlen(Title);
for(i =0; i <len ; i++)
{
if( Title[i] == "##$%^&*()}{[ ]")
return 0;;
}
return 1;
}
/*Check_Author function will check user input if it's a valid Author name or not! */
int Check_Author(char *Author){
int valid_Name = 1;
int len = 0;
int i= 0;
len = strlen(Author);
for(i =0; i <len ; i++)
{
if( !(isalpha(Author[i])) && (Author[i] != ' '))
{
valid_Name = 0;
break;
}
}
return valid_Name;
}
int Check_Date(int *DD, int *MM,int *YYYY){
if(DD[MAX_DAY] > MAX_DAY || DD[MIN_DAY]< MIN_DAY)
return 0;
if(MM[MAX_MONTH] >31 || MM[MIN_DAY]<1)
return 0;
if(YYYY[MAX_YEAR]>MAX_YEAR || YYYY[MIN_YEAR]<MIN_YEAR)
return 0;
return 1; //if statement true return 1
}
int Check_ISBN(int *ISBN){
if(ISBN[MAX_ISBN] > MAX_ISBN || ISBN[MIN_ISBN] < MIN_ISBN);
return 0;
return 1; //if ISBN VALID
}
// This function is used to check file existence, every time if it's called
//the following functions is user choice to either add a book, delete, view, and view by year -> Switch cases
void addBook(){
system("cls"); //clearing black screen
int Title_Validity = 0, Name_Validity = 0, ISBN_Validity, Date_Validity = 0,n;
struct Book *insert = NULL;
FILE* ptr = fopen("stored.txt","w");
if (ptr == NULL){
printf("Error opening the file! \n");
exit(1);}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
printf("\n\t\t ========================================================================");
printf("\n\t\t ADD NEW BOOK ");
printf("\n\t\t ========================================================================");
printf("\n\n\t\t\tENTER YOUR DETAILS BELOW:");
printf("\n\t\t\t---------------------------------------------------------------------------\n");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
printf("\t\tHow many Books would you like to insert? ");
scanf("%d", &n);
for(int i = 0; i<n; i++){
insert = (struct Book*)calloc(n,sizeof(struct Book));
//Inputing Title & Check Title validity
//do{
printf("\n\t\t\tBook Title : ");
fflush(stdin);
fgets(insert[i].Title, MAX_Title, stdin);
/*Title_Validity = Check_Title(&insert[MAX_Title].Title);
if(Title_Validity){
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_");
printf("\t\t\t\t\t\t \t\t Invalid Input ! please try again! \n\t\t\t and make sure to not use any digits or special characters! \n ");
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_*_");
}
}while(Title_Validity);*/
//Inputing Author
printf("\n\t\t\tBook Author : ");
fflush(stdin);
fgets(insert[i].Author, MAX_Author, stdin);
//Inputing ISBN
//do{
printf("\n\t\t\tBook ISBN : ");
scanf("%d", &insert[i].ISBN);
// fflush(stdin);
//fgets(insert[i].ISBN, MAX_ISBN, stdin);
/* ISBN_Validity = Check_ISBN(&insert[MAX_ISBN].ISBN);
if(ISBN_Validity == 0){
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_");
printf("\t\t\t\t\t\t \t\t Invalid Input ! please try again! \n\t\t\t and make sure to not to not accedes the range 9~11! \n ");
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_*_");
}
}while(ISBN_Validity!=0);*/
//Inputing Edition
printf("\n\t\t\tBook Edition (only digits acceptable) : ");
scanf("%d", &insert[i].Edition);
//Inputing Date
printf("\n\t\t\tBook Date [DD MM YYYY] : ");
scanf("%d%d%d", &insert[i].DD,&insert[i].MM,&insert[i].Year);
printf("\n\t\t ========================================================================");
printf("\n\t\t The book %s has been added to the library.", insert[i].Title );
printf("\n\t\t ========================================================================");
}
//
Sort_Save(n,&insert[x].Title,&insert[x].Author,&insert[x].ISBN,&insert[x].Edition,&insert[x].DD,&insert[x].MM,&insert[x].Year);
return;
}
void Sort_Save(int n,char Title[MAX_Title],char Author[MAX_Author], int ISBN[MAX_ISBN], int Edition[], int day[MAX_DAY], int month[MAX_MONTH], int year[MAX_YEAR]){
int i;
struct Book *st;
FILE* fptr = fopen("sorted.txt", "w");
if(fptr == NULL){
printf("Error opening file! \n");
exit(1);
}
for(i=0; i<n; i++){
fprintf(fptr,"%s %s %d %d %d %d %d",st[i].Title,st[i].Author,st[i],st[i].ISBN,st[i].Edition,st[i].DD,st[i].MM,st[i].Year);
fprintf(fptr,"\n");
}
printf("\n");
fclose(fptr);
}
Since you're asking the users how much books they want to add, you have to allocate the block of memory only once, best right after (before the loop) and certainly not again and again in the loop, where it gets initialized with '0' (zero, that's what calloc does).
And opening a file with the mode "w" truncates that file to zero length, i don't think that this is what you want. And why do you open it, when you do not access it, neither for reading nor for writing?
After scanning, you call the Sort_Save function with a bunch of useless parameters (where does the variable 'x' come from?). You should declare the function like this:
int sortSave(struct Book *books, size_t size)
and pass the allocated block (insert) with the specified size (n).
If you want to sort your library, then you should open the existing database for read first ("r"), then read all the stored values into an array, append the new data to that array, call 'qsort' (see man qsort), specify your compare function (where you specify by which parameter your library should be sorted), close the file, open it again in write mode ("w") and finally write all your (sorted) data into that file.
Do not to forget to flush and close the file, nor to free the allocated blocks of memory.
Edit:
As a hint, seperate code from design. First make sure your code works as expected, then add all the fancy stuff, best as a seperate function.

Search returning only the first result in structure C

I am trying to read a file and print the records where the jumper has exceeded the distance provided by the user, but the search only returns the first line in the file and that's it, i know there is something wrong in the logic but i cant put my finger on it.
#include<stdio.h>
#include<string.h>
typedef struct {
char fname[30];
char lname[30];
char nationality [30];
double distance;
}Player;
void print(Player p) {
printf("%s %s %s %f \n", p.fname, p.lname, p.nationality, p.distance);
}
int search(double distance, Player allPlayers[], int max){
int i=0;
for(i=0; i<max; i++){
if(distance > allPlayers[i].distance){
return i;
}
return -1;
}
}
void load (char filename[10], Player players[]){
char tempfName [30];
char templName [30];
char tempNationality [30];
double tmpdistance;
FILE * input=fopen(filename,"r+");
if(input==NULL)
printf("Error found in opening the file\n");
else {
printf("The data are loaded successfully.\n");
int counter = 0;
while(!feof(input)){
strcpy(tempfName," ");
fscanf(input, "%s %s %s %f",tempfName, templName, tempNationality, &tmpdistance);
if(strcmp(tempfName, " ") !=0){
strcpy(players[counter].fname, tempfName);
strcpy(players[counter].lname, templName);
strcpy(players[counter].nationality, tempNationality);
players[counter].distance = tmpdistance;
counter++;
}
}
fclose(input);
}
}
int main (int argc, char *argv[]){
Player players2[40];
char myFileName[10] ="jump.txt";
load(myFileName, players2);
double tmpdistance;
printf("Please enter the distance threshold: ");
scanf("%lf", &tmpdistance);
printf("The jumpers exceeded 8.10 m are: \n");
int index = -1;
index = search(tmpdistance,players2,40);
if(index!=-1)
print(players2[index]);
else
printf("NOT Found! \n");
return 0;
}
some sample data from the file I'm trying to read :
Arsen Sargsyan Armenia 7.62
Boleslav Skhirtladze Georgia 7.26
Christian Reif Germany 7.92
Christopher Tomlinson Great_Britain 8.06
In your search() function:
if(distance > allPlayers[i].distance){
return i;
}
This will return the first jumper whose performance is less than the distance provided.
If you replace it with:
if(allPlayers[i].distance > distance){
return i;
}
It will return the first jumper whose performance is greater than the distance provided, which is what you want.
Also:
Don't loop over feof() to read a file: Why is “while ( !feof (file) )” always wrong?
You're printing "The data are loaded successfully" when you haven't loaded the data yet - you've just opened the file
You don't need the arguments to main()
You don't need to initialise index to -1 as you assign it in the next line
You don't need to specify the size of myFileName as the compiler can work it out

Buffer overflow or something else

I am creating a program, about seat reservations. I was asked to use unsigned short and unsigned int for some of the variables, so that is why they are set like that.
I have a program that works ok. But when I transfer everything inside a function, everything seems to work ok, but inside my structure weird values start to be saved all over the place..
I only want to save the values of the file (from line 2 -> the end of file).
Because I have a structure that to be initialized I have first to read the txt file and numberofseats, I have am declaring this variable (passenger) 2 times..inside the function (local var) and in the main body..
Maybe this causes the problem?
If I don't use a function everything work fine!
So the problematic code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j,numberofseats,temp;
char platenr[8],selection,buff[60];
char firstname[20];
char lastname[20];
char phone[11];
char *p;
typedef struct
{
char fullname[40];
unsigned short phonenr[10];
unsigned int seatnr;
}PASSENGERS;
void readfile( void)
{
FILE *businfo;
businfo = fopen ("bus.txt","r");
if (businfo == NULL)
{
printf("Error Opening File, check if file bus.txt is present");
exit(1);}
else
{
fscanf(businfo,"%s %d",platenr, &numberofseats);
printf("Bus Licence plate Nr is: %s and number of seats is: %d", platenr, numberofseats);
PASSENGERS passenger[numberofseats];
for (j=0;j<numberofseats;j++)
{passenger[j].seatnr=j+1;
strcpy(passenger[j].fullname,"\0");
}
while (fgets(buff,sizeof(buff),businfo)!=0)
{sscanf(buff, "%s %s %d %s", firstname, lastname, &temp,phone);
strcpy(passenger[temp-1].fullname,firstname);
strcat (passenger[temp-1].fullname, " ");
strcat(passenger[temp-1].fullname,lastname);
printf("%s",passenger[temp-1].fullname);
i=0;
for (p=phone;*p!='\0';p++)
{
(passenger[temp-1].phonenr[i])=*p -'0';
i++;
}
}
}
}
int main(void)
{
readfile();
PASSENGERS passenger[numberofseats];
A variable called x in function foo has nothing to do with a variable called y in function bar. In other words: passenger in main and passenger in readfile are different variables. Changing one will not impact the other.
What you want is probably more like this:
int main(void)
{
PASSENGERS passenger[numberofseats];
readfile(passenger);
^^^^^^^^^
Pass array as a pointer
....
}
and
void readfile(PASSENGERS* passenger)
{
....
// REMOVE THIS: PASSENGERS passenger[numberofseats];
}
Beside that notice:
// Global variables gets zero initialized
int i,j,numberofseats,temp;
^^^^^^^^^^^^
Becomes zero at start up
but still you use it in main:
PASSENGERS passenger[numberofseats];
That is probably no what you really want.
Since you try to read the number of seats in the function, it seams you really want to use dynamic memory allocation. Like:
PASSENGERS* readfile()
{
.....
.....
PASSENGERS* p = malloc(numberofseats * sizeof(PASSENGERS));
.....
.....
return p;
}
int main(void)
{
PASSENGERS* passenger = readfile();
.....
.....
free(passenger);
return 0;
}
If you don't want dynamic allocation, you must move the input of numberofseats into main so it is done before declaring the array.
The problem is that you are declaring a local array in the function readfile(), and once this function terminates, it is lost. You need to be able to return the changes to main(). For that you have some options. One is that you may declare the array in main(), and change your function to void readfile(PASSENGERS passenger[]). In this case, you will do something like this:
int main()
{
PASSENGERS passenger[numberofseats];
readfile(passenger);
// more code
You will be basically passing a pointer to the memory location of the elements stored in the array, local to main(), and the function will fill the array, effectively returning the changes.
Another option is to dynamically allocate an array (with malloc() family) in the function, and make it return a pointer like PASSENGERS *readfile(void). This option may be more suitable if the number of seats is not known at compile time, so you need to dynamically grow or shrink the array when necessary. This option however, leaves you the burden of managing the memory manually, like free()'ing the allocated memory when you are done.
Since you say that you will read numberofseats from the file, the latter would be the better idea, so your code will look something like this:
PASSENGERS *readfile(void)
{
FILE *businfo;
PASSENGERS *passenger;
businfo = fopen ("bus.txt","r");
// do the checks, read the numberofseats
passenger = malloc(numberofseats * sizeof *passenger);
// read the values, fill the array
fclose(businfo); // do not forget to close the file
return passenger;
}
int main()
{
PASSENGERS *passenger = readfile();
// more code
free(passenger);
return 0;
}
Ok, so what I did, before starting to work on dynamic allocation is specify the max number of seats in the start of main, and from there I finished my code as follows. I have 2 warning messages though in lines 43, 109 that can't seem to be able to fix.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int i,j,numberofseats,temp;
char platenr[8],selection;
char firstname[20],lastname[20];
char phone[11];
char *p;
typedef struct
{
char fullname[40];
unsigned short phonenr[10];
unsigned int seatnr;
}PASSENGERS;
void readfile(PASSENGERS passenger[])
{ char buff[60];
FILE *businfo;
businfo = fopen ("bus.txt","r");
if (businfo == NULL)
{
printf("Error Opening File, check if file bus.txt is present");
exit(1);}
else
{
fscanf(businfo,"%s %d",platenr, &numberofseats);
printf("Bus Licence plate Nr is: %s, and Number of Seats is: %d.", platenr, numberofseats);
for (j=0;j<numberofseats;j++)
{passenger[j].seatnr=j+1;
strcpy(passenger[j].fullname,"\0");
}
while (fgets(buff,sizeof(buff),businfo)!=0)
{sscanf(buff, "%s %s %d %s", firstname, lastname, &temp,phone);
strcpy(passenger[temp-1].fullname,firstname);
strcat (passenger[temp-1].fullname, " ");
strcat(passenger[temp-1].fullname,lastname);
i=0;
for (p=phone;*p!='\0';p++)
{
(passenger[temp-1].phonenr[i])=*p -'0';
i++;
}
}
}
}
void countfreeseats(PASSENGERS passenger[]){
int freeseats = 0;
for (j=0; j<numberofseats; j++)
{
strcmp(passenger[j].fullname,"\0")==0 ? freeseats = freeseats + 1 : freeseats ;}
printf ("There are %d Free Seats in this Bus. \n", freeseats);
printf("Seats that are Available are:\n");
for (j=0; j<numberofseats; j++)
{if (strcmp(passenger[j].fullname,"\0")==0)
printf ("%u\n", passenger[j].seatnr);
}
freeseats = 0;
}
void changeData(PASSENGERS *target){
unsigned short tempdigit;
printf("Enter Passenger's first name:");
scanf("%s",firstname);
printf("Enter Passenger's last name:");
scanf("%s",lastname);
strcpy(target->fullname,firstname);
strcat (target->fullname, " ");
strcat(target->fullname,lastname);
printf("Enter Passenger's phone Nr:");
scanf("%s",phone);
i=0;
for (p=phone;*p!='\0';p++)
{
(target->phonenr[i])=*p -'0';
i++;
}
}
void searchpassenger(PASSENGERS passenger[], char selection)
{ char tempsel,tmpfirst[20],tmplast[20];
unsigned short tempphone[10];
if (selection == '1')
{ printf("Enter Passenger's first name:");
scanf("%s",tmpfirst);
printf("Enter Passenger's last name:");
scanf("%s",tmplast);
strcat (tmpfirst, " ");
strcat(tmpfirst,tmplast);
for (j=0;j<numberofseats;j++)
if (strcmp(passenger[j].fullname,tmpfirst)==0)
printf ("Passenger %s has Seat Nr #: %u\n",tmpfirst,passenger[j].seatnr);
}
else if (selection == '2')
{ printf("Enter Passenger's Phone Nr:");
scanf("%s",phone);
i=0;
for (p=phone;*p!='\0';p++)
{
(tempphone[i])=*p -'0';
i++;
}
for (j=0;j<numberofseats;j++)
{if (strcmp(tempphone,passenger[j].phonenr)==0)
printf("Passenger %s has Seat Nr %hd already Booked",passenger[j].fullname,passenger[j].seatnr);
}
}
}
void cancelSeat(PASSENGERS *target){
strcpy(target->fullname,"\0");
for (i=0;i<10;i++)
target->phonenr[i]=0;
printf("Seat Nr %d is now Free",temp);
}
void showList(PASSENGERS passenger[])
{
printf("The following Seats are Booked: \n Name, PhoneNr, SeatNr\n\n"); /*Emfanisi minimatos*/
for (i=0; i<numberofseats; i++)
if (strcmp(passenger[i].fullname,"\0")!=0)
{
printf("%s, ",passenger[i].fullname);
for (j=0;j<10;j++)
{printf("%hu",passenger[i].phonenr[j]);}
printf(", %u\n",passenger[i].seatnr);
}
}
void writeFile(PASSENGERS passenger[])
{
FILE * output; /* Dilosi onomatos arxeiou */
output = fopen("output.txt","w"); /*dimiourgia i eggrafi pano se iparxon arxeio me onoma output.txt, mesw tis parametrou w*/
fprintf(output,"%s %d \n",platenr,numberofseats); /* mesw tis fprintf eksagogi pinakidas kai epikefalidas "Diagramma leoforeiou" sto arxeio output.txt. Allagi grammis opou xreiazetai*/
for (i=0; i<numberofseats; i++)
{if (strcmp(passenger[i].fullname,"\0")!=0)
{
fprintf(output,"%s ",passenger[i].fullname);
fprintf(output,"%u ",passenger[i].seatnr);
for (j=0;j<10;j++)
fprintf(output,"%hu",passenger[i].phonenr[j]);
fprintf(output,"%s","\n");
}
}
fclose(output); /* Kleisimo arxeiou*/
printf("File Saved as Output.txt");
}
int main(void)
{
PASSENGERS passenger[53];
readfile(passenger);
do{
printf("\n\nNeo Sistima Katagrafis Thesewn Leoforeiou\n");
printf("Please make a selection:\n\n");
printf("0. Exit\n");
printf("1. Empty Seats \n");
printf("2. Book Specific Seat \n");
printf("3. Advanced Search of Booked Seats\n");
printf("4. Cancel Seat Booking\n");
printf("5. Show List of Booked Seats\n");
scanf(" %c",&selection);
if (selection=='1')
countfreeseats(passenger);
else if (selection=='2')
{
printf("Please give seat nr (between 1 and %d) that you want to book:\n", numberofseats);
scanf("%d",&temp);
if (temp >numberofseats || temp <= 0)
{printf("Error: Seat nr should be between 1 and %d", numberofseats);}
else if (strcmp(passenger[temp-1].fullname,"\0")!=0)
printf("Error: Seat is already booked");
else
changeData(&passenger[temp-1]);
}
else if (selection=='3')
{
char tempsel;
printf("Do you want to search with Name (1) or Phone Nr (2)?\n");
scanf(" %c",&tempsel);
searchpassenger(passenger,tempsel);
}
else if (selection=='4')
{
printf("Please give Seat Nr (between 1 and %d) that you want to Cancel Booking:\n", numberofseats);
scanf("%d",&temp);
if (temp >numberofseats || temp <= 0)
{printf("Error: Seat nr should be between 1 and %d", numberofseats);}
else if (strcmp(passenger[temp-1].fullname,"\0")==0)
printf("Error: Seat is already free");
else
cancelSeat(&passenger[temp-1]);
}
else if (selection=='5') /*Menu 6 - Emfanisi listas kratimenon thesewn taksinomimenon kata ayksonta arithmo*/
{
showList(passenger);
}
} while (selection!='0');
{
writeFile(passenger);
}
}

saving array to a file won't work, program crashes

I posted a few days ago already about a problem with my array-program. Well, it is basically a program which lets the user generate an array, safe a specific number in a specific slot, read the array or read a specific slots value. Now I am figuring out, how to let the user save the current array as a file.
this is what I got
void safeFile(){
FILE *f = fopen("list.txt", "a+");
putc(f , list);
fclose(f);
printf("File saved");
start();
}
where's the problem?
My Program crashes everytime I call the function safeFile() .
I played around, came with fputs instead of putc, program won't crash anymore, the file gets created but it's still blank
void safeFile(){
FILE *f = fopen("list.txt", "r+");
fputs(f , list);
fclose(f);
printf("File saved");
start();
}
here is my current full code
would be grateful for advices, im a newb
#include <stdio.h>
#include <stdlib.h>
int list[30];
int x = 0;
int i = 0; // variable used by for-Loop in setList
int j = 0; // variable used by for-Loop in getList
int input;
int option; //start Value
int gvinput; //getValue input
void start();
void getList();
int main()
{
start();
return 0;
}
void setList(int sizeOfList)
{
for (i = x; i <= sizeOfList; i++)
{
list[i] = i;
}
}
void getList(){
for(j = x; j < i ; j++ )
{
printf("At %d we got the value %d \n",j,list[j]);
}
}
void startList()
{
fflush(stdin);
printf("Please enter number between 0 and 30\n ");
scanf("%d",&input);
if(input > 30 || input == 0)
{
printf("The Number is not between 0 and 30\n");
startList();
}
setList(input);
getList();
fflush(stdin);
start();
}
void setValues(int l[])
{
fflush(stdin);
int v;
int loc;
printf("please enter what value you want to safe\n");
scanf("%d",&v);
fflush(stdin);
printf("Where do you want to save it?\n");
scanf("%d",&loc);
l[loc] = v;
printf("we got at slot %d the value %d\n\n",loc,l[loc]);
start();
}
void getValues(int getArray[]){
fflush(stdin);
printf("which slot do you want to read?\n");
scanf("%d",&gvinput);
fflush(stdin);
printf("The value is: %d \n\n",getArray[gvinput]);
start();
}
void safeFile(){
FILE *f = fopen("list.txt", "r+");
fputs(f , list);
fclose(f);
printf("File saved");
start();
}
void start(){
fflush(stdin);
printf("\n");
printf("[L] = generate Slots\n");
printf("[S] = set a Value at specific slot\n");
printf("[G] = get a Value from a specific slot\n");
printf("[F] = safe File");
printf("[X] = exit\n");
option=getchar();
if(option == 'L' || option == 'l'){
startList();
}
if(option == 'S' ||option == 's'){
setValues(list);
}
if (option =='G' ||option == 'g'){
getValues(list);
}
if (option == 'X' || option == 'x'){
printf("Thank you");
}
if (option == 'f' || option == 'F'){
safeFile();
}
int putc( int ch, std::FILE* stream );
putc writes a single char, and you pass an array of ints to it. The same is true for fputs, which writes a null-terminated string. You'll really have to write some code that serializes your data structure to a sequence of bytes to be written to the file.
In your case, since you want to save a list of ints, you can do this with a loop, for example, that is, loop over your array and write each item to the file. You'll also need a function that writes an int (putc isn't good here, since it writes a char). Have a look at printf, if you'd like to stick with C-style IO, otherwise use streams.
If your using putc(), you should be passing char by char.
for(i=0;i<strlen(list);i++)
{
putc(f,list[i]);
}
The list is an array, if you pass the address it means whole array so putc won't work here.
int fputs(const char *s, FILE *stream);
The second argument to the fputs is the stream. Since u use int [10]. u can use fprintf to print to the file.
Also, fflush(stdin); is undefined behaviour
you need to use the loop, but it is not working because the parameters in the putc function are not in the correct order. Try this:
for(i=0;i<strlen(list);i++)
{
putc(list[i],f); //<---------- NOT putc(f,list[i]);
}
first the char and second the stream.
int putc ( int character, FILE * stream );

Writing in a binary file

My program scans names and birth years and stores them in an array of structures. Scanning from keyboard and printing in screen works fine, but I'm not sure whether printing in my binary file is correct because my program runs without errors and I can't check if the data has been printed correctly in the binary file.
My question is about whether the syntax of my "fwrite" functions is correct.
#include <stdio.h>
#define MAXNAME 50 //size of name
#define MAXPERSONS 2 //Max num of persons
typedef struct{
char name[MAXNAME];
int year;
}person_t;
int read_person(person_t[], int);//scans the person
int write_person(const person_t[], int, FILE*);//prints the persons in the screen and the bfile
int main()
{
FILE *pfile;
person_t v[3];
int iscan=0,iprint;
if((pfile=fopen("persons.bin","wb"))==NULL) printf("couldnt open<vehicles.txt>\n");
else{
while(iscan<MAXPERSONS){
read_person(&v[iscan],iscan+1);
iscan++;
}
for(iprint=0;iprint<iscan;iprint++)
write_person(&v[iprint],iprint+1,pfile);
}
fclose(pfile);
printf("\n\n");
return 0;
}
int read_person(person_t v[],int i)
{
printf("Person %d",i);
printf("\n\tName: ");
fflush(stdin);
gets(v->name);
printf("\n\tYear: ");
scanf("%d",&v->year);
}
int write_person(const person_t v[],int j, FILE *pfile)
{
//print in screen
printf("\nPerson %d",j);
printf("\n\tName: %s\n",v->name);
printf("\n\tYear: %d\n",v->year);
//print in the binary file
fwrite(v->name,sizeof(char),1,pfile);
fwrite(&v->year,sizeof(int),1,pfile);
}
This program reads from the bin file
#include<stdio.h>
#define MAXNAME 50 //size of name
#define MAXPERSONS 2 //Max num of persons
typedef struct{
char name[MAXNAME];
int year;
}person_t;
int read_person(person_t[], int, FILE*);
int write_person(const person_t[], int);
int main(){
FILE *pfile;
person_t v[3];
int iscan=0,iprint;
if((pfile=fopen("persons.bin","rb"))==NULL) printf("couldnt open<vehicles.txt>\n");
else{
while(iscan<MAXPERSONS){
read_person(&v[iscan],iscan+1,pfile);
iscan++;
}
for(iprint=0;iprint<iscan;iprint++)
write_person(&v[iprint],iprint+1);
}
fclose(pfile);
printf("\n\n");
return 0;
}
int read_person(person_t v[],int i, FILE *pfile){
//read from the binary file
fread(v->name, sizeof(v->name),1,pfile);
fread(&v->year,sizeof(v->year),1,pfile);
}
int write_person(const person_t v[],int j){
//print in screen
printf("\nPerson %d",j);
printf("\n\tName: %s\n",v->name);
printf("\n\tYear: %d\n",v->year);
}
Suggest changing fwite() to write the full size of person_t.
int write_person(const person_t v[], int j, FILE *pfile) {
//print in screen
printf("\nPerson %d",j);
printf("\n\tName: %s\n",v[j].name);
printf("\n\tYear: %d\n",v[j].year);
//print in the binary file
if (1 != fwrite(&v[j], sizeof(v[j]),1, pfile)) handle_error();
return 0;
}
int read_person(person_t v[], int i) {
printf("Person %d",i);
printf("\n\tName: ");
// don't do this fflush(stdin);
// consider scanf() gets(v.name);
// " %49[^\n]": space to consume leading whitespace, 49 (50 -1 ) limit input, [^\n] to read any text but \n
if (1 != scanf(" %49[\n]", v[i].name)) handle_error();
printf("\n\tYear: ");
if (1 != scanf("%d",&v[i].year)) handle_error();
return 0;
}
You might consider writing and reading the entire person_t struct.
int write_person(const person_t v[],int j, FILE *pfile)
{
//print in screen
printf("\nPerson %d",j);
printf("\n\tName: %s\n",v[j].name);
printf("\n\tYear: %d\n",v[j].year);
fwrite(&(v[j]),sizeof(person_t),1,pfile);
}
The general idea you are approaching is called 'serialization' or 'marshalling' (depending upon author). There are many ways serialize or marshall data, but some good approaches are JSON, UBJSON, MessagePack, and ProtocolBuffers, among others.

Resources