Read a file line by line to struct - c

I want to read a file which looks like this:
Spyros 1
George 2
John 3
and I want to store each student in a struct:
typedef struct studentR *student;
struct studentR{
char name[MAXSTRING];
int id;
student next;
};
I have written the following piece of code which does what I want but only for the first line. How can I move it to the next line?
while(fscanf(fp, "%s %d", st->name, &st->id) != EOF){
l = list_push_back(l, st->name, st->id);
}
Here is list_push_back
//enters the new student in the end of the list
list list_push_back(list l, char *name, int id){
student new_student = (student)malloc(sizeof(struct studentR));
assert(new_student);
strcpy(new_student->name, name);
new_student->id = id;
new_student->next = NULL;
//push payload(stsudent data) at the top if the list is empty
if (list_isempty(l))
{
l->head = new_student;
l->tail = new_student->next;
l->size++;
}else{
//push the payload(student data) at the bottom if the list is NOT empty
student last = (student)malloc(sizeof(struct studentR));
assert(last);
last->next = new_student;
l->tail = new_student;
l->size++;
}
return l;
}

Among the things wrong with that code:
Never properly set tail in the add-to-empty-list case.
Leak memory in the add-to-not-empty-list case (twice).
Sort-of-add a node in the add-to-not-empty-list case, but leak memory while doing it.
That function should look like this:
list list_push_back(list l, const char *name, int id)
{
student new_student = malloc(sizeof *new_student);
assert(new_student);
strcpy(new_student->name, name);
new_student->id = id;
new_student->next = NULL;
if (l->size == 0)
{
l->head = new_student;
}
else
{
l->tail->next = new_student;
}
l->tail = new_student;
l->size++;
return l;
}
That's all.

Related

wrong output when code runs problem with linked list?

