How to call string in singly linked list in C - c

Here is my struct
struct Student
{
int numberofstudents;
float mid,prj,final,hmw;
int lettergrade;
int studentnumber;
char name[40];
char lastname[40];
int birthyear;
float totalgrade;
struct Student *next;
}* head;
And I have a function like this
void searchbylastname(char *lastname)
{
struct Student * temp = head;
while(temp!=NULL)
{
if(temp->lastname == lastname){
printf("Student Number: %d\n", temp->studentnumber);
printf("Name: %s\n", temp->name);
printf("Surname: %s\n", temp->lastname);
printf("Birth Year: %d\n", temp->birthyear);
printf("Total Grade: %0.2f\n", temp->totalgrade);
return;
}
temp = temp->next;
}
printf("Student with student number %s is not found !!!\n", lastname);
}
I'm calling it in main with switch case
head = NULL;
int choice;
char name[50];
char lastname[50];
int birthyear;
int studentnumber;
float totalgrade;
float prj,hmw,mid,final;
case 6:
printf("Enter student lastname to search: ");
scanf("%s", &lastname);
searchbylastname(lastname);
break;
but it cannot search by last name, it's automatically direct me here;
printf("Student with student number %s is not found !!!\n", lastname);
I don't know what to do, if anyone has an opinion, I would really appreciate it.

== does not compare strings in C only the references (addresses) of those strings. If they do not reference the same object they always will be different.
To compare strings you need to use strcmp function.
https://www.man7.org/linux/man-pages/man3/strncmp.3.html
You have more problems in your code. Even if you use strcmp it will display the message that the student has not been found. If you may have more students having the same surmane (which rather expected you need add a flag)
void searchbylastname(char *lastname)
{
struct Student * temp = head;
int studentsFound = 0;
while(temp!=NULL)
{
if(!strcmp(temp->lastname,lastname)){
stutentsFound = 1;
printf("Student Number: %d\n", temp->studentnumber);
printf("Name: %s\n", temp->name);
printf("Surname: %s\n", temp->lastname);
printf("Birth Year: %d\n", temp->birthyear);
printf("Total Grade: %0.2f\n", temp->totalgrade);
}
temp = temp->next;
}
if(!studentsFound)
printf("Students having %s surname have not been found !!!\n", lastname);
}

Related

My linked list is displaying garbage values after my insert function is applied

