How would I make all letters be an invalid input? I want all letters, numbers greater than 20, and numbers less than or equal to 0 to be invalid inputs. I used an or cause I want any case to be an invalid input. Any help would be greatly appreciated.

#include <stdio.h>
#include <math.h>

int main (void)
{
    float purchase = 0;


    printf("Please enter amount of purchase:\n");

    printf("purchase: ");
    scanf("%f" , &purchase);
    printf("The purchase you entered is: $%.2f\n", purchase);

    if((purchase  > 20) || (purchase <= 0))
        {
        printf("Invalid purchase amount\n");
        printf("Amount should be greater than 0 and less than or"); 
        printf(" equal to 20\n");
        return 1;
        }



    return 0;
}

You need to read the input as characters
Test each character to make sure it's a digit
If so, convert the value to int/float.

You need to read the input as characters
Test each character to make sure it's a digit
If so, convert the value to int/float.

How would I do that? I'm new with c.

>How would I make all letters be an invalid input?
I notice you don't check the return value of scanf. That's the first step in recognizing whether it failed or not. Then you can recover:

while (scanf("%f", &purchase) != 1) {
  /* This is me being lazy */
  while (getchar() != '\n')
    ;
  clearerr(stdin);
  printf("Invalid input, do it again: ");
  fflush(stdout);
}

You need to read the input as characters
Test each character to make sure it's a digit
If so, convert the value to int/float.

How would I do that? I'm new with c.

Do what?
1) Read characters?
2) Test characters?
3) Convert characters?

If 1, don't bother trying it yet. Come back to this in a couple weeks and you'll be able to do it.
If 2, wait until you learn loops. Then come back to it.
If only 3, look up string conversion functions in your book. They start with ato* and str*

Another solution could be something of this sort

int main(int argc, char* argv[])
{
        int i;
        scanf("%d",&i);
        if(i<=0)
        {
                printf("%d\n",i);                                        // This takes care of 0, -ve and alphabets
                printf("Invalid Input\n");
        }
        else
        {
                printf("%d\n",i);
                printf("Valid Input\n");
        }
}

>Another solution could be something of this sort
If the user types letters, scanf will fail and leave i uninitialized. Accessing an uninitialized variable's value is undefined behavior. The suggestion becomes reasonable if you initialize to an invalid value for the program (like 0).

But then you've got the bigger problem of a dirty input stream in the case of letters. I hope you don't plan on taking any input after this, because there's no telling what you'll get. ;)

You could also do something like this

....
    char input[10];
    int converted_number = 0;
    int length;
    int i = 0;
    
    printf("Enter Input : ");
    fgets(input,10,stdin);
    input[strlen(input) - 1] = '\0';

    if(strlen(input) > 2)    // number is within 20 hence must be within 2 digits
    {
        printf("Invalid");
        return 0;
    }
    else
    {
        length = strlen(input);

        while(i < length)
        {
            if(input[i] < 48 || input[i] > 56)    //  if one of the characters is not a number, then immediate exit
            {
                printf("Invalid");    
                return 0;
                break;
            }
            else
            {
                converted_number = converted_number*10 + (input[i] - 48);    // converting the number to integer
            }
            
            i++;
        }
    }

    if(converted_number < 0 || converted_number > 20)
        printf("Invalid");
    else
        printf("Valid");
    ....

>printf("Enter Input : ");
The stream isn't guaranteed to be flushed unless you print a newline or call fflush. The user may not see your prompt before fgets starts blocking, which is generally very confusing. ;)

>while(i < length)
You only use for this loop, yet it's declared at the top of main. Wouldn't it be easier to read the code if your variables are declared closer to where they're used? Further, your while loop is constructed identically to a for loop, so I'd say a for loop makes more sense here.

>if(input < 48 || input > 56)
The world is not ASCII. You can make your code portable by using '0' and '9' instead.

>return 0;
>break;

The break is redundant; it'll never be reached because you return on the previous line.

>converted_number = converted_number*10 + (input - 48);
Once again, '0' makes the code portable.

>while(i < length)
You only use for this loop, yet it's declared at the top of main. Wouldn't it be easier to read the code if your variables are declared closer to where they're used? Further, your while loop is constructed identically to a for loop, so I'd say a for loop makes more sense here.

You can thank Borland for that. There, we first have to initialize all variables before using them. Guess old habits die hard

>return 0;
>break;
The break is redundant; it'll never be reached because you return on the previous line.

C**p! I was deleting all of the break s and forgot that one

>if(input < 48 || input > 56)
>converted_number = converted_number*10 + (input - 48);

If i say to my teacher "then we subtract '0' from the character, then we get the numeric equivalent", she will say "x - 0 = x"
Point noted. All of us here have been brought up learning ASCII

>printf("Enter Input : ");
The stream isn't guaranteed to be flushed unless you print a newline or call fflush. The user may not see your prompt before fgets starts blocking, which is generally very confusing.

I still have to come across this error


Thanks again!

>You can thank Borland for that. There, we first have to initialize all variables before using them.
Yes, I'm aware of that warning, but it's not relevant to what I was saying. Take this line:

int i = 0;

and move it to here:

else
{
    int i = 0;

    length = strlen(input);

It's still initialized, but now the scope of the variable is limited to the else clause (the only place you actually use it). Readers won't wonder where else you use i because it's declared at the top of main.

>I still have to come across this error
Let me guess: you use Windows. I haven't encountered that issue on Windows either, but it's prevalent on Unix/Linux. In other words, it's a portability issue. I'm almost like a broken record when it comes to portability, ne?

It's still initialized, but now the scope of the variable is limited to the else clause (the only place you actually use it). Readers won't wonder where else you use i because it's declared at the top of main.

So in a nut-shell, reduce the scope of all variables as much as possible so that the reader will know at once where and why it is used

>I still have to come across this error
Let me guess: you use Windows.

Right on target.
But in my college, we use Unix/Linux but still didn't encounter it. Guess i'll have to learn it the hard way

>So in a nut-shell, reduce the scope of all variables as much as possible
>so that the reader will know at once where and why it is used

Bingo.

>Guess i'll have to learn it the hard way
Sometimes that's the only way. Or you could just take my word for it and not worry about ever encountering it (except in other people's code). ;)

