473,498 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Garbage value reading due to buffering problem

32 New Member
I have seen a simple program for handling Link List operations. The following is the part of the code that contains the problem. The code is modified but contains all necessary information regarding the problem.
Expand|Select|Wrap|Line Numbers
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<conio.h>
  4.  
  5. struct llist
  6. {
  7.     int val;
  8.     struct llist *next;
  9. };
  10. typedef llist item;
  11.  
  12. void llist(item **head);
  13.  
  14. void main()
  15. {
  16.     item *head;
  17.     llist(&head);
  18. }
  19.  
  20. void llist(item **head)
  21. {
  22.     int i=1, no;
  23.     char ch='y';
  24.     item *curr, *temp;
  25.  
  26.     while(ch=='y')
  27.     {
  28.         printf("Enter no: ");
  29.         scanf("%d",&no);
  30.  
  31.         if(i==1)
  32.         {
  33.             (*head)=(item*)malloc(sizeof(item));
  34.             (*head)->val=no;
  35.             (*head)->next=NULL;
  36.             temp=(*head);
  37.             i++;
  38.  
  39.             printf("After First node allocation : *head = %u  temp = %u\n\n",*head, temp);
  40.         }
  41.         else
  42.         {
  43.             printf("Before next node allocation : temp = %u\n", temp);        
  44.  
  45.             curr=(item*)malloc(sizeof(item));
  46.             curr->val=no;
  47.             curr->next=NULL;
  48.             temp->next=curr;
  49.             temp=curr;
  50.  
  51.             printf("After compliting next node allocation : curr=%u  temp=%u\n\n",curr,temp);        
  52.         }
  53.  
  54.         printf("Do you want to add node?(y/n) : ");
  55.         scanf("%s",&ch); /**** Use %c here ****/
  56.     }
  57. }
In this, the link list is created and initialized. There are certain printf() statements I've inserted for better understanding of the problem. The llist() function prompts the user to enter a number, creates a node, initializes it and attaches it to LL, and then asks user if he has any node to be inserted. The choice is read in a "char" variable "ch" which is initialized to 'y'.
1. If we use "scanf("%c",&ch);", it never accepted the choice "ch" and directly returned to main().
2. If we use string format specifier %s in place of %c (as used in above code snippet), it accepts choice "ch", but manipulates the addresses of LL. The following is a sample output. It will give an Idea what is happening.
Expand|Select|Wrap|Line Numbers
  1. Enter no: 123
  2. After First node allocation : *head = 3289416  temp = 3289416
  3.  
  4. Do you want to add node?(y/n) : y
  5.  
  6. Enter no: 234
  7. Before next node allocation : temp = 3289344
  8. After completing next node allocation : curr=3289432  temp=3289432
  9.  
  10. Do you want to add node?(y/n) : y
  11.  
  12. Enter no: 345
  13. Before next node allocation : temp = 3289344
  14. After completing next node allocation : curr=3289448  temp=3289448
  15.  
  16. Do you want to add node?(y/n) : y
  17.  
  18. Enter no: 456
  19. Before next node allocation : temp = 3289344
  20. After completing next node allocation : curr=3289464  temp=3289464
  21.  
  22. Do you want to add node?(y/n) : n
3. When we use "int ch" in place of "char ch", and give option as "Enter 0 for exit" and do necessary modifications in code, the whole thing works perfectly and we get desired output.

So, I don't understand why it is not accepting "char" (%c) but accepts "string" (%s) but gives problem and why no problem with "int"(%d)? How is it related to keyboard buffer? Please explain this.
Thank you.
Jan 5 '09 #1
8 7345
gpraghuram
1,275 Recognized Expert Top Contributor
Hi,
The problem is becos STDIN has some characters which the scanf if reading and not waiting for your prompt.
You can use fflush(STDIN) befor using scanf.
but fflush(STDIN) is not the right way to do it.

Raghu
Jan 5 '09 #2
Aftabpasha
32 New Member
@Raghu
Thanks for your reply.
The reason given by you can satisfy the problem when we accept "ch" as "char" i.e. using %c as format specifier.

But when we are using "%s", it is accepting 'y' properly. If there are some characters left in buffer then it should read some garbage value.in place of 'y' also.
Here, it is accepting 'y' properly but causing the value of "temp" to change.

And when we use "int ch"(%d) in place of "char ch"(%c or %s) and end the loop when ch=0, then it works perfectly. Here why the garbage values are not being read?

I just want to know, if there are garbage values present in buffer, why they are affecting differently? Is it due to different alignment of different datatypes & there respective sizes in memory? I think alignment and size of different datatypes are the most probable reasons.
Please explain these with example if possible.
Jan 5 '09 #3
Banfa
9,065 Recognized Expert Moderator Expert
You can not use ch, a char, to accept input from %s. The minimum number of bytes written by %s is 2, so you will write to memory outside the limits of the variable ch corrupting other variables and producing undefined behaviour.

%c doesn't work properly when used just after %d because there are extra characters (\n) in the input stream that %d has not read but that will be read by %c.

You need to empty the input stream before calling scanf with %c. However you should not that calling fflush on stdin or any input stream is undefined behaviour according to the standard. The only real way to clear the input stream is to read characters until it is empty.

