I'm learning to use linkedlist, I feel I already understand the concept but when coding why do I always get an error (bus error)....this code can run, but only until "SCANF the NAME" after that an error appears.
typedef struct Student{
char name[20];
char idNum[10];
int saving;
struct Student *next;
}Student;
Student *head = NULL;
void insert_student(){
char *name,*idNum;
int saving;
Student *current;
Student *new_student;
new_student = (Student*)malloc(sizeof(Student));
// apakah ada memoory kosong?
if(new_student==NULL){
printf("==== YOUR MEMMORY IS FULL! ====\n");
exit(0);
}
printf("Enter your name : ");scanf("%[^\n]s",name);
printf("Enter your Id : ");scanf("%[^\n]s",idNum);
printf("How many your money : Rp");scanf("%d",&saving);
strcpy(new_student->name,name);
strcpy(new_student->idNum,idNum);
new_student->saving = saving;
new_student->next = NULL;
if(head==NULL){
head = new_student;
}
else{
current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = new_student;
}
}
void print_students(){
Student *current;
if(head==NULL){
printf("==== THERE IS NO STUDENT YET!\n");
exit(0);
}
current = head;
while (current!= NULL)
{
printf("Name : %s",current->name);
printf("id : %s",current->idNum);
printf("Saving : Rp%d",current->saving);
current = current->next;
}
}
int main(){
insert_student();
print_students();
return 0;
}
I'm hoping to create nodes for the dynamic linked-list Student and then display them
printf("Enter your name : ");scanf("%[^\n]s",name);
printf("Enter your Id : ");scanf("%[^\n]s",idNum);
You have to give named and idNum meaningful values before you pass their values to scanf. Instead, you are just passing uninitialized garbage value to scanf, which won't work. You must pass to scanf pointers to the place you want the strings you're reading in to be stored.
For starters it is a bad idea to make the functions to depend on the global variable head. In this case you will not be able to use more than one list in the program.
Within the function insert_student you declared uninitialized pointers name and idNum:
char *name,*idNum;
So using them in the calls of scanf
printf("Enter your name : ");scanf("%[^\n]s",name);
printf("Enter your Id : ");scanf("%[^\n]s",idNum);
invokes undefined behavior.
You need to declare character arrays instead of pointers
char name[20], idNum[10];
Also the format specifications are incorrect.
You should write
printf("Enter your name : "); scanf( " %19[^\n]", name );
printf("Enter your Id : "); scanf( " %9[^\n]", idNum );
Pay attention to the leading space in the format strings It allows to skip white space characters.
Otherwise after this call of scanf
printf("How many your money : Rp");scanf("%d",&saving);
the input buffer will contain the new line character '\n'. So when you will call the function insert_student a second time the first call of scanf (if the format specification does not contain the leading space)
printf("Enter your name : "); scanf( "%19[^\n]", name );
will read an empty string.
Also it is not a flexible approach when the whole program exits if a new node was not allocated.
if(new_student==NULL){
printf("==== YOUR MEMMORY IS FULL! ====\n");
exit(0);
}
It will be better to return to the caller an integer that will report whether the function was executed successfully. For example
int insert_student( void )
{
//...
Student *new_student;
new_student = (Student*)malloc(sizeof(Student));
int success = new_student != NULL;
if ( success )
{
printf("Enter your name : ");scanf("%[^\n]s",name);
printf("Enter your Id : ");scanf("%[^\n]s",idNum);
printf("How many your money : Rp");scanf("%d",&saving);
//...
}
return success;
}
Related
im curently working on linked list but to input some string ive veeb trying several ways to do it , i dont know what makes them error
this is my current code
struct barang{
char namabarang[30];
int hargabarang;
int idbarang;
struct barang* next;
};
struct barang *head;
void input()
{
struct barang *ptr;
char nama[30];
int harga,id;
ptr = (struct barang*)malloc(sizeof(struct barang *));
if(ptr == NULL)
{
printf("\n\n\tOVERFLOW!");
}
else
{
printf("\n\n\tSilahkan Masukan\n");
printf("\tNama barang : ");
fflush(stdin);
scanf("%[^\n]",nama);
strcpy(ptr ->namabarang,nama);
ptr-> next = head;
head = ptr;
printf("\n\tData Berhasil Disimpan di NODE awal!");
}
}
You are never consuming any newlines, so all the scanf after the first are not reading any data. Probably the simplest solution is to modify the scanf to be:
if( scanf(" %29[^\n]", ptr->namabarang ) != 1 ){
fprintf(stderr, "Invalid input\n");
exit(1);
}
By writing directly to ptr->namabrang, you can omit the strcpy. Adding the leading whitespace in the format specifier will cause subsequent scanf to consume the newlines, but will also trim any leading white space. If that is a problem, you should STOP USING SCANF. You should not be using scanf in any case, but that's another discussion. Also, adding the width modifier will prevent a buffer overflow.
I am creating a program that gets user input and puts it into a struct called Student before returning back to a main menu. From the main menu you can add another student. This works but when I try to print all of the Students data that has been added to the array of structs it only prints the last Student that was added.
Here is the struct:
struct Student
{
char* firstName;
int age, cuid;
float GPA;
};
This is how I'm allocating space for the array in main:
struct Student* studentArray = malloc(*recordMaxPtr * sizeof(struct Student));
Here are the functions that capture user input and print the array:
// Gets info and adds student to the array of structs
void addStudents(struct Student* s, int *numStudents)
{
// Allocate memory for the first name
char *firstName = (char*) malloc(25*sizeof(char));
// Gets the name of student
printf("What is the name of the student you'd like to add? ");
gets(s->firstName);
printf("\n"); // blank line
// Gets age of student
printf("How old is the student? ");
scanf("%d", &s->age);
printf("\n"); // blank line
// Gets CUID
printf("What is his / her CUID number? ");
scanf("%d", &s->cuid);
printf("\n"); // blank line
// Gets GPA
printf("What is the student's GPA? ");
scanf("%f", &s->GPA);
printf("\n"); // blank line
}
// Sorts the array and then lists all of the saved students
void printStudents(struct Student* s, int *numStudents)
{
//bsort();
for (int i = 0; i < *numStudents; i++)
{
printf("Student #%d\n", i + 1);
printf(" Student's Name: %s\n", s[i].firstName);
printf(" Age: %d\n", s[i].age);
printf(" CUID: %d\n", s[i].cuid);
printf(" GPA: %2f\n", s[i].GPA);
}
}
I thought about trying to use a for loop to gather all of the student's data that I need at once but this is a school project and I'm not allowed to do it that way. I've been trying to figure this out for a while and I've sort of hit a brick wall on what to do. My best guess is that data is getting overwritten every time you enter a new student to the array but I'm not sure how to fix that.
You allocated a memory for the first name, but didn't save that anywhere. You have to store the address to the structure.
// Allocate memory for the first name
char *firstName = (char*) malloc(25*sizeof(char));
s->firstName = firstName; // add this
Also here are some more things to do for better code:
Check if malloc() succeeded
Check if scanf() succeeded
Replace gets() with fgets() and removal of newline character (gets() has unavoidable risk of buffer overrun and removed from new C specification)
Remove the cast of result of malloc() (c - Do I cast the result of malloc? - Stack Overflow)
I am creating a singly linked list with just a single node and I am having some trouble with getting it to work as I want it to. When I enter the information I want to place in the list I am getting my last piece of data to append to the previous one without my doing. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define maxName 30
#define maxID 10
#define maxAge 3
typedef struct node
{
char fName[maxName];
char lname[maxName];
char PUID[maxID];
char age[maxAge];
struct node *next;
}node;
node *head = NULL;
//This function will create a list with just a single node and the data to the list must be passed by paramter
node * createnode(char firstName[], char lastName[], char puid[], char age[])
{
head = (node*)malloc(sizeof(node));
printf("Enter the first name: ");
scanf("%s", &(head -> fName));
printf("Enter the last name: ");
scanf("%s", &(head -> lname));
printf("Enter the PUID: ");
scanf("%s", &(head -> PUID));
printf("Enter the Age: ");
scanf("%s", &(head -> age));
return head;
}
And this is the output I am getting when I enter the information:
JAke,Thomas,789456987525,25->
That 25 is appending to the end of the PUID I enter. Any help you be awesome! Thank you!
You should remove address operators.
printf("Enter the first name: ");
scanf("%s", (head -> fName));
printf("Enter the last name: ");
scanf("%s", (head -> lname));
printf("Enter the PUID: ");
scanf("%s", (head -> PUID));
printf("Enter the Age: ");
scanf("%s", (head -> age));
This function declaration
node * createnode(char firstName[], char lastName[], char puid[], char age[]);
does not make sense because the parameters are not used in the function.
So the function should be declared like
node * createnode( void );
Within the function statements like this
scanf("%s", &(head -> fName));
^^^
are incorrect. They must look like
scanf("%s", head -> fName);
As for the wrong output then it seems you are entering more characters in a character array than it can hold including the terminating zero of string.
For example the entered symbols 7894569875 will be stored in the data member PUID like string "7894569875" that contains 11 characters (including the terminating zero character) instead of 10.
It is more safe to use the function fgets instead of scanf with the format specifier %s.
For example
#include <string.h>
//...
fgets( head->fName, maxName, stdin );
head->fName[ strcspn( head->fName, "\n" ) ] = '\0';
Pay attention to that it is a bad idea when a function depends on a global variable. In this case you will be unable for example to have to lists in a program.
I'm newbie here and there is some question that I want have some lesson from you guys.
For example:
#include <stdio.h>
#include<stdlib.h>
#include<ctype.h>
void main()
{
char name[51],selection;
do
{
printf("Enter name: ");
fflush(stdin);
fgets(name,51,stdin);
printf("Enter another name?(Y/N)");
scanf("%c",&selection);
selection=toupper(selection);
}while (selection=='Y');
//I want to printout the entered name here but dunno the coding
printf("END\n");
system("pause");
}
As I know when the loops perform will overwrite the variable then how I perform a coding that will printout all the name user entered?
I have already ask my tutor and he is ask me to use pointer, can anyone guide me in this case?
You've basically got two options, create a list of all the names, looping through each of them at the end, or concatenate all the names into a string as you read them, and print that whole buffer at the end. The first goes roughly like this:
char ch[2]="Y", names[100][52]; //store up to 100 50-char names (leaving space for \n and \0)
int x, nnames=0;
while(nnames<100 && *ch=='Y'){
fgets(names[nnames++], sizeof names[0], stdin); //since names is a 2d array, look
//only at the length of a row, (in this case, names[0])
fgets(ch, 2, stdin);
*ch = toupper(*ch);
}
for(x=0; x<nnames; x++)
//print names[x].
And the second goes roughly like this:
char names[100*52], *np=names, *ep=names+sizeof names; //an array, the position, and the end
char ch[2]="Y";
while(np<ep && *ch=='Y'){
fgets(np, ep-np, stdin); //read a name, and a newline into the buffer
//note how I use the difference between the end and the position to tell
//fgets the most it can possibly read
np+=strlen(np); //advance the position to the end of what we read.
//same deal with the y/n stuff...
}
printf("%s", names);
Notice the lack of loop at the end, because the whole string is stored in names.
Use a single string to get all names:
char allnames[1000] = "";
do {
//get name in fgets
selection = toupper(selection);
strcat(allnames, selection);
//Check for repetion
} while (/*there is repetion*/);
printf("%s", allnames);
You've to select the size of allnames suitably to store all names.
You can use a linked list to store all the entered names. All data structure books talk about linked list a lot.
#include <stdio.h>
#include <stdlib.h>
struct name_node
{
char name[100];
struct name_node *next;
};
struct name_node* add_name(struct name_node *first, const char *name)
{
struct name_node *p;
/* create our node */
p = (struct name_node*)malloc(sizeof(struct name_node));
strcpy(p->name, name);
p->next = NULL;
/* link our node to the tail */
if (first) {
for (; first->next; first = first->next);
first->next = p;
}
return p;
}
void print_names(struct name_node *first)
{
/* print names stored in the list */
for (; first; first = first->next) {
printf("%s\n", first->name);
}
}
/* free the memory we used */
void destroy_list(struct name_node *first)
{
if (first) {
if (first->next)
destroy_list(first->next);
free(first);
}
}
int main(void)
{
struct name_node *head = NULL;
struct name_node *node;
char name[100];
char selection;
do {
printf("Enter name: ");
fflush(stdin);
fgets(name, 51, stdin);
/* save the user input to a linked list */
/* save head if we don't have head */
node = add_name(head, name);
if (!head)
head = node;
printf("Enter another name?(Y/N)");
scanf("%c", &selection);
selection = toupper(selection);
}
while (selection == 'Y');
/* print the list if we have any data */
if (head)
print_names(head);
/* free the memory we used */
destroy_list(head);
printf("END\n");
system("pause");
return 0;
}
Hii ,
I have been trying to write a program... We have a structure which has a rank field and the name field.The pointer to this structure is stored in an array of fixed size. I have implemented it as follows and i have certain problems...
The code i have written is :
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct
{
int rank;
char *name;
}node;
int insert(node **a , char name[] , int *rank)
{
if(*rank >= 5)
{
printf("\n Overflow ");
return 0;
}
(*rank)++;
node *new = (node *)malloc(sizeof(node));
new->name = name;
new->rank = *rank;
a[*rank] = new;
return 0;
}
int delete(node **a , int *rank)
{
int i = *rank;
if(*rank<0)
{
printf("\n No elements");
return 0;
}
printf("\n Deleting %d , %s ",((a[*rank]))->rank,((a[*rank]))->name);
printf("\n Reordering the elements ");
while(i<5)
{
a[i] = a[i+1];
}
return 0;
}
int display(node **a , int rank)
{
while(rank>0 && (a[rank])>0)
{
printf(" rank = %d name = %s \n",((a[rank])->rank),((a[rank])->name));
rank--;
}
return 0;
}
int main()
{
node *a[5] = {NULL};
char ch = 'y';
int choice,rank = -1;
char name[10];
while(ch!='n' || ch!= 'N')
{
printf("\n Enter 1 to insert , 2 to delete , 3 to display and 4 to exit \n");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("\n Enter name to insert");
gets(name);
insert(a,name,&rank);
break;
case 2:
printf("\n Enter rank to delete ");
scanf("%d",&rank);
delete(a,&rank);
break;
case 3:
display(a,rank);
break;
case 4:
exit(0);
default:
printf("\n Invalid choice...please enter again ");
break;
}
ch = getchar();
}
return 0;
}
First thing is the system automatically takes the choice except for the first time...(i couldn't find the fault there...) and i am a bit confused about this pointer stuff...Please see if its alright...Any corrections are welcome and please give me some explanation as to why it is wrong and how we shd do it...
Thank You
First of all, all your functions always return 0 -- even for an error condition. Life would be so much easier, if you passed rank in as an int, and returned it's new value.
rank = insert(a, name, rank);
/* : */
/* : */
int insert(node **a , char name[] , int rank)
{
if(rank >= 5)
{
printf("\n Overflow ");
return 0;
}
rank++;
node *new = (node *)malloc(sizeof(node));
new->name = name;
new->rank = rank;
a[rank] = new;
return rank;
}
It's been many years since I last used scanf, but as I recall, you must account for every character in the stream, meaning,"Don't forget the Enter".
scanf("%d\n",&choice);
Also with gets(name);, if you type more tha 9 characters, you are quite screwed, as it will overwrite the stack of your program.
UPDATE:
Also, you have two ways to exit this program, except one will never work. You could choose option "4" which will call exit(0). Alternately, at the end of each command, you wait for a character before stepping over. It appears you want to be able to enter "N" ther and exit, except that won't work:
while(ch!='n' || ch!= 'N')
for that to evaluate to false, ch must be both "n" & "N" at the same time. You really want
while(ch!='n' && ch!= 'N')
UPDATE2:
I just noticed the biggest problem in you code. name everywhere in your code only ever points to the single array defined in main(). Everytime you enter a new name, it overwrites that array, and since every node points to that one array, the name changes everywhere. You need to make a copy.
in insert():
node *new = (node *)malloc(sizeof(node));
new->name = strdup(name); // use malloc internally.
Then in delete() you'll have to free that memory (speaking of which, you need to free node there too...)
printf("\n Deleting %d , %s ",((a[*rank]))->rank,((a[*rank]))->name);
free(a[*rank]->name);
free(a[*rank]);
printf("\n Reordering the elements ");
Remember, Whenever you call malloc, you will eventually have to call free.
I'm confused as to the use of the "rank" variable. Main uses it as an index to the last node in the array, and the nodes use it as a ranking. Adding nodes increases it, but deleting nodes doesn't decrease it.
In the very least, I'd suggest separate the index variable from the ranking variable to make the logic easier to follow.
Personally, I'd write a structure to encapsulate the array with its own index tracking and add/delete functions. That way Main is free to read in user options and manipulate rank of new nodes without worrying about data structure details.
while(ch!='n' || ch!= 'N')
{
printf("\n Enter 1 to insert , 2 to delete , 3 to display and 4 to exit \n");
scanf("%d",&choice); getchar();
.
.
.
//ch = getchar();
}
Using getchar() along with scanf() causes this problem. Since '\n' after reading a character into 'ch' goes as an input to scanf. One way to resolve your problem is read that '\n' with an extra getchar() before it is read by gets().
Also you should modify while loop in delete.