Upon running the code below i get the output
NAME: (null) | GPA: 0.000000 | YEAR: (NULL)
are the linked lists not implemented correctly? I am currently using a makefile and bringing in a test.data file with names and gpa and senior/ect..
Ollie 2.9 freshmen
John 3.2 senior
Julie 2.2 freshmen
Joe 1.8 freshmen
Mary 3.8 senior
Sue 3.4 junior
Jane 2.7 senior
Bob 2.8 senior
Fred 3.2 freshmen
Bill 3.3 junior
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "students.h"
Student *top = NULL;
Student *temp, *temp1, *temp2;
// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
Student *buildStudentList()
{
Student *p;
p = readNext();
push(&top, p);
return top; //TODO: Change return
}
//Read a single line from standard input and return a student structure located on the heap
Student *readNext()
{
Student *s =(Student*) malloc(sizeof(Student));
scanf("%s", s -> name);
scanf("%f", &s -> gpa);
scanf("%s", s -> year);
s->next = NULL;
return s; //TODO: Change return
}
//Return a student structure stored on the heap
Student *makeStudent(char *name, float gpa, char *year)
{
Student *s =(Student*) malloc(sizeof(Student));
s -> name = name;
s -> gpa = gpa;
s -> year = year;
s -> next = NULL;
return s; //TODO: Change return
}
//insert a new student node at the head of the linked list
void push(Student **list, Student *student)
{
top = *list;
student -> next = top;
top = student;
}
//Insert a student node in the desired position on the linked list
void insert(Student *list, Student *s, int position)
{
int i;
top = list;
temp = top;
for(i = 1; i < position -1; i++)
{
temp = temp -> next;
}
if(temp == NULL)
{
//blank
}
else
{
s -> next = temp -> next;
temp -> next = s;
}
}
//Displays contents of a single student structure
void display(Student *s){
printf("NAME:%s | GPA: %f | YEAR:%s
", s -> name, s-> gpa, s -> year);
}
//Displays contents of the entire linked list
void displayAll(Student *list)
{
temp = list;
while(temp != NULL)
{
display(temp);
temp = temp -> next;
}
}
//Delete all data allocated on the heap before terminating program
void cleanUp(Student *list)
{
temp1 = list;
temp2 = temp1 -> next;
while(temp1 != NULL)
{
free(temp1);
temp1 = temp2;
}
if(temp2 != NULL)
{
temp2 = temp2 -> next;
}
}
//Main function tests your functions.
int main()
{
printf("Program Started
");
//Construct Linked List from Standard Input
Student *list = buildStudentList();
//Insert a new student in desired position
Student *s = makeStudent("Max",3.0, "senior");
insert(list, s, 3);
//Display entire linked list
displayAll(list);
//Free all heap memory
cleanUp(list);
printf("Program Successful Exit
");
exit(EXIT_SUCCESS);
}
Since you didn't post your struct definition, I had to guess whether (e.g.) name was char *name; or (e.g. char name[100];). Within the code, it used it as a pointer.
So ...
Your readNext and makeStudent don't allocate space for the strings (char * pointers) name and year, so they're probably segfaulting.
insert takes Student *list when it really needs Student **list.
IMO, you should have a separate List type to avoid confusion (that has a single element: Student *head;). So, wherever you have Student *list, you replace it with List *list
When you do that, you don't have to pass down Student ** [a double star] pointer when you mean a list. Using list->head is a lot easier and more descriptive than *list.
Also, be consistent. Some functions take Student **list if they modify the list [they have to]. Others use Student *list, but they should be consistent as well.
No need for the various global scope temp variables. These should be function scoped and use more descriptive names.
Your insert has issues. It will orphan the node it's trying to insert if no position match is found (e.g. insert at position 99 in your example). Usual is to insert at tail or return an error code. Also, it wasn't totally clear what position meant [to me], because of the code you had. It could have been "insert before" or "insert after" the Nth node.
You can't insert a literal newline in a double quoted string. So, use the \n escape sequence (e.g.) printf("hello world\n");
Also, functions that take no arguments should use void (e.g.) instead of int main(), use int main(void).
Here's a cleaned up version of your code, incorporating what I've mentioned above:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
//#include "students.h"
typedef struct student Student;
struct student {
Student *next;
float gpa;
char *name;
char *year;
};
typedef struct list {
Student *head;
} List;
//insert a new student node at the head of the linked list
void
push(List *list, Student *student)
{
student->next = list->head;
list->head = student;
}
//Return a student structure stored on the heap
Student *
makeStudent(char *name, float gpa, char *year)
{
Student *s = (Student *) malloc(sizeof(Student));
s->name = strdup(name);
s->gpa = gpa;
s->year = strdup(year);
s->next = NULL;
return s;
}
//Read a single line from standard input and return a student structure located on the heap
Student *
readNext(void)
{
char name[1000];
float gpa;
char year[1000];
Student *s = NULL;
int count = scanf("%s %f %s",name,&gpa,year);
if (count == 3) {
printf("readNext: name='%s' gpa=%g year='%s'\n",name,gpa,year);
s = makeStudent(name,gpa,year);
}
return s;
}
// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
List *
buildStudentList(List *list)
{
Student *p;
while (1) {
p = readNext();
if (p == NULL)
break;
push(list, p);
}
return list;
}
//Insert a student node in the desired position on the linked list
int
insert(List *list, Student *s, int position)
{
Student *cur;
Student *prev;
int i;
int goflg;
//position -= 1;
#if 0
i = 1; // insert before Nth position
#else
i = 0; // insert after Nth position
#endif
prev = NULL;
for (cur = list->head; (cur != NULL) && (i < position);
++i, cur = cur->next) {
prev = cur;
}
// this may not be needed -- usual is to insert at tail if position is not
// found -- this will orphan the node to be inserted
#if 0
goflg = (i == position);
#else
goflg = 1;
#endif
if (goflg) {
s->next = cur;
if (prev != NULL)
prev->next = s;
else
list->head = s;
}
return goflg;
}
//Displays contents of a single student structure
void
display(Student *s)
{
printf("NAME:%s | GPA: %f | YEAR:%s\n", s->name, s->gpa, s->year);
}
//Displays contents of the entire linked list
void
displayAll(List *list)
{
Student *temp = list->head;
while (temp != NULL) {
display(temp);
temp = temp->next;
}
}
//Delete all data allocated on the heap before terminating program
void
cleanUp(List *list)
{
Student *cur;
Student *next;
for (cur = list->head; cur != NULL; cur = next) {
next = cur->next;
free(cur->name);
free(cur->year);
free(cur);
}
list->head = NULL;
}
//Main function tests your functions.
int
main(void)
{
List top = { NULL };
List *list;
printf("Program Started\n");
//Construct Linked List from Standard Input
list = buildStudentList(&top);
//Insert a new student in desired position
Student *s = makeStudent("Max", 3.0, "senior");
insert(list, s, 3);
//Display entire linked list
displayAll(list);
//Free all heap memory
cleanUp(list);
printf("Program Successful Exit\n");
exit(EXIT_SUCCESS);
}

pointers and Structs from csv file

I need to read-in a .csv file and print it's contents, the students' names and age. The actual output is correct but it is appended with junk characters. The program also terminates with a segmentation fault! For some reason, these problems do not occur on OSX but do on Windows.
Code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE_LENGTH 80
#define MAX_NUM_STUDENTS 500
#define MAX_NAME_SIZE 50
typedef struct student_s Student;
struct student_s {
char name[MAX_NAME_SIZE];
int age;
Student* next; // Pointer to next student in a list
};
Student studentPool[MAX_NUM_STUDENTS]; // The student pool
int firstFree = 0;
Student* newStudent(const char* name, int age)
{
Student* student = NULL;
if (firstFree < MAX_NUM_STUDENTS) {
student = &studentPool[firstFree];
firstFree += 1;
strncpy(student->name, name, MAX_NAME_SIZE);
student->name[MAX_NAME_SIZE - 1] = '\0'; // Make sure it's terminated
student->age = age;
student->next = NULL;
}
return student;
}
Student* readOneStudent(FILE* file)
{
char buffer[MAX_LINE_LENGTH];
Student* student = NULL;
char* inputLine = fgets(buffer, MAX_LINE_LENGTH, file);
if (inputLine != NULL) { // Proceed only if we read something
char* commaPos = strchr(buffer, ',');
if (commaPos != NULL && commaPos > buffer) {
int age = atoi(commaPos + 1);
*commaPos = '\0'; // null-terminate the name
student = newStudent(buffer, age);
}
}
return student;
}
int precedes(const Student* new, const Student* old)
{
int final = strcmp(old->name, new->name);
if (final == 0) {
if (old->age <= new->age) {
final = -1;
} else {
final = 1;
}
}
return final;
}
Student* insert(Student* student, Student* list)
{
Student* current = list;
if (list == NULL) {
student->next = list;
list = student;
} else if (precedes(current, student) < 0) {
student->next = current;
current = student;
list = current;
} else {
while(current->next && precedes(student, current->next) < 0) {
current = current->next;
}
student->next = current->next;
current->next = student;
}
return list;
}
Student* readStudents(FILE *file)
{
Student* student_list;
Student* student = readOneStudent(file);
while (student != NULL) {
student_list = insert(student, student_list);
student = readOneStudent(file);
}
return student_list;
}
void printOneStudent(Student student)
{
printf("%s (%d)\n", student.name, student.age);
}
void printStudents(const Student* student)
{
while (student != NULL) {
printOneStudent(*student);
student = student->next;
}
}
int main(void)
{
FILE* inputFile = fopen("studlist.txt", "r");
if (inputFile == NULL) {
fprintf(stderr, "File not found\n");
} else {
Student* studentList = readStudents(inputFile);
printStudents(studentList);
}
}
input:
Zaphod Beeblebrox,250
Albert Einstein,133
Albert Einstein,7
The output is sorted alphabetically for student names' then increasing age.
expected output:
Albert Einstein (7)
Albert Einstein (133)
Zaphod Beeblebrox (250)
on Windows, output is appended with:
p
# (0)
then segfault.
student_list is a uninitialized stack variable. It could be 0 (NULL) on some machines but that does not have to be true. In general you should expect an initialized stack variable to contain whatever garbage is in that location of memory.
Here is the simple fix:
Student* readStudents(FILE *file)
{
Student* student_list = NULL;
Student* student = readOneStudent(file);
while (student != NULL) {
student_list = insert(student, student_list);
student = readOneStudent(file);
}
return student_list;
}
The bug is triggered in the insertion method here:
if (list == NULL) {
student->next = list;
list = student;
}
Whatever the variable list is pointing to will be used for sorting. In your case it looks like it was "bigger" than all the legit inputs and garbage made its way to the back of your linked list. The print function would then keep dereferencing uninitialized next pointers until the SIGSEGV is triggered.
For debugging this sort of problems you might want to check out valgrind.

Adding node to a linked list

So I'm creating a linked list in C and adding some nodes to it that contain information. I have an if else statement where I create the linked list's head and then add nodes to it. The problem is that when I add a new node I seem to lose the old one. Not sure why this is happening or how to fix this.
Edit: I have made some updates to make it a runnable program.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include<regex.h>
int main(int argc, char argv[]) {
int head=0, i=0;
char tempCourseID[10], tempCourseGrade[10], tempCourseCH[10];
static struct LinkedList {
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
} LinkedList;
static struct LinkedList *first, *savefirst, *headlist;
first = malloc(sizeof ((*first)));
savefirst = first;
headlist = first;
for(i ; i<5; i++){
printf("Enter Course name");
fgets(tempCourseID, sizeof(tempCourseID), stdin);
printf("Enter Course grade");
fgets(tempCourseGrade, sizeof(tempCourseGrade), stdin);
printf("Enter Course credit hours");
fgets(tempCourseCH, sizeof(tempCourseCH), stdin);
//checks to see if linked list head exists
if (head == 0) {
printf("No head has been found.\n");
headlist->CourseName = tempCourseID;
headlist->CourseGrade = tempCourseGrade;
headlist->CourseCreditHours = tempCourseCH;
headlist->next = NULL;
printf("A head has been created\n");
printf("A node has been added\n");
head = 1;
} else {
printf("Ahead already exists\n");
first = malloc(sizeof ((*first)));
first->CourseName = tempCourseID;
first->CourseGrade = tempCourseGrade;
first->CourseCreditHours = tempCourseCH;
first->next = NULL;
savefirst->next = first;
savefirst = first;
printf("A node has been add\n");
head = 1;
}
}
while (headlist != NULL) {
printf(" %s ", headlist->CourseName);
printf(" %s ", headlist->CourseGrade);
printf("%s \n", headlist->CourseCreditHours);
headlist = headlist->next;
}
return 0;
}
You have char tempCourseID[10] and char* CourseName
It is legal to use CourseName = tempCourseID; however tempCourseID is temporary, and so the string will be lost soon. In this case we need to allocate separate memory for CourseName, and then copy the value from tempCourseID
Use instead
CourseName = malloc(strlen(tempCourseID) + 1);//add +1 for null-character
strcpy(CourseName, tempCourseID);
//or
CourseName = strdup(tempCourseID)//shortcut!
There are problem with the linked list. You have too many variables with similar names. A linked list needs only head. You can introduce a temporary variable node for adding new nodes. If you are adding nodes to the tail, then save the last node in the list, lets call it savenode
In this example I removed fgets functions and replaced it with sprintf, that's just to make it easier to run the program and debug. You can put back fgets later.
int main(int argc, char argv[])
{
struct LinkedList
{
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
};
int i;
char tempCourseName[100], tempCourseGrade[100], tempCourseCH[100];
struct LinkedList *head = NULL;
struct LinkedList *node = NULL;
struct LinkedList *savenode = NULL;
for(i = 0; i < 5; i++)
{
sprintf(tempCourseName, "CourseName %d", i);
sprintf(tempCourseGrade, "tempCourseGrade %d", i);
sprintf(tempCourseCH, "tempCourseCH %d", i);
node = malloc(sizeof(*node));
node->CourseName = strdup(tempCourseName);
node->CourseGrade = strdup(tempCourseGrade);
node->CourseCreditHours = strdup(tempCourseCH);
node->next = NULL;
if(head == NULL)
head = node;
//check savenode exists
//this will be the last node (tail) in the existing list
//get it to point to our new node
if(savenode)
savenode->next = node;
//now we have a new tail
savenode = node;
}
//walk through the list
node = head;
while(node)
{
printf("%s, %s, %s\n",
node->CourseName, node->CourseGrade, node->CourseCreditHours);
node = node->next;
}
return 0;
}

Linked list insertion doesn't work as expected

I'm writing a function that places new nodes alphabetically into a linked list structure by sorting them by the name field. Here is my program, intended to test that it can successfully insert a new node into an existing structure:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee
{
/* Employee details */
char name[MAX_NAME_LENGTH+1]; /* name string */
char sex; /* sex identifier, either ’M’ or ’F’ */
int age; /* age */
char job[MAX_JOB_LENGTH+1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
int main(){
struct Employee *a;
struct Employee *c;
struct Employee *b;
a = malloc(sizeof(struct Employee));
c = malloc(sizeof(struct Employee));
b = malloc(sizeof(struct Employee));
strcpy(a->name, "A");
a->sex = 'F';
a->age = 42;
strcpy(a->job, "Optician");
a->prev = NULL;
a->next = c;
strcpy(c->name, "C");
c->sex = 'F';
c->age = 22;
strcpy(c->job, "Nurse");
c->prev = a;
c->next = NULL;
strcpy(b->name, "B");
b->sex = 'M';
b->age = 34;
strcpy(b->job, "Rockstar");
b->prev = NULL;
b->next = NULL;
place_alpha(b, &a);
if(a->prev == NULL)
{
printf("a->prev is correct\n");
}else{
printf("a->prev is INCORRECT\n");
}
if(a->next == b)
{
printf("a->next is correct\n");
}else{
printf("a->next is INCORRECT");
}
if(b->prev == a)
{
printf("b->prev is correct\n");
}else{
printf("b->prev is INCORRECT\n");
}
if(b->next == c)
{
printf("b->next is correct\n");
}else{
printf("b->next is INCORRECT\n");
}
if(c->prev == b)
{
printf("c->prev is correct\n");
}else{
printf("c->prev is INCORRECT\n");
}
if(c->next == NULL)
{
printf("c->next is correct\n");
}else{
printf("c->next is INCORRECT\n");
}
}
void place_alpha(struct Employee *new, struct Employee **root) //Places a new node new into the database structure whose root is root.
{
if(*root==NULL) //If there is no database yet.
{
*root = new;
(*root)->prev = NULL;
(*root)->next = NULL;
}
else
{
if(strcmp(new->name, (*root)->name)<=0) // if the new node comes before root alphabetically
{
new->next = *root;
new->prev = (*root)->prev;
if((*root)->prev != NULL)
{
(*root)->prev->next = new;
}
(*root)->prev = new;
*root = new;
return;
}
else if((*root)->next == NULL) // If the next node is NULL (we've reached the end of the database so new has to go here.
{
new->prev = *root;
new->next = NULL;
(*root)->next = new;
return;
}
else if(strcmp(new->name, (*root)->name)>0) // If the new node comes after root alphabetically
{
place_alpha(new, &(*root)->next);
return;
}
}
}
Sadly, the program is unsuccessful, as showcased by the output:
a->prev is correct
a->next is correct
b->prev is INCORRECT
b->next is correct
c->prev is INCORRECT
c->next is correct
Program ended with exit code: 0
I can't figure out why, as I've clearly set b->next to c and c->prev to b.
This was tricky: there is a subtile bug in your place_alpha() function: you update *root even if it is not the root node of the list. This causes the pointer b to be updated erroneously. place_alpha() should only be called with a pointer to the actual root node.
I modified your code to make it more readable and reliable:
I wrote a function to create a new node
I protected the string copies from overflow using calloc() and strncat(). Read about these functions in the manual.
I use place_alpha() to insert all 3 nodes into the list in the same order you do.
I use newp instead of new to avoid C++ keywords in C code.
Note that place_alpha() must be called with a pointer to the head pointer of the list, if you pass a pointer to an intermediary node, chaining back along the prev links would locate the first node, but if the new employee should be inserted at the head of the list, you would not have the address of the root node to update in the caller's scope. This is the reason many programmers prefer to use a specific structure for the list head.
Here is the updated code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee {
/* Employee details */
char name[MAX_NAME_LENGTH + 1]; /* name string */
char sex; /* sex identifier, either 'M' or 'F' */
int age; /* age */
char job[MAX_JOB_LENGTH + 1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
struct Employee *new_employee(const char *name, char sex, int age, const char *job) {
struct Employee *newp = calloc(1, sizeof(*newp));
if (!newp) {
fprintf(stderr, "cannot allocate employee\n");
exit(1);
}
strncat(newp->name, name, MAX_NAME_LENGTH);
newp->sex = sex;
newp->age = age;
strncat(newp->job, job, MAX_JOB_LENGTH);
newp->next = newp->prev = NULL;
return newp;
}
int main(void) {
struct Employee *list = NULL;
struct Employee *a = new_employee("A", 'F', 42, "Optician");
struct Employee *b = new_employee("B", 'M', 34, "Rockstar");
struct Employee *c = new_employee("C", 'F', 22, "Nurse");
place_alpha(a, &list);
place_alpha(c, &list);
place_alpha(b, &list);
if (a->prev == NULL) {
printf("a->prev is correct\n");
} else {
printf("a->prev is INCORRECT\n");
}
if (a->next == b) {
printf("a->next is correct\n");
} else {
printf("a->next is INCORRECT");
}
if (b->prev == a) {
printf("b->prev is correct\n");
} else {
printf("b->prev is INCORRECT\n");
}
if (b->next == c) {
printf("b->next is correct\n");
} else {
printf("b->next is INCORRECT\n");
}
if (c->prev == b) {
printf("c->prev is correct\n");
} else {
printf("c->prev is INCORRECT\n");
}
if (c->next == NULL) {
printf("c->next is correct\n");
} else {
printf("c->next is INCORRECT\n");
}
return 0;
}
void place_alpha(struct Employee *newp, struct Employee **root) {
// Insert a new node newp into the database structure whose root is root.
struct Employee *ep;
if (*root == NULL) { // if there is no database yet.
newp->next = newp->prev = NULL;
*root = newp;
return;
}
if ((*root)->prev) {
// invalid call, should only pass the root node address
fprintf(stderr, "invalid call: place_alpha must take a pointer to the root node\n");
return;
}
if (strcmp(newp->name, (*root)->name) <= 0) {
// if the new node comes before root alphabetically
newp->next = *root;
newp->prev = NULL;
newp->next->prev = newp;
*root = newp;
return;
}
for (ep = *root;; ep = ep->next) {
if (ep->next == NULL) {
// If the next node is NULL, we've reached the end of the list
// so newp has to go here.
newp->prev = ep;
newp->next = NULL;
newp->prev->next = newp;
return;
}
if (strcmp(newp->name, ep->next->name) <= 0) {
// The new node comes between ep and ep->next alphabetically
newp->prev = ep;
newp->next = ep->next;
newp->prev->next = newp->next->prev = newp;
return;
}
}
}
EDIT: place_alpha was a bit redundant, so I cleaned it and got a much simpler version:
void place_alpha(struct Employee *newp, struct Employee **root) {
//Places a new node newp into the database structure whose root is root.
struct Employee **link = root;
struct Employee *last = NULL;
while (*link && strcmp(newp->name, (*link)->name) > 0) {
last = *link;
link = &last->next;
}
newp->prev = last;
newp->next = *link;
if (newp->next) {
newp->next->prev = newp;
}
*link = newp;
}

Save structs in a file

I'm doing a program to save a list of contacts in a file whit structs. I've tried a lot of things but when I try go read the file to the program, it doesn't read anything.
This is my program without opening files and saving to files:
#include <stdio.h>
#include <stdlib.h>
struct agenda {
int idContacte;
char name[50];
struct agenda *nextContacte;
};
struct agenda *pAgenda;
struct agenda *pFirst = NULL;
struct agenda *pIndex;
void insert();
void show();
int main()
{
//Menu
int opc;
while(1){
printf("1.Insert Contact.\n");
printf("2.Show Contacts.\n");
printf("3.Exit\n");
scanf("%d", &opc);
switch(opc){
case 1:
insert();
break;
case 2:
show();
break;
case 3:
return 0;
}
}
}
void insert(){
pAgenda = (struct agenda *)malloc(sizeof(struct agenda));
printf("Insert ID: ");
scanf("%d", &pAgenda->idContacte);
printf("Insert the name: ");
scanf("%s", pAgenda->name);
printf("\n");
if (pFirst==NULL || pAgenda->idContacte < pFirst->idContacte)
{
pAgenda->nextContacte=pFirst;
pFirst=pAgenda;
}
else if (pAgenda->idContacte > pFirst->idContacte){
pIndex=pFirst;
while(pIndex->nextContacte && pIndex->nextContacte->idContacte < pAgenda->idContacte)
{
pIndex = pIndex->nextContacte;
}
pAgenda->nextContacte = pIndex->nextContacte;
pIndex->nextContacte = pAgenda;
}
}
void show(){
pIndex = pFirst;
while(pIndex && pIndex->idContacte <= 100) {
printf("\nID: %d", pIndex->idContacte);
printf("\nNAME: %s", pIndex->name);
printf("\n\n");
pIndex = pIndex->nextContacte;
}
}
Can you help me how can I get contact at start of the program from a file, and then when insert a contact, rewrite the file and insert all the contacts again in the file?
When you end your program you should do the following
int save_list(struct agenda *head) {
FILE *save = fopen("file.name", "wb");
if(!save) return -1;
while(head) {
fwrite(head, sizeof *head - sizeof head, 1, save);
head = head->nextContacte;
}
fclose(save);
/* Somebody would free list memory after this function execution */
return 0;
}
At the start of your program you should do the following
struct agenda *restore_list() {
FILE *restore= fopen("file.name", "rb");
struct agenda *head = NULL;
struct agenda *cur = head;
struct agenda temp;
if(!restore) return head;
while( fwrite(&temp, sizeof temp - sizeof head, 1, save) == 1) {
struct agenda *node = malloc( sizeof(struct agenda) );
if(NULL == node) {
/* Handle out of memory error here, free list */
return NULL;
}
*node = temp;
node->nextContacte = NULL;
if(head) {
cur->nextContacte = node;
cur = node;
} else {
/* First node */
head = cur = node;
}
}
fclose(restore);
return head;
}

Resources