hello i am new to these boards and new to the language of c. i am trying to figure out this user input stuff....and i am about to kill myself! every time i think i have it...C throws me another road block.

i am trying to create a menu based program to calculate sales tax, and i want to be able to check for negative numbers; as well as characters in the user input (sorry if my English is bad). basically i need some big help please. i mean there has to be a way to check for both negative and character based input?

thank you, here is code.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

main()

        { // begin main

     //Defining integers, floating points and characters.

  float fPrice, fSalesTax_Del, fSalesTax_Enci, fSalesTax_Jolla, fAnswer, fCheckSum;
  int iDivide_By, iResponse;
  char cMenu;

    iResponse = 0;
    fCheckSum = 0;
    fPrice = 0;
    fSalesTax_Del = 7.25;
    fSalesTax_Enci = 7.5;
    fSalesTax_Jolla = 7.75;
    iDivide_By = 100;
    fAnswer = 0;
    cMenu = iResponse;


    while ( fPrice == 0 ) // loop for fPrice, makes sure something is selected

    {
        cMenu = 0;

        while( cMenu == 0 ) // Menu system loop

    {
            // menu display
      printf("\nKudler Fine Foods - Store Selector\n");
     printf("\nA\tDel Mar Location\n");
     printf("B\tThe Encinitas Location\n");
     printf("C\tThe La Jolla Location\n");
     printf("\nPlease select a Store:  ");
     scanf("  %c", &cMenu ); // input for menu selection

     // if statment for cMenu and includes lower case
  if ((cMenu == 'A' && cMenu == 'a') || (cMenu == 'B' && cMenu == 'b') || (cMenu == 'C' && cMenu == 'c'))

      if (cMenu = 1); // statment for if cMenu is true

         else

    printf("\nInvalid Store Selection.\n");

            } //end cMenu while loop

        // clear extraneous text
        system("clear");


        // switch for menu system, launches specialized code for each case

                switch ( cMenu ) //begins switch for menu system
        {

//case for switch includes lowercase letters for validation
  case  'a':  case  'A':

     printf("\nEnter Purchase Amount For The Del Mar Location:\n $ ");
    scanf("%f", &fPrice);

   while (fPrice < fCheckSum) { //begin validation loop

	printf("\n\tPlease Re-enter your Purchase Amount: $");
	scanf("%f", &fPrice);

        }//end while loop

    fAnswer = fPrice * fSalesTax_Jolla / iDivide_By;  // formula to calculate this stores sales tax
 printf("\nThe Sales Tax Amount For The Del Mar Location Is $%.2f\n", fAnswer);
 printf("\nAnd Total Sales Amount Is $%.2f\n", fPrice);

 break;

//case for switch includes lowercase letters for validation
case  'b':  case  'B':

    printf("\nEnter Purchase Amount For The Encinitas Location:\n $ ");
    scanf("%f", &fPrice);

        while (fPrice < fCheckSum) { //begin while validation loop

	printf("\n\tPlease Re-enter your Purchase Amount: $");
	scanf("%f", &fPrice);

        }//end while loop

    fAnswer = fPrice * fSalesTax_Jolla / iDivide_By; // formula to calculate this stores sales tax
    printf("\nThe Sales Tax Amount For The Encinitas Location Is $%.2f\n", fAnswer);
    printf("\nAnd Total Sales Amount Is $%.2f\n", fPrice);

break;

//case for switch includes lowercase letters for validation
case  'c':  case  'C':

        printf("\nEnter Purchase Amount For The La Jolla Location:\n $ ");
    scanf("%f", &fPrice);
   while (fPrice < fCheckSum) { //begin while validation loop

	printf("\n\tPlease Re-enter your Purchase Amount: $");
	scanf("%f", &fPrice);

        }//end while loop

    fAnswer = fPrice * fSalesTax_Jolla / iDivide_By;  // formula to calculate this stores sales tax
    printf("\nThe Sales Tax Amount For The La Jolla Location Is $%.2f\n", fAnswer);
    printf("\nAnd Total Sales Amount Is $%.2f\n", fPrice);

    break;

		} //end switch


            } //end fPrice while loop


printf("\nPress Enter key to end.\n");

    getchar();

    return 0;


} // end main

