Sorting data on text file in C - c

I found this exercise where I had to create a data structures, read some inputs, store the inputs on the "appropriate" data structure and then print everything to a text file.
I am looking forward to adding a function to order the hotel list according to the stars number, so if an hotel has 5 stars, it will be at the top of the list. Is it possible to do that? Can I do that with arrays?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct inputs {
char nome[30];
char via[30];
char stars[30];
int num;
};
int main(void)
{
struct inputs inputs = {"", "", ""};
FILE *cfPtr; // cfPtr = clients.txt file pointer
// fopen opens file. Exit program if unable to create file
if ((cfPtr = fopen("clients.txt", "w")) == NULL) {
puts("File could not be opened");
}
else {
puts("Enter the account, name, and balance.");
puts("Enter EOF to end input.");
printf("%s", "? ");
//scanf("%[^\n]s%[^\n]s%[^\n]s", inputs.via, inputs.nome, inputs.stars);
fgets(inputs.nome, 30, stdin);
inputs.nome[strcspn(inputs.nome,"\n")] = '\0';
fgets(inputs.via, 30, stdin);
inputs.via[strcspn(inputs.via,"\n")] = '\0';
fgets(inputs.stars, 30, stdin);
inputs.stars[strcspn(inputs.stars,"\n")] = '\0';
inputs.num = strlen(inputs.stars);
//printf("%s%s%s", inputs.nome, inputs.via, inputs.stars);
// write account, name and balance into file with fprintf
while (!feof(stdin)) {
fprintf(cfPtr, "%s; %s; %s; %d\n", inputs.nome, inputs.via, inputs.stars, inputs.num);
/*scanf("%[^\n]s", inputs.via);
scanf("%[^\n]s", inputs.nome);
scanf("%[^\n]s", inputs.stars);*/
fgets(inputs.nome, 30, stdin);
inputs.nome[strcspn(inputs.nome,"\n")] = '\0';
fgets(inputs.via, 30, stdin);
inputs.via[strcspn(inputs.via,"\n")] = '\0';
fgets(inputs.stars, 30, stdin);
inputs.stars[strcspn(inputs.stars,"\n")] = '\0';
inputs.num = strlen(inputs.stars);
}
fclose(cfPtr); // fclose closes file
}
}

I would suggest creating a struct type to represent one hotel, and then create an array of instances of the struct type. For instance the type could be as follows.
struct Hotel {
uint8_t stars;
char name[HOTELNAMESIZE];
};
struct Hotel hotels[NRHOTELS];
Now you can implement a sort function that sorts the hotels array based on hotels[i].stars. Of course this is a very simple implementation that has a hardcoded HOTELNAMESIZE and NRHOTELS value, but could be a decent starting point.

Related

How do I create an array of a struct and save it to a binary file for later use?

I'm relatively new to programming and recently got an assignment to create a car register which can hold up to 10 cars.
When asked about the specifics of the car, the user should put in their name, age, car type, brand, license plate and owner.
I've created a structure of the information that is needed.
struct fordon{
char namn[MAX_SIZE];
char alder[MAX_SIZE];
char fordonstyp[MAX_SIZE];
char marke[MAX_SIZE];
char reg[MAX_SIZE];
char agare[MAX_SIZE];
};
typedef struct fordon fordon_t;
And here is how I've decided to fill in the information.
int main()
{
fordon_t banan;
int quit = 0;
while(quit == 0){
meny();
char val[VAL_SIZE];
fgets(val,VAL_SIZE, stdin);
int tal = atoi(val);
switch(tal){
case 0:
return 0;
break;
case 1:
printf("Namn: \n");
fgets(banan.namn, sizeof(banan.namn), stdin);
printf("Ålder: \n");
fgets(banan.alder, sizeof(banan.alder), stdin);
printf("Typ av fordon: \n");
fgets(banan.fordonstyp, sizeof(banan.fordonstyp), stdin);
printf("Bilmärke: \n");
fgets(banan.marke, sizeof(banan.marke), stdin);
printf("REG-nummer: \n");
fgets(banan.reg, sizeof(banan.reg), stdin);
printf("Ägare: \n");
fgets(banan.agare, sizeof(banan.agare), stdin);
laggtill(&banan);
break;
However, the information doesn't exactly get saved in a binary file as I had hoped. Also I'm not sure if the code saves the user input into an array starting at index 0.
Down below is the code to save the information of the car into a binary file.
void laggtill(fordon_t *banan){
FILE *fp = NULL;
fp = fopen("register.dat", "wb");
if(fp == NULL){
puts("Filen kunde inte läsas\n");
}
else{
fwrite(&banan,sizeof(fordon_t), 1, fp);
}
fclose(fp);
}
I've tried changing some variables like for example:
void laggtill(fordon_t *banan){
FILE *fp = NULL;
fp = fopen("register.dat", "wb");
if(fp == NULL){
puts("Filen kunde inte läsas\n");
}
else{
fordon_t bil_vec[SIZE+1];
for(int i = 0; i < SIZE; i++){
fwrite(&bil_vec[i],sizeof(fordon_t), 1, fp);
}
}
fclose(fp);
}

Cannot write/read string separated by coma into a file

I'm trying to write a set of parameters of a structure into a file, and then read it in the program. The structure has a int type variable and a string type variable(this string is separated by space). I've successfully written and then read the integer part of the structure, but when i try to do the same for the string, the program crashes. I think it has something to do with my the fprintf statement, and trying to read a string separated by space.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main(void) {
// creating a FILE variable
FILE *fptr;
// integer variable
int i = 0;
char n[50];
// character variable
struct cliente {
char nome[50];
int nif;
};
struct cliente client[0];
// open the file in write mode
fptr = fopen("student", "w");
if (fptr != NULL) {
printf("File created successfully!\n");
}
else {
printf("Failed to create the file.\n");
// exit status for OS that an error occured
return -1;
}
// get student detail
printf("Enter student name: ");
scanf(" %[^\t\n]c", client[1].nome);
printf("Enter student ID: ");
scanf("%d", &client[1].nif);
// write data in file
fprintf(fptr, "%d %s", client[1].nif, &client[1].nome);
// close connection
fclose(fptr);
// open file for reading
fptr = fopen("student", "r");
// display detail
printf("\Ficheiro:\n");
fscanf(fptr, "%d %s", &i, n);
printf("ID: %d\n", i);
printf(" %s", n);
// close connection
fclose(fptr);
return 0;
}
You are declaring an array of zero length (struct cliente client[0]) but referencing the second element in the array (client[1]). That could cause a crash.

search string from file and store it in struct using c

i have a structure like so:
struct profile {
char firstName[15], lastName[15];
int age, phoneNo;
};
and i've written a code to store the text data from this structure into a text file, like so:
int main()
{
FILE* fPtr;
fPtr = fopen("profile.txt", "a");
printf("\n\nPlease enter your details:");
struct profile c;
printf("\n\nEnter your first name: ");
gets(c.firstName);
printf("\nEnter your last name: ");
gets(c.lastName);
printf("\nEnter your age: ");
scanf("%d", &c.age);
printf("Enter your phone number: ");
scanf("%d", &c.phoneNo);
fprintf(fPtr, "%s#%s#%dy#%d#\n", c.firstName, c.lastName, c.age, c.phoneNo);
fclose(fPtr);
return 0;
}
the code above will store the data input into the struct into a text file of strings, each string is one profile, and each value is separated by a '#', like below:
John#Doe#35y#0123456789#
Mary Ann#Brown#20y#034352421#
Nicholas#McDonald#15y#0987654321#
i'd like to know if there's a way i can search for a certain name/age/phoneNo from the text file, select the entire string of the corresponding profile and put each value back into a structure as above so that i can display it? i've separate each value with a '#' so that the program can use the # to differentiate between each value when it reads from the file but i'm not sure how i can separate it when i read the data. should i use fgets ? i'm new to C so i'd appreciate it if someone could explain it me how.
This is not exactly what you are looking for , but it helps you start using fgets and how to search for entries(only strings now).
#include <stdio.h>
#include <string.h>
#define MYFILE "profile.txt"
#define BUFFER_SIZE 50
int main()
{
char nametoSearch[BUFFER_SIZE];
char Names[BUFFER_SIZE];
FILE* fPtr;
if (fPtr = fopen(MYFILE, "r"))
{
// flag to check whether record found or not
int fountRecord = 0;
printf("Enter name to search : ");
//use fgets if you are reading input with spaces like John Doe
fgets(nametoSearch, BUFFER_SIZE, stdin);
//remove the '\n' at the end of string
nametoSearch[strlen(nametoSearch)-1] = '\0';
while (fgets(Names, BUFFER_SIZE, fPtr))
{
// strstr returns start address of substring in case if present
if(strstr(Names,nametoSearch))
{
printf("%s\n", Names);
fountRecord = 1;
}
}
if ( !fountRecord )
printf("%s cannot be found\n",nametoSearch);
fclose(fPtr);
}
else
{
printf("file %s cannot be opened\n", MYFILE );
}
return 0;
}

How to edit data of a file File Handling C

I'm wondering if I could use fseek() on editing the value of a variable on a file. All the tutorials I saw online were about editing a text, but how can I use fseek() to edit a value.
Here's how my program works: The user inputs a name, gender, and age. The user can input as many data as they want. Now, the user searches a name; and the gender, and age of that name will display. The user is then prompted to edit the age. After inputting a new age, the file will now be edited, with the new age written.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct data
{
char name[30];
char gender[10];
int age;
};
int main(void)
{
struct data client;
FILE* fp;
char ch = 0;
do
{
printf("Enter Name: ");
scanf("%s", client.name);
printf("Enter Gender: ");
scanf("%s", client.gender);
printf("Enter Age: ");
scanf("%d", &client.age);
fp = fopen("data.txt", "ab");
fwrite(&client, sizeof(client), 1, fp);
fclose(fp);
printf("continue? \n");
scanf(" %c", &ch);
} while (ch != 'n'); // continuously appends file till letter n is read;
char input[30]; // user input
printf("name?\n");
scanf("%s", input);
struct data Read;
fp = fopen("data.txt", "rb");
int newAge;
while (fread(&client, sizeof(client), 1, fp))
{
if (strcmp(client.name, input) == 0) // compare variable with user input
{
printf("%s", client.name);
printf(" %s", client.gender);
printf(" %d y/o", client.age);
printf("\n");
printf("enter new age");
scanf("%d", &newAge);
//fseek function
}
}
return 0;
}
Hope somebody can help.

fgets - crashes in visual studio, works in gcc

I'm working on something small and I have run into a really small but disturbing problem - the program works in gcc, but crashes in visual studio, when it gets to the fgets command:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void registerUser(char *username);
char path[256] = "C:\\Users\\magshimim\\Desktop\\cproject\\bank\\";
int main() {
int choice = 0;
char username[10];
printf("Welcome to nikitosik's bank program!\n"
"Choose an option :\n"
"0 - Register\n"
"1 - Login to existing account\n");
scanf("%d", &choice);
getchar(); // catch enter
if (!choice) {
registerUser(username);
} else {
//login();
}
}
void registerUser(char *username) { // username is passed, for verification later
FILE *userinfo; // file that contains info of all registered users
FILE *userpathf; // file to open for txt file
char usertxt[256]; // path of data
char userpath[256]; // path of new user data file
char password[15];
strcat(userpath, path);
strcat(usertxt, path);
strcat(usertxt, "users.txt");
userinfo = fopen(usertxt, "a");
printf("Choose a username(max 10 letters): ");
fgets(username, 10, stdin);
username[strcspn(username, "\n")] = 0;
strcat(userpath, username);
strcat(userpath, ".txt");
userpathf = fopen(userpath, "w");
fclose(userpathf);
printf("Choose a password(max 15 letters): ");
fgets(password, 15, stdin);
fprintf(userinfo, "%s\n%s", username, password);
fclose(userinfo);
}
thanks in advance
As above really or initialize the strings first.
memset(userpath, 0, sizeof(userpath));
memset(usertxt, 0, sizeof(usertxt));
Your program has multiple issues:
you concatenate a string into an uninitialized array: this has undefined behavior and may well explain the observed behavior on different systems as undefined behavior may take multiple forms from no consequence at all to a crash or possibly even worse misfortune.
you do not test the return values of scanf, fopen, fgets(). Any invalid or unexpected input may trigger more undefined behavior.
you do not check for potential buffer overflow in strcat(). You should instead use snprintf().
Here is a safer version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int registerUser(char *username, size_t size);
char path[] = "C:\\Users\\magshimim\\Desktop\\cproject\\bank\\";
int main(void) {
int choice = 0;
int c;
char username[10];
printf("Welcome to nikitosik's bank program!\n"
"Choose an option :\n"
"0 - Register\n"
"1 - Login to existing account\n");
if (scanf("%d", &choice) != 1)
return 1;
// consume the rest if the input line
while ((c = getchar()) != EOF && c != '\n')
continue;
if (choice == 0) {
registerUser(username, sizeof(username));
} else {
//login();
}
return 0;
}
int registerUser(char *username, size_t size) { // username is passed, for verification later
char usertxt[256]; // path of data
char userpath[256]; // path of new user data file
char password[17];
FILE *userinfo; // file that contains info of all registered users
FILE *userpathf; // file to open for txt file
printf("Choose a username(max %d letters): ", (int)(size - 2));
if (!fgets(username, size, stdin))
return -1;
username[strcspn(username, "\n")] = 0; // strip newline if any
printf("Choose a password(max 15 letters): ");
if (!fgets(password, sizeof(password), stdin))
return -1;
password[strcspn(password, "\n")] = 0; // strip newline if any
if (snprintf(usertxt, sizeof(usertxt), "%s%s", path, "users.txt") >= (int)sizeof(usertxt))
return -1;
if (snprintf(userpath, sizeof(userpath), "%s%s.txt", path, username) >= (int)sizeof(userpath))
return -1;
userinfo = fopen(usertxt, "a");
if (userinfo == NULL)
return -1;
// create user file
userpathf = fopen(userpath, "w");
if (userpathf != NULL)
fclose(userpathf);
// add user info
fprintf(userinfo, "%s\n%s\n", username, password);
fclose(userinfo);
return 0;
}

Resources