how do i input string in Linked List - c

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.

Related

(C programming) bus error on my linked list

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;
}

Printf statments not printing in order

typedef struct node_s{
int data;
struct node_s *next;
}node_t;
void insert(node_t *pointer, int data){
while(pointer->next != NULL){
pointer = pointer->next;
}
pointer->next = (node_t *)malloc(sizeof(node_t));
pointer = pointer->next;
pointer->data = data;
printf("Elemnet inserted\n"); //2. Followed by this statment once done.
pointer->next = NULL;
}
int main(){
node_t *start, *temp;
start = (node_t *)malloc(sizeof(node_t));
temp = start;
temp->next = NULL;
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Print\n");
printf("4. Find\n");
while(1){
int input;
scanf("%d\n", &input);
if(input==1){
int data;
printf("Input data\n");//1. I want this to print out first once I give 1 input.
fflush(stdout);
scanf("%d", &data);
insert(start, data);
}
}
When I compile and execute, I can give inputs but the order of printf statements are not in sequence. For instance, this is how I get the output after I give input and enter the data.
sh-4.1$ ./linked_list
1. Insert
2. Delete
3. Print
4. Find
1
23
Input data
Elemnet inserted
1
45
Input data
Elemnet inserted
I tried adding fflush(stdout), after the printf statment as well.
Remove \n from the very first scanf
scanf("%d\n", &input);
What is that \n doing there? That is what is causing your scanf to "linger", waiting for extra input, instead of terminating immediately.
That \n has special meaning for scanf. When you use a whitespace character (space, tab or \n) in scanf format specifier, you are explicitly asking scanf to skip all whitespace. If such character is used at the very end of scanf format string, then after reading the actual data scanf will continue to wait for input until it encounters a non-whitespace character. This is exactly what happens in your case.
In addition to removing \n from your scanf statements, be aware that scanf will read the data from the command line, filling the variable specified, but it will leave the \n in the input buffer causing problems the next time scanf is called. Since there is no standard command to flush input buffers, you are responsible for insuring that you do not have extraneous unused characters in the input buffer the next time scanf is called. One simple way to handle manually flushing the input buffer after each scanf if to simply use getchar() to read any remaining characters in the input buffer until \n is encountered. For example:
int c;
...
scanf ("format", &var);
do {
c = getchar();
while ( c != '\n' );
This will insure subsequent calls to scanf retrieves the wanted data instead of passing the characters that remain in the input buffer.

Linked list trouble

Does anyone know what might be the problem with the following code? When I run it, I get the following output:
Insert a value in the list: 1
Do you want to continue? y/N:
1 ->
The fact is that the do-while loop executes until the scanf("%c", &ch) statement, and then it jumps out (so I cannot provide any input for the ch variable). I tried debugging with GDB and I got some weird messages:
GI___libc_malloc (bytes=16) at malloc.c:malloc.c: No such file or directory.
Also, it says that the compiler couldn't find the vscanf.c file. Does anyone have an explanation for this strange behavior? Thanks! (The intention was to print the values of a singly linked list in reverse order.)
#include <stdio.h>
#include <stdlib.h>
struct node{
int info;
struct node* next;
};
struct node* head = 0;
void add_node(int value){
struct node* current = malloc(sizeof(struct node));
current->info = value;
current->next = head;
head = current;
}
void print_node(struct node* head){
while(head){
printf(" %d -> ", head->info);
head = head->next;
}
printf("\n");
}
int main(void){
int val;
char ch;
do {
printf("Insert a value in the list: ");
scanf("%d", &val);
add_node(val);
printf("Do you want to continue? y/N: ");
scanf("%c", &ch);
} while(ch == 'y' || ch == 'Y');
printf("\n");
print_node(head);
return 0;
}
If you want the input to be separated by a new line (which it appears that you do) then change the format of how you are reading in your character. Change following:
scanf( "%c", &ch );
... to this:
scanf( "\n%c", &ch ); // << Note, \n to pickup newline before reading the value.
You can check for proper input in an if-else block, and execute your code accordingly.
For example, here is something I would do if I needed to check whether the user wants to continue or not:
char chTemp; //Declare a test variable to check for newline
printf("Do you want to continue? y/N: ");
if (scanf("%c%c",&ch,&chTemp) != 2 || chTemp != '\n')
{
printf("Error in input (Integer input provided)");
}
else
{
//Do stuff.
}
Not only will it solve your problem, but it will also check for careless integer inputs.
The problem you are encountering is because the once you type a value for val and then press enter , then \n still remains in the input buffer . Hence , the next scanf assumes that \n which is still in the input buffer is its input , and consumes it and then loop exits .
Other Solutions :-
1) scanf("%d%*c",&val);
This would assign the first input character to val and then anything after that would be eaten up . Hence , the \n would not go into the next scanf
2) scanf("%[^\n]%*c",&val);
This would assign the anything to the val except \n and then \n would be eaten up .

Segmentation Fault during linked list in c

I am getting a segfault when I try and print out my linked list. Can anyone explain why? I am aware a segfault means that I am accessing memory I am not supposed to. I am assuming this means I am not setting up my pointers right. Any help would be great. My code...
#include <stdio.h>
#include <stdlib.h>
struct node
{
int val;
struct node *next;
}*head;
typedef struct node item;
int main() {
item *curr, *head;
head = NULL;
char word = 'y';
//int num[10];
//int i = 0;
while (word == 'y'){
printf("Would you like to enter an integer? (y/n) ");
scanf("%s", &word);
if(word == 'y'){
int temp = 0;
printf("Enter an integer: ");
scanf("%d", &temp);
curr = (item *)malloc(sizeof(item));
curr->val = temp;
if (head == NULL){
head = curr;
head->next = NULL;
}
else {
curr->next = head;
head = curr;
}
}
}
curr = head;
while(curr != NULL) {
printf("%d\n", curr->val); //seg fault happens here
curr = curr->next ;
}
return 0;
}
This:
scanf("%s", &word);
is a buffer overflow, since %s will read a string, but you only have a single character. This invokes undefined behavior; even if you enter just a single character, scanf() will add 0-termination after that character to make a proper string.
Change the declaration of word:
char word[32];
And scan with an explicit size, to prevent scanf() from writing outside the buffer:
scanf("%30s", word);
Also check the return values of all I/O and memory allocation calls, since they can fail.
Finally, don't cast the return value of malloc(), in C.
Regarding the memory leaks, can I suggest you fix them with the following code:
while(curr != NULL) {
item* temp = curr; // store the current pointer
printf("%d\n", curr->val);
curr = curr->next ;
free(temp); //free the current one now that curr points to the next
}
This frees the already printed head in each iteration of the loop.
The other issues are already addressed by other posters.
Initialize the *head pointer as
item *curr=NULL, *head = NULL;
without this, the if will not execute and you would access some random memory for head node. The while loop for printing the linked list may not terminate and keep accessing invalid memory.
if (head == NULL){
...
}
You have been caught out by scanf. First you wish to read a single character and the format for that is %c - %s reads the next non-blank sequence of characters after skipping any leading whitespace. Using %s causes the error, as it overwrites memory.
However if you change the format to %c your code still won't work, and it's scanf again. For most formats scanf will skip leading whitespace, but it does not do this when reading characters. So if you run your code you will see this:
Would you like to enter an integer? (y/n) y
Enter an integer: 10
Would you like to enter an integer? (y/n) 10
The second time around scanf has read the newline after the 10 into word, that is not a y, and then moved on to print out your list - the 10 at the end.
To skip whitespace before a character you add a space into the format string, so the line becomes:
scanf(" %c", &word);
That one change will allow your code to work but you should really do more checking. scanf will return the number of items it successfully found, you should check that to make sure the user really did enter a number etc., etc. As an example here is what happens if the user accidentally enters y twice:
Would you like to enter an integer? (y/n) y
Enter an integer: y
Would you like to enter an integer? (y/n) Enter an integer:
What has happened here is scanf("%d", &temp) failed, returned 0, and stored nothing into temp. However as you did not check the result your program continues and then the second y is consumed by the next scanf(" %c", &word).
Also look at your if (head == NULL) statement - this is not really necessary at all, you can replace the whole if/else with just two lines... that is left as an exercise.
HTH

gets() does not read user input

I am new to linked list, now I have little problems in population of nodes.
Here I could populate first node of linked list but the gets() function doesn't seems to pause the execution to fill the next node.
Output is like:
Var name : var
Do you want to continue ?y
Var name : Do you want to continue ? // Here I cannot input second data
Here is my code:
struct data
{
char name[50];
struct data* next;
};
struct data* head=NULL;
struct data* current=NULL;
void CreateConfig()
{
head = malloc(sizeof(struct data));
head->next=NULL;
current = head;
char ch;
while(1)
{
printf("Var name : ");
gets(current->name); //Here is the problem,
printf("Do you want to continue ?");
ch=getchar();
if(ch=='n')
{
current->next=NULL;
break;
}
current->next= malloc(sizeof(struct data));
current=current->next;
}
}
This happens because:
ch=getchar();
read either y or n from the input and assigns to ch but there a newline in the input buffer which gets read by the gets in the next iteration.
To fix that you need to consume the newline following the y/n the user enters. To do that you can add another call to getchar() as:
ch=getchar(); // read user input
getchar(); // consume newline
Also the function fgets should be used in place of gets. Why?
It's exactly what #codaddict said. You need to clean the buffer.
void fflushstdin( void )
{
int c;
while( (c = fgetc( stdin )) != EOF && c != '\n' );
}
You can read this links that explains it very well:
c-faq
And this mdsn if you are on windows.
One more thing, try to always use fgets -instead of gets-, as it is impossible to prevent buffer overflows if you are using gets.
You could read the section "Use of safe libraries" at this link
you should also add a line like
current->next = 0;
after
current=current->next;
to ensure that the last element's next is not dangling.

Resources