The short answer is don't use scanf - period.

Whilst it does what it says just fine, cleaning up when the unexpected happens is damn hard work (as you've found).

Example

char buff[BUFSIZ];
    if ( fgets( buff, sizeof buff, stdin ) != NULL ) {
        int myInt;
        if ( sscanf( buff, "%d", &myInt ) == 1 ) {
            if ( myInt >= 0 ) {
                // success!!!
            } else {
                // negative
            }
        } else {
            // It didn't look like an int
        }
    } else {
        // feof() or ferror() are true
    }

Separating input from conversion allows you to see what's going on. It also means that if the conversion fails, you don't have a cleanup job on the input to do.

Also, the approach is readily expandable into more complex (or more robust) conversions not involving sscanf.

the test if ((cMenu == 'A' && cMenu == 'a') || (cMenu == 'B' && cMenu == 'b') || (cMenu == 'C' && cMenu == 'c')) can never be true because the character can not be both the uppercase and lowercase letter at the same time.

With input where the case is not significant, it is common to force it to one case to simplify testing:

cMenu = tolower(cMenu);
if (cMenu == 'a' || cMenu == 'b' || cMenu == 'c')

but in your case, for what you're trying to do, I think this is even better:

while( cMenu == 0 ) // Menu system loop
{
	// menu display
	printf("\n");
	printf("Kudler Fine Foods - Store Selector\n");
	printf("\n");
	printf("A\tDel Mar Location\n");
	printf("B\tThe Encinitas Location\n");
	printf("C\tThe La Jolla Location\n");
	printf("\n");
	printf("Please select a Store:  ");
	cMenu = getchar();	// input for menu selection

	cMenu = tolower(cMenu);
	if (cMenu != 'a' && cMenu != 'b' && cMenu != 'c') {
		printf("\n");
		printf("Invalid Store Selection.\n");
		cMenu = 0;
	}
} //end cMenu while loop

Note that I did some reformatting of the indenting and I split printf's with embedded newlines. The split printf's are NOT as efficient, but I can better 'see' what the output should be.

I also switched from scanf to getchar for a single character input. ** After further testing, I don't like how getchar() works in this context. I think you should read a line like in the previous post and then find the menu selection character in the string. **

the line in your old code: if (cMenu = 1); // statment for if cMenu is true is not a test, it assigns the value 1 to cMenu, overwriting the user selection. This may have contributed to your problems.

Farther down, all three cases do the same math: fAnswer = fPrice * fSalesTax_Jolla / iDivide_By; shouldn't the sales tax float be different in each case?

Firstly, your indentation is pretty bad. I lost the flow at the middle of the code.

Secondly, use int main().

I think this is wrong:

if (cMenu = 1); // statment for if cMenu is true

You are using an assignment operator instead of '==' operator. The else part of your code will never get executed.

EDIT: Well, Murtan has already said it in a better way. :)

ok thank you everyone, ill begin reworking my code with these suggestions!

Your formatting is really bad. It should take the form of:

int main(){
        for(;;){
                statement;
        }
        switch(){
                case 'a':
                case 'B':
                        do something;
                        break;

                default:
                        nothing-above worked;
                        do-something-else;
                        break;
        }/* end switch()*/

}/*** end main() ***/

For an idea of good C formatting, take a look at this simple address book example.

If you use consistent, and clear, formatting, your code will be much easier to read. And don't forget the code comments!!!

I recommend using an indentation level of 8 characters, which is the normal width for the tab character, and try and keep your code within 80 columns of text. It'll improve readability, make it easier to print your code, and discourage you from nesting your code too deeply.

This article has been dead for over six months. Start a new discussion instead.