C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old February 25th, 2006, 11:05 PM
kuza55's Avatar
kuza55 kuza55 is offline
It's only wrong if you're caught....
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Dec 2003
Location: Sydney, Australia
Posts: 1,286 kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 3 Weeks 3 Days 6 h 10 m 16 sec
Reputation Power: 173
Clearing the input buffer (stdin)

Hi guys,

I'm trying to learn C (wht varying results, ), and I'm trying to input 2 strings of a fixed length (so I'm using fgets so as not to get buffer overflows) into 2 seperate character arrays, and then print them out (nothing too complex).

So far this is what I've got:
c Code:
Original - c Code
  1. # include <stdio.h>
  2.  
  3. int main () {
  4.    
  5.     char *c, *d;
  6.  
  7.     c = malloc (16);
  8.     d = malloc (16);
  9.  
  10.     fgets (d, 16, stdin);
  11.  
  12.     //clear stdin buffer
  13.  
  14.     fgets (c, 16, stdin);
  15.    
  16.     printf ("%s - %s\n", c, d);
  17.    
  18.     return 0;
  19. }


Anyway, what I'm trying to figure out is how to clear the input buffer, because if you input more than 16 bytes it stays in the stdin buffer, and so the user isn't asked for more data a second time.

I've tried using fflush(stdin) (even though its not supposed to clear input buffers), fseeking to the end of the stream (which I thought should have worked...), and also rewinding as well, none of those attempts have worked. So yeah, if anyone can explain to me how i should go about cleaing stdin, I'd appreciate it.

I've thought of doing something like checking if there's a new line inside the first variable, and if so, then your buffer is clear, but if there isn't either keep fgets()-ing of fgetc()-ing untill you get a new line character, and once you do stop and free your buffer into which you've been either fgets/c()-ing into.

But I would have thought there'd be some kind of built in function which would do what I needed it to.

I'm compiling with GCC 3.3.6 under Slackware 10.2, if that helps...

Also I get the following warnings when compiling:
Code:
malloc.c: In function `main':
malloc.c:8: warning: assignment makes pointer from integer without a cast
malloc.c:9: warning: assignment makes pointer from integer without a cast
And since I'm new to C I have no idea what I should do (I'm guessing malloc returns an integer and I needed to cast it to a pointer or something, but thats a guess)....and since the guide I'm learning from (http://beej.us/guide/bgc/output/html/index.html) has code which generates the same warning, I'm not sure what I should do....
__________________
- Alex
Web Security Research (my blog)
Handbook of Applied Cryptography (Free!)

Reply With Quote
  #2  
Old February 25th, 2006, 11:09 PM
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline
Contributing User
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Apr 2004
Posts: 1,676 Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 1 Month 3 Days 8 h 23 m 46 sec
Reputation Power: 132
Comments on this post
kuza55 agrees: Thanks.
__________________
Any advertisement triggered by IntelliTxt in this post is not endorsed by the author of this post.

Reply With Quote
  #3  
Old February 26th, 2006, 12:25 AM
Matschie Matschie is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2006
Posts: 8 Matschie New User: is a brand new recruit and a unknown entity at this point. 
Time spent in forums: 2 h 17 m 39 sec
Reputation Power: 0
to help ya out a little with the warnings you are getting, all you nead to do is cast your malloc, and since your variables are char *, go at it like that.

Code:
...
    char *c, *d; 

    c = (char *)malloc (16);
    d = (char *)malloc (16);
...
Comments on this post
Dave Sinkula disagrees: Learn before you teach.

Reply With Quote
  #4  
Old February 26th, 2006, 12:45 AM
kuza55's Avatar
kuza55 kuza55 is offline
It's only wrong if you're caught....
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Dec 2003
Location: Sydney, Australia
Posts: 1,286 kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 3 Weeks 3 Days 6 h 10 m 16 sec
Reputation Power: 173
Quote:
Originally Posted by Dave Sinkula

Thanks, that works, is there much overhead with getting data character by character from the input, rather than getting chunks and then searching then?

Also, i was wondering if there's anhything wrong with defining a macro in the preprocessor to do this (so that I don't have to trype that whole thing out every time, and don't get any function overhead) like so:
c Code:
Original - c Code
  1. #include <stdio.h>
  2.  
  3. #define CLEARBUF() char ch; while ((ch = getchar()) != '\n' && ch != EOF);
  4.  
  5. int main () {
  6.    
  7.     char *c, *d;
  8.     int i;
  9.  
  10.     c = malloc (16);
  11.     d = malloc (16);
  12.  
  13.     fgets (d, 16, stdin);
  14.  
  15.     CLEARBUF()
  16.  
  17.     fgets (c, 16, stdin);
  18.    
  19.     printf ("%p - %p\n", c, d);
  20.     printf ("%s - %s\n", c, d);
  21.    
  22.     return 0;
  23. }
If so I'd love to hear it.

Quote:
Originally Posted by Matschie
to help ya out a little with the warnings you are getting, all you nead to do is cast your malloc, and since your variables are char *, go at it like that.

Code:
...
    char *c, *d; 

    c = (char *)malloc (16);
    d = (char *)malloc (16);
...
That solves my warnings, but Dave seems to think there's something wrong with that it seems.....So if anyone would care to enlighten me?

And if anyone can be bothered to explain, could someone tell me what problems I could have run into if I hadn't cast them to pointers?

Reply With Quote
  #5  
Old February 26th, 2006, 12:52 AM
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline
Contributing User
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Apr 2004
Posts: 1,676 Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 1 Month 3 Days 8 h 23 m 46 sec
Reputation Power: 132
getchar returns an int -- and does so for a reason. The variable you declare ought to be the correct one (int).

Use a do...while(0) loop for a macro.

Use a C compiler for C code, rather than a C++ compiler for C code. Doing so relieves much grief.

Reply With Quote
  #6  
Old February 26th, 2006, 01:24 AM
kuza55's Avatar
kuza55 kuza55 is offline
It's only wrong if you're caught....
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Dec 2003
Location: Sydney, Australia
Posts: 1,286 kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 3 Weeks 3 Days 6 h 10 m 16 sec
Reputation Power: 173
Quote:
Originally Posted by Dave Sinkula
getchar returns an int -- and does so for a reason. The variable you declare ought to be the correct one (int).
Whoops, I should read things carefully next time, thanks.

Quote:
Originally Posted by Dave Sinkula
Use a do...while(0) loop for a macro.
Should I take that in blind faith, or is there a reason behind that? Also, do you mean do...while(1) loop? Because I'm not sure how I would implement a do...while(0) loop, and still have it loop.....I'm an absolute beginner here....

Quote:
Originally Posted by Dave Sinkula
Use a C compiler for C code, rather than a C++ compiler for C code. Doing so relieves much grief.
Isn't gcc a C compiler as well as a C++/Java/Fortan/Ada/objective-C compiler? Or should I just be using something which only supports c files, because as I understand it, if the file gcc is getting is a *.c file (which is what I'm doing) it will parse it like a C file, not a C++ file. Maybe I should I just use cc malloc.c instead of gcc malloc.c?

Reply With Quote
  #7  
Old February 26th, 2006, 02:04 AM
salem's Avatar
salem salem is offline
Contributed User
Click here for more information
 
Join Date: Jun 2005
Posts: 3,907 salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)salem User rank is General 12nd Grade (Above 100000 Reputation Level)  Folding Points: 153 Folding Title: Novice Folder
Time spent in forums: 2 Months 3 Weeks 4 Days 1 h 39 m 56 sec
Reputation Power: 1774
> And if anyone can be bothered to explain, could someone tell me what problems I could have run into if I hadn't cast them to pointers?
Well in C, there is no good reason to cast the return result of malloc.
The only thing it can achieve is hiding possible errors.

For example, you originally posted
> c = malloc (16);
And got
malloc.c:8: warning: assignment makes pointer from integer without a cast

Which is indeed correct for your code, because the error in your code was the lack of #include <stdlib.h>
The C compiler generated an implicit
int malloc();
instead.

Now, if you come along and try and fix this warning with something dumb like
c = (char *)malloc (16);
The error message goes away, but the reason for it doesn't.
You now have a forced (and unchecked) int to pointer conversion (the compiler having implicitly generated int malloc() ). On machines with different sized pointers and integers, the code is now seriously broken.

Now, even if you have
Code:
#include <stdlib.h>
...
c = malloc (16);

and you compile this with a C++ compiler, you get an entirely different warning, one about converting a void* into another pointer type. Of course, if it is your intent to write C++, then you should be using new/delete for dynamic memory not malloc/free.

> Isn't gcc a C compiler as well as a C++/Java/Fortan/Ada/objective-C compiler?
GCC (all upper case) is the GNU Compiler Collection, which is all those things you list.
gcc (all lower case) is the GNU C Compiler
g++ is the GNU C++ Compiler

If you're using
gcc prog.c
then it's pretty certain that you're compiling C code with a C compiler.


> #define CLEARBUF() char ch; while ((ch = getchar()) != '\n' && ch != EOF);
Since fgets() also reads newlines, you have to press an extra enter just to get past the CLEARBUF if the user types in a short line.

Code:
char buff[BUFSIZ];
fgets( buff, sizeof buff, stdin );

Always read into a temporary buffer, and then validate and move the data to where you need it to be inside the code proper, not inside the input routine.
BUFSIZ is a standard constant in stdio.h
Comments on this post
kuza55 agrees: Thanks.

Reply With Quote
  #8  
Old February 26th, 2006, 03:45 AM
kuza55's Avatar
kuza55 kuza55 is offline
It's only wrong if you're caught....
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Dec 2003
Location: Sydney, Australia
Posts: 1,286 kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level)kuza55 User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 3 Weeks 3 Days 6 h 10 m 16 sec
Reputation Power: 173
Quote:
Originally Posted by salem
> And if anyone can be bothered to explain, could someone tell me what problems I could have run into if I hadn't cast them to pointers?
Well in C, there is no good reason to cast the return result of malloc.
The only thing it can achieve is hiding possible errors.

For example, you originally posted
> c = malloc (16);
And got
malloc.c:8: warning: assignment makes pointer from integer without a cast

Which is indeed correct for your code, because the error in your code was the lack of #include <stdlib.h>
The C compiler generated an implicit
int malloc();
instead.

Now, if you come along and try and fix this warning with something dumb like
c = (char *)malloc (16);
The error message goes away, but the reason for it doesn't.
You now have a forced (and unchecked) int to pointer conversion (the compiler having implicitly generated int malloc() ). On machines with different sized pointers and integers, the code is now seriously broken.

Now, even if you have
Code:
#include <stdlib.h>
...
c = malloc (16);

and you compile this with a C++ compiler, you get an entirely different warning, one about converting a void* into another pointer type. Of course, if it is your intent to write C++, then you should be using new/delete for dynamic memory not malloc/free.
Thanks for all that. I'm not planning on writing C++ atm, so its not an issue right now, thanks for the tip anyway.

Quote:
Originally Posted by salem
> Isn't gcc a C compiler as well as a C++/Java/Fortan/Ada/objective-C compiler?
GCC (all upper case) is the GNU Compiler Collection, which is all those things you list.
gcc (all lower case) is the GNU C Compiler
g++ is the GNU C++ Compiler

If you're using
gcc prog.c
then it's pretty certain that you're compiling C code with a C compiler.
Well, doing man gcc gives the man file for the compiler collection, so I'm not sure, but cc prog.c works, so I'll just use that now (unless its a bad idea...)...


Quote:
Originally Posted by salem
> #define CLEARBUF() char ch; while ((ch = getchar()) != '\n' && ch != EOF);
Since fgets() also reads newlines, you have to press an extra enter just to get past the CLEARBUF if the user types in a short line.

Code:
char buff[BUFSIZ];
fgets( buff, sizeof buff, stdin );

Always read into a temporary buffer, and then validate and move the data to where you need it to be inside the code proper, not inside the input routine.
BUFSIZ is a standard constant in stdio.h
Right, thanks for that! I take it that once the user enters BUFSIZ bytes, it just stops accepting it, and since the user can't press enter they have to press backspace (so there's space in the input buffer for the new line) and then enter , opr at least that what happens for me, I'm wdonering if this is consisten behaviour among OSs?

Anyways, I implemented the buffer in which to read into, but I'm not sure wether it would be better to use my own function for copying strings, and then copy it char-by-char untill you get to a new line char, where you copy a NUL byte over instead, or if I should just copy the string using strncopy, and then check if the last character is a new line, and if it is replace it with a NUL character?

Anyways, this is what I cooked up:
c Code:
Original - c Code
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void cpyinput (char * dest, char * source, size_t length) {
  5.     int i;
  6.     size_t l;
  7.     l = length;
  8.     for (i=0;i<l;i++) {
  9.         if (source[i] == '\0') {
  10.             dest[i] = '\0';
  11.             return;
  12.         } else if (source[i] == '\n') {
  13.             dest[i] = '\0';
  14.         } else {
  15.             dest[i] = source[i];
  16.         }
  17.     }
  18. }
  19.  
  20. void stripn (char * string, size_t n) {
  21.     if (string[n] == '\n') {
  22.         string[n] = '\0';
  23.     }
  24. }
  25.  
  26. int main () {
  27.    
  28.     char *c, *d;
  29.     char buff[BUFSIZ];
  30.  
  31.     c = malloc (16);
  32.     d = malloc (16);
  33.  
  34.     fgets (buff, BUFSIZ, stdin);
  35.    
  36.     cpyinput (c, buff, 16);
  37.  
  38.     fgets (buff, BUFSIZ, stdin);
  39.  
  40.     strncpy (d, buff, 16);
  41.  
  42.     stripn (d, sizeof(d));
  43.    
  44.     printf ("%p - %p\n", c, d);
  45.     printf ("%s - %s\n", c, d);
  46.    
  47.     return 0;
  48. }

Reply With Quote
  #9  
Old February 26th, 2006, 01:07 PM
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline
Contributing User
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Apr 2004
Posts: 1,676 Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level)Dave Sinkula User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 1 Month 3 Days 8 h 23 m 46 sec
Reputation Power: 132
Quote:
Originally Posted by kuza55
Should I take that in blind faith, or is there a reason behind that? Also, do you mean do...while(1) loop? Because I'm not sure how I would implement a do...while(0) loop, and still have it loop.....I'm an absolute beginner here....
You could, but who ever wants to?

http://c-faq.com/cpp/multistmt.html

And no, it is supposed to be while(0).

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > Clearing the input buffer (stdin)

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap