Search for a record on a binary file - c

I'm trying to find if a record exists on a binary file by searching for a name.
Seems I'm not doing something right since the return of my "if" no matter the input it's always found when it doesn't exist.
The debugger states "if = A syntax error in expression", I'm not seeing it.
#ifndef DATA_PLAYER_H_INCLUDED
#define DATA_PLAYER_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Player
{
char nome[50];
int pontos;
}Players;
void ViewPont();
void SearchPont();
#endif // DATA_PLAYER_H_INCLUDED
--
#include "DATA_PLAYER.h"
void ViewPont()
{
Players pl;
FILE *fp;
int i, pontos;
fp = fopen("Pontuacoes.dat", "rb+");
while((fread(&pl, sizeof(Players),1, fp)) != 0 )
{
printf("%s %d\n", pl.nome, pl.pontos);
}
fclose(fp);
}
void SearchPont()
{
char nam[50];
char ch;
Players pl;
FILE * fp;
fp = fopen("Pontuacoes.dat","rb+");
printf("\n nome das pont\n");
fflush(stdout);
scanf("%s", nam);
printf("%s", nam);
while((fread(&pl, sizeof(Players),1, fp)) != 0)
{
if((strcmp(pl.nome, nam))==0);
{
printf("\nregisto encontrado\n");
}
}
fclose(fp);
}

Silly me..........
if(strcmp(pl.nome, nam) ==0);
-> ; that little detail....
if(strcmp(pl.nome, nam) ==0)

Related

C: Newbie attemping file reading and struct allocation using malloc

I am trying to store the values stored in a details.txt file into their appropriate place in a dynamically allocated struct. Am I doing something (that should be simple) incorrectly for this not to work? Is it necessary for me to use strtok and split by ','?
My details.txt reads:
mitch,8,1.78,burgers
murray,42,6.5,lasagna
travis,64,1.85,sushi
sam,12,1.94,bacon
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFERSIZE 256
typedef struct
{
char name[BUFFERSIZE];
int favnumber;
float height;
char favfood[BUFFERSIZE];
} Person;
void print_person(Person *p)
{
printf("name: %s\n", p->name);
printf("num: %d\nheight: %.2f\nfav. food: %s\n\n",
p->favnumber, p->height, p->favfood);
}
int count_lines(FILE *fp)
{
int nlines = 0;
char c;
for (c = fgetc(fp); c != EOF; c = fgetc(fp))
{
if (c == '\n')
{
nlines++;
}
}
rewind(fp);
return nlines;
}
int main(void)
{
FILE *fp = fopen("details.txt", "r");
// count lines
int nlines = count_lines(fp);
printf("found %d lines\n\n",nlines);
Person *people = (Person*)malloc(nlines*sizeof(Person));
char buffer[BUFFERSIZE];
int i = 0;
while (fgets(buffer,BUFFERSIZE,fp) != NULL)
{
sscanf(buffer,"%s%d%f%s",people[i].name,
&(people[i].favnumber),
&(people[i].height),people[i].favfood);
print_person(&(people[i]));
i++;
}
printf("found %d people\n",i);
free(people);
fclose(fp);
}
Unfortunately, the current output of my program is:
found 4 lines
name: mitch,8,1.78,burgers
num: 0
height: 0.00
fav. food:
...
found 4 people
The problem is that the first %s parse the the whole line, and you need , in the format string to separate the fields. Not an issue here yet but I also used %[^,] for the last format string so it will not stop at the first space. Also added precision on the strings to avoid buffer overflows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFERSIZE 255
#define str(s) str2(s)
#define str2(s) #s
typedef struct
{
char name[BUFFERSIZE+1];
int favnumber;
float height;
char favfood[BUFFERSIZE+1];
} Person;
void print_person(Person *p)
{
printf("name: %s\n", p->name);
printf("num: %d\nheight: %.2f\nfav. food: %s\n\n",
p->favnumber, p->height, p->favfood);
}
int count_lines(FILE *fp)
{
int nlines = 0;
char c;
for (c = fgetc(fp); c != EOF; c = fgetc(fp))
{
if (c == '\n') {
nlines++;
}
}
rewind(fp);
return nlines;
}
int main(void)
{
FILE *fp = fopen("details.txt", "r");
// count lines
int nlines = count_lines(fp);
printf("found %d lines\n\n",nlines);
Person *people = (Person*)malloc(nlines*sizeof(Person));
char buffer[BUFFERSIZE+1];
int i = 0;
while (fgets(buffer,BUFFERSIZE+1,fp) != NULL)
{
// Changed line, see formatting of %s
sscanf(buffer,
"%" str(BUFFERSIZE) "[^,],%d,%f,%" str(BUFFERSSIZE) "[^,]",
people[i].name,
&(people[i].favnumber),
&(people[i].height),people[i].favfood);
print_person(&(people[i]));
i++;
}
printf("found %d people\n",i);
free(people);
fclose(fp);
}