I'm trying to create a telephone directory and I'm having issues with my insert_beg function. the function's name itself explains what it is supposed to do pretty much. When I create a record using create_pd it works, and then I use the display function and then it displays the created record. Then when I try to use the insert_beg function and type in my number and name. When I try to use the display function it displays garbage values. Thanks beforehand I really appreciate any sort of help.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct phonedir
{
char* name;
char* phonenum;
struct phonedir *next;
};
struct phonedir *start = NULL;
void display();
struct phonedir *create_pd(struct phonedir *);
struct phonedir *insert_beg(struct phonedir *);
int main ()
{
int option;
while (option != 4)
{
printf("\n\n *****MAIN MENU *****");
printf("\n 1: Create a record");
printf("\n 2: Display the records");
printf("\n 3: insert a new record");
printf("\n 4: EXIT");
printf("\n\n Enter your option : ");
scanf("%d", &option);
switch(option)
{
case 1: start = create_pd(start);
printf("\n PHONE RECORD CREATED");
break;
case 2: display(start);
break;
case 3: start = insert_beg (start);
printf("PHONE RECORD ADDED \n");
break;
}
}
return 0;
}
void display()
{
struct phonedir *ptr;
ptr = start;
if(ptr != NULL)
{
printf("\t %s\n", &ptr -> phonenum);
printf("\t %s", &ptr -> name);
ptr = ptr -> next;
}
else
{
printf("Please create an entry\n");
}
}
struct phonedir *create_pd(struct phonedir *start)
{
struct phonedir *new_phonedir, *ptr;
new_phonedir = (struct phonedir *)malloc(sizeof(struct phonedir));
new_phonedir->phonenum = (char *)malloc(11*sizeof(char));
new_phonedir->name = (char *)malloc(15*sizeof(char));
printf("Enter the phone number: \n");
scanf("%s", &new_phonedir->phonenum);
printf("Enter name: \n");
scanf("%s", &new_phonedir->name);
if (start == NULL)
{
new_phonedir->next= NULL;
start = new_phonedir;
}
else
{
ptr = start;
while(ptr->next != NULL)
{
ptr = ptr->next;
}
ptr->next = new_phonedir;
new_phonedir->next = NULL;
}
return start;
}
struct phonedir *insert_beg(struct phonedir *start)
{
struct phonedir *new_phonedir;
new_phonedir = (struct phonedir *)malloc(sizeof(struct phonedir));
new_phonedir->phonenum = (char *)malloc(11*sizeof(char));
new_phonedir->name = (char *)malloc(15*sizeof(char));
printf("Enter phone number: \n");
scanf("%s", new_phonedir->phonenum);
printf("Enter name: \n");
scanf("%s", new_phonedir->name);
new_phonedir ->next = start;
start = new_phonedir;
return start;
}
Your first problem is a general one: When you compile a C program you should always enable compiler warnings. If you do that your compiler will warn you about passing parameters of the wrong type to printf and scanf.
In four places you pass the address to the string instead of the the string (the address to the first character), so &ptr->phonenum should be ptr->phonenum etc.
By the way, what do you think will happen if the user enters a phone number longer than 10 characters or a name longer than 14 characters?
These calls of scanf within the function create_pd are incorrect and invoke undefined behavior
printf("Enter the phone number: \n");
scanf("%s", &new_phonedir->phonenum);
printf("Enter name: \n");
scanf("%s", &new_phonedir->name);
you have to write
printf("Enter the phone number: \n");
scanf("%s", new_phonedir->phonenum);
printf("Enter name: \n");
scanf("%s", new_phonedir->name);
It will be even better to write
printf("Enter the phone number: \n");
scanf("%10s", new_phonedir->phonenum);
printf("Enter name: \n");
scanf("%14s", new_phonedir->name);
Also these calls of printf are incorrect
printf("\t %s\n", &ptr -> phonenum);
printf("\t %s", &ptr -> name);
You have to write
printf("\t %s\n", ptr -> phonenum);
printf("\t %s", ptr -> name);
Your printf("\t %s\n", &ptr -> phonenum); and scanf("%s", &new_phonedir->phonenum); calls (for both, phonenum and name) have an additional &, which is wrong, as it gets the address of where the pointer to your char array is stored. This makes the scanf write to where the pointer value is stored, not to where it points to, i.e. the pointer gets corrupted, as well as the data after that if you enter more than 8 bytes (on a 64bit OS). After fixing this you still will run into issues when you enter more than 11/15 chars, but I guess this is just exercise code. You also might want to add a while-loop to your display() function. :-)

Weird characters in string with C (Structs, pointers, and strings)

