I get a segfault when I add (int filter) in the struct. Is it possible to fix?
Error message: zsh: segmentation fault
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct Student {
char name[30];
char surname[30];
int course; // year of study
double average; // average grade
int load; // number of courses
char courses[10][30]; // course names
int grades[10]; // course grades
char languages[100]; // spoken languages
int negative;
// int filter;
} Student;
int main(int argc, char *argv[]) {
FILE *db = NULL;
// open database file for reading, provide a parameter or use default "db.bin"
if (argc > 1)
db = fopen(argv[1], "rb");
else
db = fopen("db.bin", "rb");
if (db){
Student students[1000]; // all the data goes here
int size = 0; // how many students in database
// reading data from file
fread(&size, sizeof(int), 1, db);
for (int i = 0; i < size; i++){
fread(&students[i], sizeof(Student), 1, db);
}
printf("%d records loaded succesfully\n", size);
// MODIFY CODE BELOW
int counterDemo = 0; // for counting students
for (int i = 0; i < size; ++i){ // process all the student records in database
Student s = students[i]; // store data for each student in s
s.negative = 0;
// Checking if student has Philosophy and passed Philosophy exam
for(int j = 0; j < s.load; ++j)
{
if(!strcmp(s.courses[j], "Philosophy"))
{
s.negative++;
}
}
bool philosophy_exam = false;
if(s.negative != 0) // If student has Philosophy and passed Philosophy exam
{
philosophy_exam = true;
}
if(philosophy_exam){ // *** first filter, conditions on the student
int anotherDemo = 0; // for counting courses/grades
printf("%s %s %d %.2f %d ", s.name, s.surname, s.course, s.average, s.load); // print student data
for (int i = 0; i < s.load; ++i){ // process each course taken by the student
if(1){ // *** second filter, conditions on the course/grade
++anotherDemo; // counting courses
printf("%s %d ", s.courses[i], s.grades[i]);
}
}
printf("%s\n", s.languages);
if (anotherDemo == s.load) // *** third filter, various other conditions
++counterDemo; // counting studfents
}
}
printf("Filter applied, %d students found\n", counterDemo); // how many passed the filters
fclose(db);
} else {
printf("File db.bin not found, check current folder\n");
}
return 0;
}
I commented the problematic variable out.
Also I run my code on terminal, like always. I am using (clang "file" -o main) could this be the problem? I have tried to run this code in different apps, but it doesn't help.
Related
The function used here is working but as i am sending each threads to do this job the threads are overdoing or doing noofthreads time because of the for loops used for them when creating. I am out of logic here what can i do so that after succesfully loading and checking the 1159999 values from multiple text files i want to store them in seperate text file.
`
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
pthread_mutex_t lck;
typedef struct{
int start;
int end;
}Innerstruct;`
struct data{
FILE **fptr;
Innerstruct *inner;
int numberthreads;
int totalno;
};
int primecount=0;//to store prime numbers count
int nofiles=3;
void countlines(int *count,FILE **fptr,int nofiles){ //counts the no of lines of cordinates from the text file
int i;
*count = 0;
for(i=0;i<nofiles;i++){
fseek(fptr[i], 0, SEEK_SET);
char line[256]; // buffer to store each line
while(fgets(line, sizeof(line), fptr[i])){
if(strlen(line) > 1){ // only increment if line is not empty so that this doesn't count blank spaces (*count)++;
}
}
}
}
void *getstorecountprime(void *p){
FILE *fptr4;
fptr4 = fopen("PrimeNumber.txt","w");
if(fptr4==NULL){
printf("Error creating file");
}
struct data *d1 = p;
int i,j,k,num,start,end;
for(k=0;k<d1->numberthreads;k++){
start= d1->inner[k].start;
end = d1->inner[k].end;
for(j=start;j<=end;j++){
for(i=0;i<nofiles;i++){
fseek(d1->fptr[i], j, SEEK_SET);
fscanf(d1->fptr[i],"%d",&num);
if(checkprime(num)){
pthread_mutex_lock(&lck);
fprintf(fptr4,"%d\n",num);
primecount++;
pthread_mutex_unlock(&lck);
}
}
}
}
}
void main(){
//checking for any error on opening the files
FILE *fptr1,*fptr2,*fptr3;
// opening text files
fptr1 = fopen("PrimeData1.txt","r");
fptr2 = fopen("PrimeData2.txt","r");
fptr3 = fopen("PrimeData3.txt","r");
if(fptr1==NULL || fptr2==NULL || fptr3==NULL){
printf("Could not open all files");
exit(1);
}
pthread_mutex_init(&lck,NULL);
FILE *fptr[] = {fptr1,fptr2,fptr3}; //array of file pointer
int num_threads,sliceperthread,*numarray;
int i;
int totalcount = 0;//to store total numbers
pthread_t *id;
struct data d1;
countlines(&totalcount,fptr,nofiles);//counts the no of lines from txt files
numarray = malloc(totalcount*sizeof(int));//dma to store all datas in array
printf("Enter how many threads do you want:");
scanf("%d",&num_threads);
id = malloc(num_threads*sizeof(pthread_t));//dma thread equal to the number of thread
d1.inner = malloc(num_threads*sizeof(Innerstruct));//dma the inner structure containing
start and end
d1.fptr = malloc(nofiles*sizeof(FILE*));//dma the fptr as array of nofiles size
sliceperthread = totalcount/num_threads;
d1.fptr=fptr;//assigned the fptr of structure to array of file pointer created above
d1.numberthreads=num_threads;\
d1.totalno = totalcount;
d1.inner[0].start = 0;
d1.inner[0].end = sliceperthread;
for(i=1;i<=num_threads;i++){
d1.inner[i].start = d1.inner[i-1].end + 1;
d1.inner[i].end = d1.inner[i-1].end + sliceperthread;
}
for(i=0;i<num_threads;i++){
pthread_create(&id[i],NULL,getstorecountprime,&d1);
pthread_join(id[i],NULL);
}
printf("%d",primecount);
}
int checkprime(int n){
int i;
for(i=2;i<=n/2;i++){
if(n%i == 0){
return 0;
}else{
return 1;
}
}
}``
As you can see from the code that i tried using a nested structure for this process. I created a structure which will store file pointers array and another inner structure array having start and end so that this could be used for threads start and end point. So i used a for loop to create threads and assign them function sending the structure as parameter. I was expecting to get prime numbers in text file but because of the iteration the program just keeps on adding values to the file.
At least these problems:
No increment
(*count)++; is lost in a comment. #M Oehm
if(strlen(line) > 1){ // only increment if line is not empty so that this doesn't count blank spaces (*count)++;
}
Wrong checkprime(int n)
Hopefully with uniform formatting it is easy to see the loop only iterates, at most, once and fails to return a value when i < 2.
int checkprime(int n) {
int i;
for (i = 2; i <= n / 2; i++) {
if (n % i == 0) {
return 0;
} else {
return 1;
}
}
}
Save time, auto format code and enable all compiler warnings to rapidly identify various code problems.
a must be simple question but I couldn't manage to do it.
I have to scan on a struct a text file with entries in this format:
{"data1","data2",number1,number2}
And compute first populating a struct.
Text of the exercise:
Consider the definition of the following structure
typedef struct {
char teamHome [30];
char teamHost [30];
int goalSquadraHome;
int goalSquadraOspite;
} match;
which is used to represent the result of a football match.
Write a function that takes as parameters an array of games and its size e
returns a result structure containing the following information:
the number of games won by the home team,
the number of games won by the visiting team,
the number of ties,
the name of the team that has scored the most goals in a match.
Then write a program that, given the array containing all 380 Serie A 2019/2020 matches,
print the information contained in the result.
The code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char squadraCasa[30];
char squadraOspite[30];
int golSquadraCasa;
int golSquadraOspite;
} partita;
typedef struct {
int partite_casa;
int partite_ospite;
int pareggi;
char squad_magg_num_goal[30];
} risultato;
int main(){
FILE *fp;
risultato risultati;
int maxgoal = 0;
risultati.partite_casa = 0;
risultati.partite_ospite = 0;
risultati.pareggi = 0;
partita partite[380];
int i=0;
if((fp = fopen("partiteSerieA1920.txt","rt"))==NULL){
printf("Errore nell'apertura del file\n");
exit(1);
}
while(!feof(fp)){
fscanf(fp,"{\"%s\",\"%s\",%d,%d",partite[i].squadraCasa,partite[i].squadraOspite,partite[i].golSquadraCasa,partite[i].golSquadraOspite);
i++;
}
for(i=0;i<380;i++){
if(partite[i].golSquadraCasa>partite[i].golSquadraOspite){
risultati.partite_casa++;
}else if(partite[i].golSquadraCasa<partite[i].golSquadraOspite){
risultati.partite_ospite++;
}else
risultati.pareggi++;
if(partite[i].golSquadraCasa>maxgoal){
strncpy(partite[i].squadraCasa,risultati.squad_magg_num_goal,30);
maxgoal = partite[i].golSquadraCasa;
}
if(partite[i].golSquadraOspite>maxgoal){
strncpy(partite[i].squadraOspite, risultati.squad_magg_num_goal,30);
maxgoal = partite[i].golSquadraOspite;
}
}
fclose(fp);
printf("%d %d %d %s\n",risultati.partite_casa,risultati.partite_ospite,&risultati.pareggi,&risultati.squad_magg_num_goal);
return 0;
}
Please let me know how to arrange it properly.
There may be other issues, but certainly your flow control is wrong. Instead of the incorrect while/feof loop(Why is “while ( !feof (file) )” always wrong?), try something like:
partita *p = partite;
while( 4 == fscanf(fp, "{\"%29s\",\"%29s\",%d,%d",
p->squadraCasa,
p->squadraOspite,
&p->golSquadraCasa,
&p->golSquadraOspite
) ){
p++;
}
Give this a try, its a bit of a different approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char squadraCasa[30];
char squadraOspite[30];
int golSquadraCasa;
int golSquadraOspite;
} partita;
typedef struct
{
int partite_casa;
int partite_ospite;
int pareggi;
char squad_magg_num_goal[30];
} risultato;
// solves given problem and stores results in risultato struct
risultato *getResult(partita **playedGames, int size)
{
risultato *result = malloc(sizeof(risultato));
result->partite_casa = 0;
result->partite_ospite = 0;
result->pareggi = 0;
int currentHighest = 0;
for (int i = 0; i < size; i++)
{
if (playedGames[i]->golSquadraCasa > playedGames[i]->golSquadraOspite){
result->partite_casa++;
if(playedGames[i]->golSquadraCasa > currentHighest ){
currentHighest = playedGames[i]->golSquadraCasa;
strcpy(result->squad_magg_num_goal, playedGames[i]->squadraCasa);
}
}
else if (playedGames[i]->golSquadraCasa < playedGames[i]->golSquadraOspite){
result->partite_ospite++;
if (playedGames[i]->golSquadraOspite > currentHighest){
currentHighest = playedGames[i]->golSquadraOspite;
strcpy(result->squad_magg_num_goal, playedGames[i]->squadraOspite);
}
}
else{
result->pareggi++;
}
}
return result;
}
// This is a custom parser of a line from the file
// data = {"data1","data2",number1,number2}
// return -> partita struct
partita *newGame(char *data){
partita *partite = malloc(sizeof(partita));
char* temp;
// Get Home Team
temp = strchr(data, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraCasa, data + 2);
data = temp+1;
// Get Away Team
temp = strchr(data+1, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraOspite, data + 2);
data = temp + 1;
// Get Home Score
temp = strchr(data + 1, ',');
temp[0] = '\0';
partite->golSquadraCasa = atoi(data + 1);
data = temp + 1;
// Get Away Score
temp = strchr(data, '}');
temp[0] = '\0';
partite->golSquadraOspite = atoi(data);
// Return game
return partite;
}
int main()
{
FILE *fp;
partita **partite = malloc(sizeof(partita *)); // list of size one, currently...
risultato *risultati;
char linea[50];
int indice = 0;
if ((fp = fopen("./partiteSerieA1920.txt", "rt")) == NULL)
{
printf("Errore nell'apertura del file\n");
exit(1);
}
// For each linea in the file, load a game into an array.
while (fgets(linea, 50,fp))
{
//chomp the \n
linea[strlen(linea)-1]='\0';
// increase size of list
partite = realloc(partite, sizeof(partita *) * (indice + 1));
// insert game into array of games
partite[indice] = newGame(linea);
indice++;
}
risultati = getResult(partite, indice);
// Print risultato
printf("\n----RESULT----\nHome Wins: %d\nAway Wins: %d\nTies: %d\nTeam With Most Goals: %s\n\n", risultati->partite_casa, risultati->partite_ospite, risultati->pareggi, risultati->squad_magg_num_goal);
// free all allocated memory then return
for (int i = 0; i < indice;i++){
free(partite[i]);
}
free(partite);
free(risultati);
fclose(fp);
return 0;
}
I was trying to run your code but couldnt get it to parse data from the file properly so i made a quick parser for you (This is in the code above already):
partita *newGame(char *data){
partita *partite = malloc(sizeof(partita));
char* temp;
// Get Home Team
temp = strchr(data, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraCasa, data + 2);
data = temp+1;
// Get Away Team
temp = strchr(data+1, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraOspite, data + 2);
data = temp + 1;
// Get Home Score
temp = strchr(data + 1, ',');
temp[0] = '\0';
partite->golSquadraCasa = atoi(data + 1);
data = temp + 1;
// Get Away Score
temp = strchr(data, '}');
temp[0] = '\0';
partite->golSquadraOspite = atoi(data);
// Return game
return partite;
}
You can always try to use something similar to this to parse strings or lines that you bring in as I find it is more efficient to just code something that you know works to the specification you want.
Let me know if there is some problem with the code or would like to know more about the functionality of this. I tried to keep as much of this in Italian.
Cheers
I recently got an assignment to sort members in a struct by last name and if they are the same to sort by first name. What i have so far only reads their name and age from the file but I am not properly grapsing how I would be able to sort it. So far I gathered the data from the file but im at a loss from there. I followed a code I saw but i didnt get a proper grasping of the process so i reverted back to step one.
struct Members{
int id;
char fname[50];
char lname[50];
int age;
}bio;
int main(){
int i=0;
FILE *fptr;
file = fopen("Members Bio.txt", "r");
while ( fscanf(file, "%d%s%s%d", &bio[i].id,bio[i].fname,bio[i].lname,&bio[i].age) != EOF)
{
printf("%d %s %s %d %d\n", bio[i].id,bio[i].fname, bio[i].lname, bio[i].age);
i++;
}
fclose(fptr);
}
Can anyone help me out on this one?
Code goes something like this for your case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Members{
int id;
char fname[50];
char lname[50];
int age;
};
typedef int (*compare_func)(void*, void*);
int struct_cmp(void* s1, void* s2)
{
int l_result = strcmp(((struct Members*) s1)->lname, \
((struct Members*) s2)->lname);
if (l_result < 0)
return 1;
else if (l_result > 0)
return 0;
else
return (strcmp(((struct Members*) s1)->fname, \
((struct Members*) s2)->fname) < 0 ? 1 : 0);
}
void sort(void* arr,long ele_size,long start,long end,compare_func compare)
{
// Generic Recursive Quick Sort Algorithm
if (start < end)
{
/* Partitioning index */
void* x = arr+end*ele_size;
long i = (start - 1);
void* tmp=malloc(ele_size);
for (long j = start; j <= end - 1; j++)
{
if ((*compare)(arr+j*ele_size,x))
{
i++;
// Swap is done by copying memory areas
memcpy(tmp,arr+i*ele_size,ele_size);
memcpy(arr+i*ele_size,arr+j*ele_size,ele_size);
memcpy(arr+j*ele_size,tmp,ele_size);
}
}
memcpy(tmp,arr+(i+1)*ele_size,ele_size);
memcpy(arr+(i+1)*ele_size,arr+end*ele_size,ele_size);
memcpy(arr+end*ele_size,tmp,ele_size);
i= (i + 1);
sort(arr,ele_size,start, i - 1,compare);
sort(arr,ele_size,i + 1, end,compare);
}
}
int main()
{
FILE* fp;
int bio_max = 3;
struct Members bio[bio_max]; // Define bio to be large enough.
/* Open FILE and setup bio matrix */
/* For testing */
bio[0].id = 0;
strcpy(bio[0].fname, "");
strcpy(bio[0].lname, "Apple");
bio[0].age = 0;
bio[1].id = 1;
strcpy(bio[1].fname, "");
strcpy(bio[1].lname, "Cat");
bio[1].age = 1;
bio[2].id = 2;
strcpy(bio[2].fname, "");
strcpy(bio[2].lname, "Bat");
bio[2].age = 2;
/* Sort the structure */
sort(bio, sizeof(struct Members), 0, bio_max - 1, struct_cmp);
/* Print the sorted structure */
for (int i = 0; i < bio_max; i++) {
printf("%d %s %s %d\n", bio[i].id, bio[i].fname, \
bio[i].lname, bio[i].age);
}
}
Output
0 Apple 0
2 Bat 2
1 Cat 1
If the strings are not sorting in the way you want, you can redefine the struct_cmp function. Code is self explanatory, the base logic in the code is pass an array and swap elements using memcpy functions. You cant use simple assignment operator if you want to be generic, so that is why the element size is explicitly passed.
Edit
The code was not handling the condition, if lname are same. I missed it thanks for #4386427 for pointing this out.
I think you should define bio to be an array. And google sort algorithms please. Also recommend you google how to use libc function qsort.
I am new to programming and would like some help in for File in C.
This is my code
#include <stdio.h>
#include <string.h>
void read_file();
void write_fil();
void add();
void display();
void search();
#define NAME_CHRS 30
struct employee_rec
{ char name[NAME_CHRS];
int dependents;
float pay_rate;
};
struct employee_rec employee;
struct employee_rec emp_array[];
FILE *employ;
int count=-1;
void read_file(void)
{
int idx;
employ = fopen("EMPLOYEE.DAT", "a+");//i add
//for (idx=0; idx <= count; idx++)
fread(&emp_array[idx], sizeof emp_array[idx], 1, employ);
fclose(employ);
}
void write_file()
{
int x;
employ = fopen("EMPLOYEE.DAT", "a+");
for (x=0; x <= count; x++)
fwrite(&emp_array[x], sizeof emp_array[x], 1, employ);
fclose(employ);
}
void add()
{
count+=1;
printf("Enter name: ");
scanf("%s", emp_array[count].name);
printf("Pay rate, other dependents: ");
scanf("%f %i", &emp_array[count].pay_rate, &emp_array[count].dependents);
}
void display()
{
int idx;
read_file();
printf("Name\t\tPay Rate\tDependents\n");
printf("----\t\t--------\t----------\n");
for (idx=0; idx <= count; idx++)
{
printf("%-10s\t%-8g\t%-8d\n", emp_array[idx].name, emp_array[idx].pay_rate, emp_array[idx].dependents);
}
}
void search()
{
char target[20];
int idx, found=0;
printf("Enter a name to search: ");
scanf("%s", target);
for (idx=0; idx <= count; idx++){
if(strcmp(emp_array[idx].name, target) == 0)
{
found = 1;
break;
}
}
if(found == 1)
{
printf("Name: %s\n", emp_array[idx].name);
printf("Pay rate: %g\n", emp_array[idx].pay_rate);
printf("Dependents: %d\n", emp_array[idx].dependents);
}
else
printf("Not found!\n");
}
int main(void)
{
int i;
//for (i=0; i < 3; i++)
// add();
// write_file();
display();
search();
return 0;
}
The original program would ask the user to key in data and then display it for the user.
So when another user runs the program and has the file it doesnt need to add more data but just read from the file
I have commented the for loop, display and search in my main because i just want to retrieve the data from my file.
Im not sure what to do with
fread(&emp_array[idx], sizeof emp_array[idx], 1, employ);
fclose(employ);
Since right now im using the counter from the insert to get the size, it will say size is 0 as the current run did not enter the data into the file (file already has data).
Is there any other way I can get all my data from the file without inserting it in the same run?
EDIT: So as some of the comments have mentioned the size of emp_arry is empty. I would like to get the size from a file. Since the file as a array inside which i want to transfer the data to emp_array.
One simple solution is to design a file header which includes the number of data in this file. Then, you can first read file header to get the number and then dynamically allocate memory to read data from file.
Program specifications:
Read questions from a data file in the following format:
Question
Number of choices
N-amount of choices
Correct answer
Example:
What is the capital of France?
3
Madrid
Sydney
Paris
Paris
Present the user a question at a time and keep track of their score, etc, etc.
What I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE_SIZE 60
#define MAX_LIST_SIZE 15
#define MAX_QUIZ_SIZE 10
typedef struct question {
char *question;
char **choices;
int n_choices;
char *correct_answer;
} QUESTION;
typedef struct quiz {
struct question *questions;
int n_questions;
} QUIZ;
char *dupString(const char *s) {
// copies a string
char *dup = malloc(strlen(s) + 1);
strcpy(dup, s);
return dup;
}
void free_choices(QUESTION *q) {
// free memory
for(int i = 0; i < q->n_choices; i++) {
free(q->choices[i]);
}
free(q->choices);
}
int ask(QUESTION *q) {
// Return 1 for correct guess, 0 for incorrect guess.
int choice;
// Print the question
printf("\n%s\n", q->question);
// Print the choices
for (int i = 0; i <= q->n_choices-1; i++) {
printf("%d : %s", i+1, q->choices[i]);
}
// Get user guess
do {
printf("Select an answer [1-%d]: ", q->n_choices);
scanf("%d", &choice);
/* Not sure how to structure here*/
if (strcmp(q->choices[choice-1], q->correct_answer) == 0) {
// if correct return 1
return 1;
}
} while (choice < 1 || choice > q->n_choices);
// Incorrect
return 0;
}
struct question parseQuestion(FILE *pData) {
int qIndex, numChoices;
char question[MAX_LINE_SIZE], temp[MAX_LINE_SIZE], choices[MAX_LINE_SIZE], correctAns[MAX_LINE_SIZE];
QUESTION q = {NULL, NULL, 0, NULL};
// Eat first line = QUESTION
fgets(question, MAX_LINE_SIZE, pData);
q.question = question;
// Eat second line = NUMBER OF CHOICES
fgets(temp, MAX_LINE_SIZE, pData);
numChoices = atoi(temp);
q.n_choices = numChoices;
// Allocate memory
q.choices = calloc(q.n_choices, sizeof(char*));
// Eat nth lines = CHOICES
for (qIndex=0; qIndex<=numChoices-1; qIndex++) {
fgets(choices, MAX_LINE_SIZE, pData);
q.choices[qIndex] = dupString(choices);
}
// Eat nth + 1 line = CORRECT ANSWER
fgets(correctAns, MAX_LINE_SIZE, pData);
q.correct_answer = correctAns;
return q;
}
int main() {
int num = 0; // question being asked
int strikes = 0; // incorrect guesses
FILE* pData;
char *filename = "tickle.txt";
char c;
if ((pData = fopen(filename, "r"))) {
printf("Welcome to the 2014 Quiz-festival!\n\n");
printf("Are you ready to begin? [Y/y]\n");
c = getchar();
if (c == 'Y' || c == 'y') {
QUESTION question = parseQuestion(pData);
ask(&question);
free_choices(&question);
} else {
printf("Come back again.\n");
return 0;
}
} else {
printf("File failed to open.");
}
fclose(pData);
return 0;
}
Thank you to #alk how picked up my error, that is resolved.
What I still can't get is how to loop through the data file and populate the quiz structure with question structures.
So this is where I'm struggling at the moment. From what I can tell I'm pretty close to finishing this little program as long as I can get this to work.
parseQuestion() duplicates the choices but misses to duplicate the question as well as the answer.
Instead it simply copies the two arrays' addresses to the locally defined variable QUESTION q which is copied on return.
The memory for the question and answer strings is free'd on returning from the function, accessing it afterwards invokes undefined behaviuor.