How to read comma-separated csv file with `sscanf()`

I'm attempting to print an array of structures read from a CSV file in Excel. However, only the students' IDs are printed; other information was also printed but some confusing rare characters. Can you please tell me what could be wrong with this code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char ID[8];
char name[32];
int score;
} student;
int main(int argc, char *argv[]) {
student student_list[100];
FILE *source = fopen("students.csv", "r");
if (source == NULL) {
perror("Unable to open the source file.");
exit(1);
}
char buffer[1024];
fgets(buffer, sizeof(buffer), source);
int num_student = 0;
while (!feof(source)) {
student *one_student = student_list + num_student;
sscanf(buffer, "%8[^,] %32[^,] %3[^,]",
&one_student->ID, &one_student->name, &one_student->score);
fgets(buffer, sizeof(buffer), source);
num_student++;
}
for (int i = 0; i < num_student; i++) {
printf("ID: %s name: %-9s score: %-3d\n",
student_list[i].ID, student_list[i].name, student_list[i].score);
}
fclose(source);
return 0;
}
This is a sample input file students.csv:
B213350,John Adam Smith,80
B191835,Mary Elizabeth Smith,71
B201304,Yamazaki Fuyumi,95
B201832,Liam,57
B201834,Alfonso Hernández,65
There are multiple problems:
you should not use feof(). Read Why is “while ( !feof (file) )” always wrong?
Use this loop instead:
while (fgets(buffer, sizeof buffer, source)) {
// handle the line
}
the sscanf() format string is incorrect: the character counts are too large and the , are missing. It should be " %7[^,\n], %31[^,\n], %d" and you should check that the return value is 3, the number of successful conversions expected.
you should stop when the student array is full.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char ID[8];
char name[32];
int score;
} student;
int main(int argc, char *argv[]) {
student student_list[100];
FILE *source = fopen("students.csv", "r");
if (source == NULL) {
fprintf(stderr, "Cannot open file students.csv: %s\n", strerror(errno));
return 1;
}
char buffer[1024];
int num_student = 0;
while (num_student < 100 && fgets(buffer, sizeof(buffer), source)) {
student *one_student = &student_list[num_student];
if (sscanf(buffer, " %7[^,\n], %31[^,\n], %d",
one_student->ID, one_student->name,
&one_student->score) == 3) {
num_student++;
} else {
printf("invalid CSV line: %s", buffer);
}
}
for (int i = 0; i < num_student; i++) {
printf("ID: %-9s name: %-32s score: %-3d\n",
student_list[i].ID, student_list[i].name,
student_list[i].score);
}
fclose(source);
return 0;
}
Note that this approach to parsing CSV files cannot handle empty fields. Parsing the line with strtok() would not work either because consecutive commas would be handled as a single separator. You need a different approach using strcspn() or strchr().

C - Reading strings from text file into arrays inside a structure

