musikluver2003
musikluver2003

Reputation: 163

Switch Statement goes to Default on Second try

I'm writing this program for class where it creates customers for a bank. I think I've got the basics - I still have some work to do and a couple things to add. Its compiling with no errors, but I have two problems I can't figure out:

  1. I can add a customer, but when the menu comes up a second time, no matter what option I put in, it goes to the default in the switch statement.

  2. Even after adding the customer, if I choose to search for it, it always says not found. If you answer, PLEASE explain, as I am trying to learn :) Thanks for any insight & advice!

customer.c

#include <stdio.h>
#include <stdlib.h>
#include "person.h"

// Program Contstants
#define INTEREST    .03
#define CHAR_LEN    40
#define MIN_PRINC   1000
#define MAX_PRINC   1000000
#define MIN_TERM    5
#define MAX_TERM    30

// Program Variables
struct person *customer = NULL;

// Function Prototypes
void addCustomer();
struct person *findCustomer(int custID);
void printCustomer();

int main(void) {
    char input;

    for (;;) {
        printf("\n\nChoose From the Options Below:\n");
        printf("Type 'N' to Add a New Customer\n");
        printf("Type 'P' to Print a Customer's Information\n");
        printf("Type 'Q' to Quit the Program\n\n");
        scanf("%c", &input);
        while (getchar() != '\n');

        switch (toupper(input)) {
          case 'N':
            addCustomer();
            break;
          case 'P':
            printCustomer();
            break;
          case 'Q':
            exit(0);
          default:
            printf("Invalid Entry. Please Reenter.\n");
            break;
        }
    }
}

void addCustomer() {
    struct person *cur, *prev, *new_node;

    new_node = malloc(sizeof(struct person));

    if (new_node == NULL) {
        printf("The Database is Full. You Cannot Add a New Customer.");
        return;
    }

    printf("\nEnter the Customer ID: ");
    scanf("%d", &new_node->custID);

    for (cur = customer, prev = NULL; 
         cur != NULL && new_node->custID > cur->custID;
         prev = cur, cur = cur->next);

    if (cur != NULL && new_node->custID == cur->custID) {
        printf("This Customer ID Already Exists\n");
        free(new_node);
        return;
    }

    printf("\nEnter Customer's First Name: ");
    gets(new_node->fName);

    printf("\nEnter Customer's Last Name: ");
    gets(new_node->lName);

    printf("\nEnter Customer's Street Address: ");
    gets(new_node->address);

    printf("\nEnter Customer's City: ");
    gets(new_node->city);

    printf("\nEnter Customer's 2-Digit State: ");
    gets(new_node->state);

    printf("\nEnter Customer's 5-Digit Zip Code: ");
    gets(new_node->zip);

    printf("\nEnter Customer's Principal: ");
    scanf("%f", &new_node->principal);

    printf("\nEnter Customer's Loan Term (In Years): ");
    scanf("%d", &new_node->yearlyTerm);

    new_node->next = cur;
    if (prev == NULL) {
        customer = new_node;
    } else {
        prev->next = new_node;
    }
}

struct person *findCustomer(int custID) {
    struct person *p;

    for (p = customer; p != NULL && custID > p->custID; p = p->next);

    if (p != NULL && custID == p->custID) {
        return p;
    } else {
        return NULL;
    }
}

void printCustomer() {
    int custID;
    struct person *p;

    printf("Enter Customer ID: ");
    scanf("%d", &custID);

    p = findCustomer(custID);

    if (p != NULL) {
        printf("\nCustomer ID:\t\t%d", p->custID);
        printf("\nCustomer's Name:\t%s %s", p->fName, p->lName);
        printf("\nCustomer's Address:\t%s", p->address);
        printf("\n\t\t\t%s, %s %s", p->city, p->state, p->zip);
        printf("\nCustomer's Principal:\t$%.2f", p->principal);
        printf("\nCustomer's Loan Term:\t%d", p->yearlyTerm);
    } else {
        printf("The Customer ID Wasn't Found.\n");
    }
}

person.h

// Program Constants
#define MAX_CUSTOMERS  10
#define CHAR_LEN       40

struct person {
    int custID;
    char fName[CHAR_LEN + 1];
    char lName[CHAR_LEN + 1];
    char address[CHAR_LEN + 1];
    char city[CHAR_LEN + 1];
    char state[3];
    char zip[6];
    float principal;
    int yearlyTerm;         // Loan Term in Years
    int monthlyTerm;        // Loan Term in Months
    float monthlyPayment;   // Calculated Monthly Payment
    float actualPayment;    // Calculated Monthly Payment Total 
    struct person *next;
};

Upvotes: 1

Views: 43

Answers (1)

chqrlie
chqrlie

Reputation: 144715

The second time scanf("%c", &input); is executed, it reads the \n that is pending in standard input after the scanf("%d", ...) that was executed last.

You can fix this by ignoring any white space before the character you want to read by inserting a space character in front of the %c:

scanf(" %c", &input);

Note that you should test the return value from scanf to verify that the input was parsed correctly. You definitely should not use gets() and you should protect scanf("%s", ...) by specifying the maximum number of characters to read: scanf("%19s", buffer); if the buffer has a length of 20 chars.

The getchar() loop consumes the rest of the input line where the user selected which option to execute, but look at addCustomer(): the last input operation is scanf("%d", &new_node->yearlyTerm);. This call to scanf leaves the remainder of its line in standard input, including the \n.

The proper way to flush pending input after your calls to scanf() is this:

void flush_line(void) {
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;
}

Note the int type for c so it can receive all values of unsigned char and the special value EOF. char would not be correct for this, and your while loop has a problem: you do not test for EOF, so the program will run an endless loop at end of file. Try typing control-Z (in Windows) or control-D (on Unix), to verify that.

Also note the explicit continue statement. Your empty loops are correct for the C syntax, but a tad confusing for the reader because the ; at the end of the for clause looks like an error. It is recommended to make this empty body more explicit by using {} or some other syntactic construction. I personally prefer a single obvious continue; statement.

Upvotes: 4

Related Questions