scanf problem

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The following code does not work properly. The scanf routine (for int) runs constant without waiting for input. If I include the string input routine (by removing the comments), both scanf's are functioning correctly.

I have no idea why. Perhaps someone can help me.

Oh, I use the latest winavr/avr studio. If you need more info, I'll post it since I do not want to bloat the post.

Thanks


int main (void)
{

	char test[16];
	int k, res;
    ioinit(); //Setup IO pins and defaults

	

    while(1)
    {
/*	
	printf("Waiting for string input:\n"); 
	res = scanf("%s", test);
	printf("res %d \n %s\n", res, test);
*/
	printf("Waiting for int input:\n"); 
	res = scanf("%3d", &k);
	printf("res %d \n %d\n", res, k);
    
	}
   
    return(0); // never get here
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you need to use the address specifier, '&' in all situations with scanf()

res = scanf("%s", &test);

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Carl,

that's not it. Without the string reading routine - only the int routine - it is not working correcly. It is running constantly, without waiting for any input.

Only with the int reading routine gives the following output when I input once a non-char character. It will never stop:

res 0
0
Waiting for int input:
res 0
0
Waiting for int input:
res 0
0
Waiting for int input:
res 0

and with both routines:

Waiting for string input:
res 1
test1
Waiting for int input:
res 1
123
Waiting for string input:
res 1
test2
Waiting for int input:
res 1
321
Waiting for string input:

Ans now with a rubbisch character for the int routine

Waiting for string input:
res 1
hallo
Waiting for int input:
res 1
0
Waiting for string input:
res 1
ahallo2
Waiting for int input:
res 1
222
Waiting for string input:

Apparantly res=1 even when a rubbisch character for the int is put in...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps the scanf routine is buggy?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The scanf function works fine in my imagecraft compiler. Doesnt the gcc compiler have its own forum?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Doesnt the gcc compiler have its own forum?

scanf(), in all probablility, is not buggy--at least to the fundamental extent that you are implying. For generations, the same query has been made during struggles with scanf(). I just can't remember the last time I used it--must be over 20 years.

For most work, the blocking nature of scanf() precludes its use. If testing, I'd first work with sscanf() and "canned" strings until I felt sure that the mechanisms are working.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sun. Jan 27, 2008 - 01:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Bob,

So Imagecraft is ok then? Humm.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
For most work, the blocking nature of scanf() precludes its use.

I've found the same thing.

For my embedded designs, I usually build my own version of scanf() using getchar(). Doing this, I find that I can gain much more flexibility on how I input characters & strings.

And yes, the ImageCraft ICCAVR C compiler rules - especially when new to the C language, as it applies to embedded programming. The ImageCraft ICCAVR is very easy to set up, and has an application builder that allows you to select hardware options and then it generates the basic initialization routines for the selected hardware.

ImageCraft provides a 30 day, fully functional trial version - free for the downloading.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks guys.

To sum it up: gcg suck when dealing with scanf. Right?

Quote:

For most work, the blocking nature of scanf() precludes its use.

Can you elaborate on this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nick-123 wrote:
Thanks guys.

To sum it up: gcg suck when dealing with scanf. Right?


Well, you're putting words into our mouths.

To quote:

microcarl wrote:
And yes, the ImageCraft ICCAVR C compiler rules - especially when new to the C language, as it applies to embedded programming.

That's only my opinion. There are many here who will tell you that GCC rules.

Quote:

For most work, the blocking nature of scanf() precludes its use.

nick-123 wrote:
Can you elaborate on this?

For my work, I find scanf() to be less usable for inputting data through a console device. As I use a matrix keypad for a lot of projects, scanf() has limitations. Even when I did a project using a PC and Hyper-Terminal as a parameter display/entry method, I found that writing my own key entry a better solution. I don't really remember all of the particulars, but scanf() was difficult to use in my application.

Again, that doesn't mean that scanf() sucks... After all, scanf() has been part of the C programming language for a very long time, so it must be somewhat useful. It just means that scanf() might not be the best alternative for many/some applications.

Don't read more into what we say, then what we are saying.

And I just noticed that you've posted in multiple forums...

Are you afraid that you won't get quick enough attention, or what?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just go and type your program into the C compiler on a host computer.
The result will behave the same, once the first non-numeric character
is entered, the scanf for %d can no longer succeed, and the entire
thing will run within an infinite loop.

This is because the scan for %d can *never* consume that non-numerical
character which is now stuck in the input buffer.

Yes, processing input line by line is one option to get around this.
Another one is to try some input cleanup upon getting a scanf return
value of 0.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How about using fflush() ? Shouldn't that purge the whole buffer?

There are pointy haired bald people.
Time flies when you have a bad prescaler selected.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

fflush is only defined on output buffers.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

the scanf for %d can no longer succeed, and the entire
thing will run within an infinite loop.

I wonder if that is the normal behaviour for scanf for all c compilers.
Just looked the function up in 'The C programming language' from Kerningham & Richie pp150. The function should return a zero when it finds the next input character that does not match the first specification in the control string. That's a bit cryptic, but I think that the function should return a zero when there's an error. That it gets stuck in an endless loop is not a feature of C, but an error of the compiler. :shock:

Carl, I was asked to post it in the gcc forum and not in here. Maybe you might delete that other post. Thx.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nick-123 wrote:

> I wonder if that is the normal behaviour for scanf for all c
> compilers.

At least for anything that conforms to the standard. Anything else is
not entitled to call itself a C compiler. (Btw., it's not the
compiler but the "implementation" in the terms of the C standard, as
usually this function is not implemented by the compiler itself but by
the standard library.)

> Just looked the function up in 'The C programming language' from
> Kerningham & Richie pp150. The function should return a zero when it
> finds the next input character that does not match the first
> specification in the control string.

That's only half of the truth. Here's the (even more cryptic) text
from the standard:

``The fscanf function returns the value of the macro EOF if an input
failure occurs before any conversion. Otherwise, the function
returns the number of input items assigned, which can be fewer than
provided for, or even zero, in the event of an early matching
failure.''

That is, it must return EOF in case there's been an IO error before
the first conversion. This is obviously not the case in our
situation, because there was no IO error (the non-numeric character
has been read successfully). But if there's not been an early IO
error, it returns the number of successful items assigned. Since
there was only one conversion requested which failed, the return value
will be 0.

> That it gets stuck in an endless loop is not a feature of C, but an
> error of the compiler.

Care to prove your claim?

It's an error of the person operating that compiler. The scanf()
function is required to leave the unmatched character unread in the
input stream (i. e. there's a mandatory one-character pushback in that
requirement). Therefore, it's the responsibility of the developer to
take care about input conversion errors, and to cleanup the input in a
way so the next conversion can succeed. One possible way for this to
happen has been mentioned: you read the input line by line with
fgets(), and then scan the complete line with sscanf(). Another
clever trick is mentioned in the standard:

#include 
/* ... */
int count; float quant; char units[21], item[21];
do {
        count = fscanf(stdin, "%f%20s of %20s", &quant, units, item);
        fscanf(stdin,"%*[^\n]");
} while (!feof(stdin) && !ferror(stdin));

Have a look at the line right before the "while". Alas, since the %[]
format requires a lot of memory at run-time, in avr-libc this feature
is only available in the full-blown floating-point version of scanf(),
not in the minimal or standard version.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Jörg,

I did not know that scanf pushes back the unmatched character. And if scanf is called again, it processes this pushedback character again and one gets an endless loop. I now do understand.

I've used other c compilers before and never encountered this problem. I always checked the result and if it was zero, I informed the user and restarted the scanf again.
Is there an easy method to get rid of this pushback?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Is there an easy method to get rid of this pushback?

No, but you can always consume the unprocessed characters in some
way. A scanf("%*c") will always consume one character, as well as
a simple (void)getc(). But if your input is constructed of lines,
I think it's best to consume input characters until reaching a '\n'
character, and then start over.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Re scanf():

"Doctor, doctor, it HURTS when I do this!"
"Then don't do that anymore."

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.