Things to Avoid in C/C++ -- fflush(stdin), Part 2 - GIDNetwork
Jan 5 '09 #4
Aftabpasha
32 New Member
@ Banfa
Thanks for your reply.
Now, I got this.
1. %s is accepting character ('y') correctly, but violating memory. Hence, the LL is getting corrupted.
2. When read as "char"(%c), due to scanf() problem, it is reading some accidentally left characters (probably '\n') as a wrong answer.

So, the whole problem is due to scanf() leaving some data unread in buffer.
But this accidentally left values should also affect integers. Here when I change "char ch" to "int ch" and continues accepting values (to be inserted in LL) from user while(ch != 0), it works perfectly. When I input 0 as my choice, it accepts 0 exactly, and not a single bit of it as garbage. If there are some unread bits left in buffer, they should be read in the "int" too, giving a non-zero value even if we enter a 0.
Please explain why this happening?
Thank you.
Jan 5 '09 #5
Banfa
9,065 Recognized Expert Moderator Expert
That is easy to explain, when you ask for an integer \n is not a valid character however it is white space. scanf will skip white space looking for the start of a numeric type (integer %d or float %f) because that is how you would want a user interface to work. You would not want your user interface to fail to convert a number just because the user had typed a few spaces first. So although a \n is left in the input stream when you ask for a int %d scanf automatically discards it before reading the provided digit 0.

However when you ask scanf for a character %c, \n is a perfectly valid character so that is what scanf returns.

Try this program

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2.  
  3. int main(int argc, char *argp[])
  4. {
  5.     int n[3];
  6.     char ans[3];
  7.  
  8.     printf("Input an integer: ");
  9.     scanf ("%d",&n[0]);
  10.     printf("\nInput another integer: ");
  11.     scanf ("%d",&n[1]);
  12.     printf("\nInput a final integer: ");
  13.     scanf ("%d",&n[2]);
  14.     printf("\nNow give me an answer yes or no (y/n):");
  15.     scanf ("%c",&ans[0]);
  16.     scanf ("%c",&ans[1]);
  17.     scanf ("%c",&ans[2]);
  18.  
  19.     printf("\n\nI read the integers: %d %d %d\n", n[0], n[1], n[2]);
  20.     printf("\n\nI read the character values: %d %d %d\n", ans[0], ans[1], ans[2]);
  21.  
  22.     return 0;
  23. }
  24.  
Note at the end although it asks for a single character the program then reads 3. The \n from the previous input and the \n from the current input with the actual input between them.
Jan 5 '09 #6
Aftabpasha
32 New Member
@Banfa
Thank you for your clear & informative replies.
All of my confusions about those garbage values are removed now.
The code you've provided was certainly helpful to me.
Just a single question. It's about the code from you. Why have you used
Expand|Select|Wrap|Line Numbers
  1. int main(int argc, char *argp[])
I mean you could have simply used
Expand|Select|Wrap|Line Numbers
  1. int main()
in place of it.
Is it a better practice to use such syntax?(Command Line Interface to your program).
Thanks again.
Jan 5 '09 #7
Banfa
9,065 Recognized Expert Moderator Expert
I used it because of habit mainly, it is not better (or best) practice. I have been writing main like that for 20 years now so that is how I write it even if there is no command line parameters.

Of course the fact that I never typed the main line of that program but copied it from another program could also have something to do with it :D
Jan 5 '09 #8
Aftabpasha
32 New Member
Well, I m just a beginner...and hope I'll also have some habit after 20 years (of course a good one).
Once again thank you all for your replies.
Jan 5 '09 #9

Sign in to post your reply or Sign up for a free account.

Similar topics

24
2712
by: Hendrik Schober | last post by:
Hi, I have a 'std::istream' and need to read its whole contents into a string. How can I do this? TIA; Schobi
3
6936
by: David Merrick | last post by:
Hi ! can any of you help ? Since datasheets and forms can happily display calculated fields over 255 characters long, I was surprised to discover that the same when read via a DAO recordset...
50
4876
by: Michael Mair | last post by:
Cheerio, I would appreciate opinions on the following: Given the task to read a _complete_ text file into a string: What is the "best" way to do it? Handling the buffer is not the problem...
5
3553
by: Bob lazarchik | last post by:
Hello: We are considering developing a time critical system in C#. Our tool used in Semiconductor production and we need to be able to take meaurements at precise 10.0 ms intervals( 1000...
18
2167
by: Larry Herbinaux | last post by:
I'm having issues with garbage collection with my long-standing service process. If you could review and point me in the right direction it would be of great help. If there are any helpful...
28
3129
by: Goalie_Ca | last post by:
I have been reading (or at least googling) about the potential addition of optional garbage collection to C++0x. There are numerous myths and whatnot with very little detailed information. Will...
11
2048
by: japhy | last post by:
Is there a way to read a line (a series of characters ending in a newline) from a file (either by descriptor or stream) atomically, without buffering additional contents of the file?
0
1356
by: Kyle Lanclos | last post by:
I've done a lot of web searching, a fair bit of C-source reading, and quite a lot of miscellaneous head scratching, and I find that I am not necessarily closer to an ideal solution. I have a...
5
705
by: Luis Zarrabeitia | last post by:
I have a problem with this piece of code: ==== import sys for line in sys.stdin: print "You said!", line ==== Namely, it seems that the stdin buffers the input, so there is no reply until ...
0
7002
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7205
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6887
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
1
4910
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4590
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3093
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3085
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
656
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
291
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.