Hi I'm creating a linked list that holds students' information.
However, when displaying the string variables of the student struct, it displays characters other than the strings that it's supposed to display. Here is the snippet from my code (I cut out the code unrelated to my problem):
# include <stdio.h>
# include <stdlib.h>
struct Student {
int student_number[2];
char *last;
char *first;
char *course;
int year;
int age;
char sex;
int grade;
struct Student * next;
};
typedef struct Student Student;
struct SLList {
Student * head;
Student * tail;
int size;
};
typedef struct SLList SLList;
void initList(SLList * list){
list->head = 0;
list->tail = 0;
list->size = 0;
}
Student * getStudent(SLList * list, int index) {
Student * current = list->head;
for (int i = 0; i < index; i ++) {
current = current->next;
}
return current;
}
Student * createStudent(int * number, char *last, char *first, char * course, int year, int age, char sex, int grade){
Student * student = (Student *) malloc(sizeof(Student));
student->student_number[0] = number[0];
student->student_number[1] = number[1];
student->last = last;
student->first = first;
student->course = course;
student->year = year;
student->age = age;
student->sex = sex;
student->grade = grade;
student->next = 0;
return student;
}
void enrolStudent(SLList * list, int index){
Student * student;
int i, found = 1;
int student_number[2];
char last[15];
char first[15];
char course[15];
int year;
int age;
char sex;
int grade;
printf("Student Number: ");
scanf("%i-%i", &student_number[0], &student_number[1]);
printf("Last Name: ");
scanf("%s", last);
printf("First Name: ");
scanf("%s", first);
printf("Course: ");
scanf("%s", course);
printf("Year: ");
scanf("%i", &year);
printf("Age: ");
scanf("%i", &age);
printf("Sex [M or F]: ");
scanf(" %c", &sex);
printf("Final Grade: ");
scanf("%i", &grade);
Student * toInsert = createStudent(student_number, last, first, course, year, age, sex, grade);
if (index == 0){
toInsert->next = list->head;
list->head = toInsert;
}
if (index == list->size){
if (list->tail != 0) {
list->tail->next = toInsert;
}
list->tail = toInsert;
}
list->size ++;
return;
}
void showStudents(SLList * list, int index) {
Student * student = getStudent(list, index);
printf("\n");
printf("Student Number: %i-%i\n", student->student_number[0], student->student_number[1]);
printf("Last Name: %s\n", student->last);
printf("First Name: %s\n", student->first); //! error in printing strings
printf("Course: %s\n", student->course);
printf("Year Level: %i\n", student->year);
printf("Age: %i\n", student->age);
printf("Sex: %c\n", student->sex);
printf("Final Grade: %i\n", student->grade);
printf("\n");
}
int main(){
int choice = 0;
int rtn = 0;
SLList students;
initList(&students);
printf("What do you want to do?\n");
printf("1. Enrol a student\n");
[...]
printf("4. Display all student/s\n");
for(;;){
printf("\nEnter a number: ");
rtn = scanf("%d", &choice);
if (choice == 1) {
enrolStudent(&students, students.size);
} else if (choice == 4) {
int i;
for (i = 0; i < students.size; i ++){
showStudents(&students, i);
}
printf("Displaying %i of %i student(s)\n", i, students.size);
}
[...]
}
I believe that I need to allocate memory for the char * variables of the struct, but I don't know how it should go.
Hope to get some help. Thanks!
you are passing local variable address to createStudent and simply assigning this to internal pointers that's wrong.
you can do is use something like an strdup call as below
student->last = strdup(last);
student->first = strdup(first);
student->course = stddup(course);
or allocate space to last, first and course and copy the string
Your assumption is correct: You assigned pointers to stack objects to your list elements. So the content is likely to be overwritten on the course of further execution of the program, which gives you the weird characters in the output further down the road.
The correct way would be to allocate memory for the strings during createStudent which is done through malloc or calloc of minimum the length of the string. And you already have an example there in your function, so I'm a bit surprised that you stated you don't know how to do that. Another possibility is to call strdup for that purpose which basically does exactly the combination of allocation and string copy.
Oh and one more remark: Please make it a habit from the beginning of your career that you clean up after yourself. Meaning: Whatever you allocate, deallocate it after usage. In your case: If you have a createStudent function, create a destroyStudent function. If you have a linked list somewhere, free it before exitting the program. Picking that habit up early will save you from memory leaks in the future.

why does the age in the search function not printing?

I was asked to make a hash table program which input name and age. I declared name and age as char. While doing the search function, I need to print the name and the age but the age do not print. What is wrong with my code?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
int n;
int count;
struct data
{
char name [100];
char age[5];
struct data *next;
};
struct data *chain[100000];
struct data* insert(char name[], char age[]){
struct data *curr = (struct data*) malloc (sizeof(data));
strcpy(curr->name, name);
strcpy(curr->age, age);
curr->next = NULL;
return curr;
};
//hash function
int hashing(char name[]){
int first = name[0];
return first % n;
}
//buat tau di index ke x dia data ke brp
void add(struct data *newNode){
int hash = hashing(newNode->name);
printf("index->%d\n", hash);
if(chain[hash] == NULL){
chain[hash] = newNode;
}
else
{
struct data *temp = chain[hash];
while(temp->next != NULL){
temp = temp->next;
//count++;
}
count++;
temp->next = newNode;
//count++;
}
printf("data-> %d\n", count);
}
void view(){
for(int i = 0 ; i < n ; i ++)
{
int count = 0;
if(chain[i]!=NULL){
printf("=== index %d data ===\n", i );
struct data *temp = chain[i];
while(temp!=NULL){
printf("data %d\n", count);
printf("name=%s age=%s\n", temp->name, temp->age);
temp = temp->next;
count ++;
}
}
}
printf("\n");
}
void search(int hash){
char age[5];
char search[100];
printf("Search name:");
scanf(" %[^\n]s", search);
int key = hashing(search);
printf("Search data %s from index %d data....\n", search, key);
if(strcmp(chain[key]->name, search)==0){
printf("data found at node %d\n", key);
printf("name = %s age = %s\n", search, age);
}
else
{
struct data *temp = chain[key];
while(temp->next!=NULL){
if(strcmp(chain[key]->name, search)==0){
printf("data found at node %d\n", key);
printf("name = %s age = %s\n", search, age);
}
temp = temp->next;
}
if(strcmp(temp->name, search)==0 && temp->next==NULL){
printf("data found at node %d\n", key);
printf("name = %s age = %s\n", search, age);
}
else{
printf("no data found!\n");
}
}
}
//void remove(int hash){
// //int key = item->key;
// int hash = hashing(key);
// int option;
// printf("input option:");
// scanf("%d", &option);
// char search[100];
// printf("delete name:");
// scanf(" %[^\n]s", search);
// int first = search[0];
// int key = first % n;
// printf("Search data %s from index %d data....\n", search, key);
// if(chain[key]==hash){
// chain[key]=-1;
// }
// else
// {
// printf("try");
// }
//}
int main(){
char name[100];
char age[5];
printf("input the number of hash table: ");
scanf("%d", &n); getchar();
struct data *chain[n];
int chainSize[n]={0};
printf("\n");
int option;
do{
printf("=== Option Menu ===\n");
printf("1. insert data\n");
printf("2. delete data\n");
printf("3. search data\n");
printf("4. view data\n");
printf("5. exit\n");
printf("input option: ");
scanf("%d", &option); getchar();
switch(option){
case 1:{
printf("input name: ");
scanf(" %[^\n]s", name);
printf("input age: ");
scanf(" %[^\n]s", age);
add(insert(name,age));
printf("\n");
break;
}
case 2:
{
//remove();
break;
}
case 3:
{
search(n);
break;
}
case 4:
{
view();
break;
}
}
}while(option!=5);
}
the output is like this
name = hansol
age =
when it is supposed to be like this:
name = hansol
age = 23
so the age variable does not print while doing the search function

How to record thousand of information by using Structure ? [duplicate]

This question already has answers here:
malloc dynamic array in dynamic array of structs
(3 answers)
how to create array of struct
(3 answers)
Closed 4 years ago.
By using this code I can record only one student information, but what if I want to record thousand or more information of students ?
#include <stdio.h>
#include <string.h>
struct {
char name[10];
int id;
float marks;
char grade;
} s;
int main() {
printf("Name : ");
scanf("%s", s.name);
printf("Id : ");
scanf("%d", &s.id);
printf("Marks : ");
scanf("%f", &s.marks);
printf("Grade : ");
scanf(" %c", &s.grade);
printf("%s %d %.2f %c\n", s.name, s.id, s.marks, s.grade);
}
You can consider using dynamic arrays, if length of students reach max, realloc students
#include <stdio.h>
#include <stdlib.h>
typedef struct student {
const char* name;
int id;
float marks;
char grade;
} student;
typedef struct class {
int len;
int max_alloc_len;
student** students;
} class;
student* newClass() {
struct class* c;
c = malloc(sizeof(c));
c->len = 0;
c->max_alloc_len = 10;
c->students = malloc(sizeof(struct student*) * 10);
return c;
}
student* newStudent(const char* name)
{
struct student* s;
s = malloc(sizeof(s));
s->name = name;
return s;
}
void addStudent(class* c, student* s)
{
c->students[c->len++] = s;
if (c->len >= c->max_alloc_len) {
c->max_alloc_len *= 2;
c->students = realloc(c->students, sizeof(struct student*) * c->max_alloc_len);
}
}
int main() {
int i;
class* c;
student* s;
c = newClass();
for (i = 0; i < 20; i++) {
s = newStudent("jim");
addStudent(c, s);
}
printf("%s", c->students[19]->name);
}
You can create one array of structure and store them like how we store elements into array. See the complete code given below:
#include <stdio.h>
#include <string.h>
#define N 100
struct record{
char name[10];
int id;
float marks;
char grade;
} ;
int main() {
struct record s[N]; // allocate memory for N=100 records
int num_records= 0;
printf("How many records do you wish to store (1- 100): ");
scanf("%d", &num_records);
while (num_records > N)
{
printf("Enter between than (1- 100): ");
scanf("%d", &num_records);
}
for (int i= 0; i < num_records; i++)
{
printf("\n____Enter details for Record %d _____\n",i+1); // now records starts from 1 insted of f0
printf("Name : ");
scanf("%s", s[i].name);
printf("Id : ");
scanf("%d", &s[i].id);
printf("Marks : ");
scanf("%f", &s[i].marks);
printf("Grade : ");
scanf(" %c", &s[i].grade);
}
for (int i= 0; i < num_records; i++)
printf("%s %d %.2f %c\n", s[i].name, s[i].id, s[i].marks, s[i].grade);
}
Hope this helps you.
#include <stdio.h>
#include <stdlib.h>
struct{
char name[10];
int id;
int marks;
char grade;
}s[10];
int main()
{
int i;
for(i=0;i<sizeof(s);i++){
printf("name: ");
scanf("%s",s[i].name);
printf("id: ");
scanf("%d",&s[i].id);
printf("marks: ");
scanf("%d",&s[i].marks);
if(s[i].marks>=90)
s[i].grade='S';
else if(s[i].marks>=80)
s[i].grade='A';
printf("\n%s %d %d %c\n",s[i].name,s[i].id,s[i].marks,s[i].grade);
}
return 0;
}
This way you can add as many records as you want.
If you don't know the number of students at the time of coding this program you can always use linked lists and malloc to allocate memory dynamically although it's not safe especially if you have very limited memory resources for example in embedded systems case.
your code will be
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include<conio.h>
struct LinkedList{
char name[10];
int id;
float marks;
char grade;
struct LinkedList *next;
};
typedef struct LinkedList *node; //Define node as a pointer of data type struct LinkedList
node createNode(){
node temp; // declare a node
temp = (node)malloc(sizeof(struct LinkedList)); // allocate memory using malloc()
temp->next = NULL;// make next point to NULL
return temp;//return the new node
}
node addNode(node head,char* name, int id, float marks, char grade){
node temp,p;// declare two nodes temp and p
temp = createNode();//createNode will return a new node with data = value and next pointing to NULL.
strncpy(temp->name, name, 10); // add element's data part of node
temp->id = id; // add element's data part of node
temp->marks = marks; // add element's data part of node
temp->grade = grade; // add element's data part of node
if(head == NULL){
head = temp; //when linked list is empty
}
else{
p = head;//assign head to p
while(p->next != NULL){
p = p->next;//traverse the list until p is the last node.The last node always points to NULL.
}
p->next = temp;//Point the previous last node to the new node created.
}
return head;
}
char i, x;
node head; // declare The head
char name[10];
int id;
float marks;
char grade;
int main() {
printf("If you want to quit press q ,to continue press anything else");
i = getch();
while(i !='q'){
printf("\n Name : ");
fgets(name, 10, stdin);
printf("\n Id : ");
scanf("%d", &id);
printf("\n Marks : ");
scanf("%f", &marks);
printf("\n Grade : ");
scanf(" %c", &grade);
printf("\n name: %s id: %d marks: %.2f grade: %c\n", name, id, marks, grade);
addNode(head, name, id, marks, grade);
x = 'y';
do{
printf("\n If you want to quit press q ,to continue press anything else");
i = getch();
if(i=='q'){
printf("\n Are you sure you want to quit?");
printf("\n press y: for yes anything else: for NO");
x = getch();
}
}while(x !='y');
}
return 0;
}

Type casting node structure to print content

I am writing a binary tree program where each node in the tree contains a struct.
I am stuck on how to properly type cast the struct in order to print it's contents.
This is my struct definition:
//inventory definition
typedef struct inventory
{
char invName[36];
int invPartNo;
int invQOH;
float invUnitCost;
float invPrice;
}item;
//tree definition
struct btree {
void *data;
struct btree *left;
struct btree *right;
} ;
And in here I am trying to type cast the struct contents so I can print it:
void print_inorder(btree *node)
{
if(node == NULL)
{
return;
}
print_inorder((struct btree*)node->left);
//error here in these 5 lines: the node->data->invName, invPartNo, etc.
printf("Name: %s\n", (char)node->data->invName); //my incorrect attempt
printf("Part Number: %.5d\n", (int*)node->data->invPartNo);
printf("Quantity on hand: %d\n", node->data->invQOH);
printf("Unit Cost: %0.2f\n", node->data->invUnitCost);
printf("Price %0.2f\n\n", node->data->invPrice);
print_inorder(node->right);
}
I can suppose that you are having compilation errors.
Don't hesitate to use more brackets and you forgot to cast void* to item*:
printf("Name: %s\n", ((item*)(node->data))->invName);
printf("Part Number: %.5d\n", ((item*)(node->data))->invPartNo);
printf("Quantity on hand: %d\n", ((item*)(node->data))->invQOH);
printf("Unit Cost: %0.2f\n", ((item*)(node->data))->invUnitCost);
printf("Price %0.2f\n\n", ((item*)(node->data))->invPrice);
Define a (temporary) pointer to what you expect under the void-pointer:
item * pitem = node->data;
Test if it is pointing to something and print it:
if (NULL != pitem)
{
printf("Name: %s\n", pitem->invName);
printf("Part Number: %.5d\n", pitem->invPartNo);
printf("Quantity on hand: %d\n", pitem->invQOH);
printf("Unit Cost: %0.2f\n", pitem->invUnitCost);
printf("Price %0.2f\n\n", pitem->invPrice);
}
or assert if it's not valid:
assert(NULL != pitem);
printf("Name: %s\n", pitem->invName);
printf("Part Number: %.5d\n", pitem->invPartNo);
printf("Quantity on hand: %d\n", pitem->invQOH);
printf("Unit Cost: %0.2f\n", pitem->invUnitCost);
printf("Price %0.2f\n\n", pitem->invPrice);

Resources