views:

138

answers:

2

Hello,

This program asks for any row number. I want the program to loop a scan function if the user types anything else other than numbers..

My code is :

 do{
   printf("Enter row number\n");
   scanf("%d",&row);
  }while(row>='a' && row<='z');

but this code doesnt work .. I keep getting an error when typing in a letter. I tried manipulating around it and the whole thing loops infinitely ... What am I doing wrong ?

In simpler terms : How do I tell C NOT to break the loop unless the input is an INTEGER ?

Please help thanks !

A: 

You will want to read in characters, then determine if that character is a numeric and convert as needed. You will also want to put in a check for some special character like 'q' or something to break you out of the loop when you are done entering characters.

Rob Goodwin
Thanks, but I want to know how the conversion is done ..
ZaZu
+3  A: 

You are ignoring the return from scanf() which tells you whether the typed information was accurate for the conversion (%d) or not. If it was inaccurate, you have to do error recovery, which is not particularly easy with scanf(). Most people go for the approach of 'read a line of input and then parse it', where the error recovery is simpler.


I understand that return values as essential in error checking, but how do I scan if its numbers or letters? Can I say if (input!=(integers)) or anything similar?

This is why people don't use scanf(). If you get the line of data into a buffer (character array), then you can check the contents of the array as often as you like. If you use scanf(), you don't get a reliable chance to process the data until after scanf() decides it has an error.

The functions (usually also available as macros) in <ctype.h> allow you to classify characters. The functions in <stdlib.h> provide reliable conversions from strings to integers of various sorts.

So, you can think about doing something like:

char buffer[256];

while (fgets(buffer, sizeof(buffer), stdin))
{
    ...check contents of buffer using isdigit() etc...
    ...or just plough ahead with...
    long value;
    char *end;
    errno = 0;
    value = strtol(buffer, &end, 0);
    if (errno != 0 || (*end != '\0' && !isspace(*end))
        ...diagnose problems...
}

This code is a bit out of my league at the moment .. is there a simpler way?

Well, I suppose you can use atoi() instead of strtol(), which simplifies the error handling (because it is less precise):

char buffer[256];

while (fgets(buffer, sizeof(buffer), stdin))
{
    int value = atoi(buffer);
    if (value == 0)
    {
        puts("zero read - exiting loop");
        break;
    }
}

It doesn't get much simpler than this. I don't know which part of the previous solution you felt was beyond you. The alternatives, it seems to me, are much fiddlier, involving reading one character at a time and saving the digits and rejecting the non-digits:

char buffer[256];
char *dst = buffer;
int c;
int value;

while ((c = getchar()) != EOF)
{
    if (isdigit(c))
    {
        *dst++ = c;  /* Ignoring buffer overflow - bad! */
    }
    else if (isspace(c))
    {
        *dst = '\0';
        value = atoi(buffer);
        break;
    }
    else
    {
        printf("Unexpected character '%c'!\n", c);
    }
}

Etcetera. There are various issues to resolve in that code - like resetting the pointer after an erroneous character, and avoiding buffer overflow, and dealing with signs on the numbers, and ... well, all sorts of stuff that I'd rather leave to routines like fgets() and strtol().

Jonathan Leffler
Thanks for the reply, yes I understand that return values as essential in error checking, but how do I scan if its numbers or letters ? can I say if (input!=(integers)) or anything similar ?
ZaZu
Thanks for the explanation, but this code is a bit out of my league at the moment .. is there a simpler way ?
ZaZu
@Zazu: The explanation is complete and the code simple. You need to reread it until you understand it. For example, the third code block in this answer was how one could do it but shouldn't. The second code block calls two functions that have been well documented since 1977. If you cannot learn what fgets and atoi and the structure of the while loop does, then yes, you are out of your league and should get an introduction to programming. We won't write your code for you here, and we can't make you read what has been written.
msw
@Zazu: Also, re-asking questions you already asked on Stack Overflow is kind of frowned upon: http://stackoverflow.com/questions/2796108/how-to-prevent-users-from-inputting-letters-or-numbers
msw