I am trying to read text from a .txt file into arrays of a structure.
This is my code (I have played around with this a heap so apologies if it seems all over the place):
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
int main()
{
int i = 1;
int j = 0;
char temp[4];
struct userStruct { // a struct definition for the users;
char pin[5];
char first[26];
char last[26];
};
struct userStruct userList[10]; // an array of struct user to hold 10 users
struct userStruct * users;
users = &userList;
FILE * filePtr;
filePtr = fopen ("users.txt", "r");
if (filePtr != NULL)
{
fscanf(filePtr, "%s %s %s %s", users[i].pin[j], users[i].first[j], users[i].last[j], temp);
if (strcmp(temp, "\n"))
{
i++;
j++;
}
printf("PIN %s| First %s| Last %s|", users[i].pin[j], users[i].first[j], users[i].last[j]);
fclose(filePtr);
}
else
{
printf("Unable to open users.txt");
}
return 0;
}
The users.txt file contains the text:
1234 John Smith
5678 Barry Cool
Many thanks for the help.
You only want 3 conversion specifiers in the scanf. Try
if( 3 == fscanf(filePtr, "%4s %25s %25s", users[i].pin, users[i].first, users[i].last) ){ ...
The printf is also weird. Try:
printf("PIN %s| First %s| Last %s|", users[i].pin, users[i].first, users[i].last);

How to read, modify structs from a non-text file?

I want to save some struct into a file and read all of them or modify them. I tried like this, but this way I got only the last saved structs, and I don't know how to get all of them, or how to modify them later in the file.
I don't get any error just the last saved structs, but in the file I see all of them if I open with a text editor.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#define MAX_STRING_LEN 80
#define PHONE_NUMBER 15
struct order {
time_t systime;
char name[MAX_STRING_LEN];
char email[MAX_STRING_LEN];
int phonenumber;
int size;
};
//functions
void saveToFiles(struct order *current);
void dbList(struct order *current);
//save into file
void saveToFiles(struct order *current) {
FILE * file=fopen("db.txt", "a");
if(file != NULL) {
fwrite(current, sizeof(struct order), 1, file);
// fwrite("\n", sizeof("\n"), 1, file); //If I broke the line then all of the reading get some numbers, without any meaning
fclose(file);
}
}
//list the db
void dbList(struct order *current) {
int option;
printf("list: \n 1 - ful list\n 2 - just names\n 3 - just size\n 0 - exit");
scanf(" %i", &option);
if(option == 0) {
exit(1);
}
if(option == 1) {
//loadList(1);
struct order *obj=malloc(sizeof(struct order));
FILE * file = fopen("db.txt","rb");
fseek(file, 0, SEEK_SET); //I tried to put the file read at the begining of the file
while(fread(obj, sizeof(struct order), 1, file)) {
printf("LOG: op1\n");
fread(obj, sizeof(struct order), 1, file);
printf("%s/%s/%d/%d\n", obj->name, obj->email, obj->phonenumber, obj->size);
}
if(feof(file)) {
printf("\n--END--\n");
}
else {
printf("Some error...");
}
}
}
//***
int main(k)
{
struct order current; //struct init
// current = malloc(sizof(*current));
int option = 1;
while(option != 0) {
printf(" " "\x1B[34m");
printf("0 exit \n 1 new \n 2 list \n \n " "\x1B[0m");
scanf(" %i", &option);
if(option == 1) {
getNewOrder(&current);
}
if(option == 2) {
dbList(&current);
}
}
return 0;
}
For write file, pls check if fseek() to SEEK_END and then do fwrite can help.

how should I use qsort for pointers to sort by first character of it in c

/* problem of qsorting
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUT "doc.txt"
#define OUTPUT "output.txt"
#define MAX_SIZE 500
typedef struct student // here I declare stuctures
{
char name[20];
int index;
int code;
int grade;
char surname[20];
} student;
int cmpfunc (const void * a, const void * b) // initial part of qsort
{
return ( *(char*)a - *(int*)b );
}
int main()
{
int i=0, m=0;
int number=0;
FILE *fo;
FILE *fi;
char file[]={INPUT};
char file1[]={OUTPUT};
fo = fopen(file, "r"); // open the file
fi = fopen(file1, "w"); // open the file
student *studentPtr;
studentPtr = (student*) malloc(MAX_SIZE*sizeof(student));
// here I use mallocation
if(fo == NULL || studentPtr == NULL || fi == NULL)
{
perror("Error");
exit(1);
}
while (!feof(fo)) // reading of file
{
fscanf(fo,"%d %s %s %d %d",
&studentPtr[i].index,
studentPtr[i].name,
studentPtr[i].surname,
&studentPtr[i].code,
&studentPtr[i].grade);
i++;
}
i=m;
printf("please insert a number upto 7:\n");
// because there are only 7 raws in the file
scanf("%d",&number);
m=number;
if (number > 7)
{
printf("try again");
}
else
{
for(i=0;i<m;i++)
{
qsort(studentPtr[i].surname, 1, sizeof(char), cmpfunc); // ?
printf("%d %s %s %d %d\n", // printing out
studentPtr[i].index,
studentPtr[i].name,
studentPtr[i].surname,
studentPtr[i].code,
studentPtr[i].grade);
fprintf(fi,"%d %s %s %d %d\n", // writing in the file
studentPtr[i].index,
studentPtr[i].name,
studentPtr[i].surname,
studentPtr[i].code,
studentPtr[i].grade);
}
}
free(studentPtr);
fclose(fo);
fclose(fi);
return 0;
}
I am just beginner and sorry for obvious mistakes.
I cannot do qsorting properly.
i will attach txt file as a comment of this post.
could you guys tell me how to change first part of qsort not to get silly things, after that i will try to do that by myself

Resources