Or you could just take my word for it and not worry about ever encountering it (except in other people's code).

Listen, i don't doubt you but I basically live my life around these quotes

Why do we fall master Wayne, so that we can learn to pick ourself up again

Don't make the same mistakes as i did, make your own mistakes

I believe everyone should experiment with mistakes for a better understanding of a subject.
After much philosophy, can you give me a snippet, where that printf error occurs? I'll test it in my college.

>can you give me a snippet, where that printf error occurs?

#include <stdio.h>

int main(void)
{
  printf("Type something: ");
  getchar();
  return 0;
}

I still have to come across this error

I run into it constantly. My preferred IDE is SlickEdit (on Windows). When I build and execute the code, SE runs it in a shell. This environment in which the code is run (the important part here) does not display the prompt.

I consider this a feature, because it helps me write code with the explicit flush there.

#include <stdio.h>
#include <string.h>

int main(void) 
{
   char line[BUFSIZ];
   printf("enter some test: ");
   if ( fgets(line, sizeof line, stdin) )
   {
      char *newline = strchr(line, '\n');
      if ( newline )
      {
         *newline = '\0';
      }
      printf("line = \"%s\"\n", line);
   }
   printf("enter some more test: ");
   if ( fgets(line, sizeof line, stdin) )
   {
      char *newline = strchr(line, '\n');
      if ( newline )
      {
         *newline = '\0';
      }
      printf("line = \"%s\"\n", line);
   }
   return 0;
}

/* my output
hello world
what's going on?
enter some test: line = "hello world"
enter some more test: line = "what's going on?"
*/

Of course, here I see a blinking cursor that seems to indicate to me that I'm supposed to do something before I type "hello world" and hit enter. But it is rather annoying to see a program staring at you with a blinking cursor and no idea what it is asking.

>Another solution could be something of this sort
If the user types letters, scanf will fail and leave i uninitialized. Accessing an uninitialized variable's value is undefined behavior. The suggestion becomes reasonable if you initialize to an invalid value for the program (like 0).

But then you've got the bigger problem of a dirty input stream in the case of letters. I hope you don't plan on taking any input after this, because there's no telling what you'll get. ;)

I discovered that after testing it out :). I was googling and reading my book for ideas with no luck. I was really annoyed after I figured that out :(. Won't using that while loop in your previous post also deal with clearing the input?


>I still have to come across this error
Let me guess: you use Windows. I haven't encountered that issue on Windows either, but it's prevalent on Unix/Linux. In other words, it's a portability issue. I'm almost like a broken record when it comes to portability, ne?

I gotta use Unix/Linux so that would be a very big problem for me :(.

>How would I make all letters be an invalid input?
I notice you don't check the return value of scanf. That's the first step in recognizing whether it failed or not. Then you can recover:

while (scanf("%f", &purchase) != 1) {
  /* This is me being lazy */
  [B]while (getchar() != '\n')
    ;[/B]
  clearerr(stdin);
  printf("Invalid input, do it again: ");
  fflush(stdout);
}

I just noticed you put a random ";" after your while loop. Is that on purpose? I thought you didn't put ";" after a while loop.

I just noticed you put a random ";" after your while loop. Is that on purpose? I thought you didn't put ";" after a while loop.

It ain't random. It's an empty loop body. Putting it on a separate line helps people understand that it is intentional, rather than what can be a common bug (when people inadvertently create an empty loop body by placing an errant semicolon after a while or for statement).

It ain't random. It's an empty loop body. Putting it on a separate line helps people understand that it is intentional, rather than what can be a common bug (when people inadvertently create an empty loop body by placing an errant semicolon after a while or for statement).

So what does that ";" mean and what does it do? Sorry I'm new with c.

It ain't random. It's an empty loop body. Putting it on a separate line helps people understand that it is intentional, rather than what can be a common bug (when people inadvertently create an empty loop body by placing an errant semicolon after a while or for statement).

So what does that ";" mean and what does it do? Sorry I'm new with c.

Read what I wrote, please. It's an empty statement as the loop body. It's an empty statement; it does nothing. It's in the loop body. The loop body repeatedly does nothing.

Read what I wrote, please. It's an empty statement as the loop body. It's an empty statement; it does nothing. It's in the loop body. The loop body repeatedly does nothing.

I did but I don't understand what that means :(.

You don't know what "it does nothing" means?

Please, tell me what you think "it does nothing" could possibly mean.

while (getchar() != '\n')
    ;

This code will read a character from the keyboard buffer.
If the character is not '\n' do it again. Keep it up until '\n' is read.

The body of the loop is empty because all the work is done with the getchar() function.

while (getchar() != '\n')
    ;

This code will read a character from the keyboard buffer.
If the character is not '\n' do it again. Keep it up until '\n' is read.

The body of the loop is empty because all the work is done with the getchar() function.

Thx for explaining that :).

You don't know what "it does nothing" means?

Please, tell me what you think "it does nothing" could possibly mean.

I didn't understand how what you were saying was possible. I thought it would cause an infinite loop. I didn't know it would stop after it read " '\n' " like WaltP just explained.

Well... it's pretty implicit with the whole while([B]getchar() != '\n'[/B]) part

code is fine

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.