Question

I have a problem that I cannot find an actual solution after searching for about half a day. In this program, I have to fill an array of structs with customer information. I also have to do a couple other things, but I cannot figure out this bug in my code. I know the problem is the input buffer has a line feed or a new line character in the buffer after scanning in the quantity of customers. Many have suggested already online using:

while((number = getchar()) != '\n' && number != EOF)
/* discard the character */;

This only works for the first name entered, then I run into the same problem from the loop putting the new line or line feed from the customer priority. There needs to be a way that I can take out that line feed and not have to worry about it. I cannot use something like fflush(); or any functions like that.

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

#define MIN_CUSTOMERS   2          /* Minimum valid menu choice       */
#define MAX_CUSTOMERS   100        /* Maximum valid menu choice       */
#define MAX_NAME_LENGTH 21         /* Maximum last name length        */
#define END_OF_STRING   '\0'       /* End of string character         */
#define NEW_LINE        '\n'       /* New line character              */
#define QUIT            0          /* Program exit value              */
#define DB_ALLOC_ERROR  1          /* Database allocation error       */

/**********************************************************************/
/*                        Program Structures                          */
/**********************************************************************/
/* A company customer record                                          */
struct customer
{
char  customer_name[MAX_NAME_LENGTH];  /* Last name of customer    */
float amount_owed;          /* Dollar amount customer owes         */
int   priority;             /* Priority number of customer        */
};

/**********************************************************************/
/*                         Function Prototypes                        */
/**********************************************************************/

void print_heading();
/* Print  the heading of the program                               */
void print_instructions();
/* Print the program instructions                                  */
int get_number_of_customers();
/* Get the number of customers to be recorded                      */
void get_customers(int quantity,
            struct customer *p_customer_records_start);
/* Ask the user for customers and fills them into the database     */
void clean_names(int quantity,
            struct customer *p_customer_records_start);
/* Clean customer names of everything except letters and spaces    */
void sort_customers(int quantity,
            struct customer *p_customer_records_start);
/* Sort the array of customers alphabetically                      */
void print_customers(int quantity,
                struct customer *p_customer_records_start);
/* Print the items in the customer database                        */

/**********************************************************************/
/*                           Main Function                            */
/**********************************************************************/
int main()
{
int quantity;   /* Amount of customer databases                     */
struct customer *p_customer_records; /* Pointer to the database    */

/* Print the program heading                                       */
   printf("\n\n\n\n\n\n");
   print_heading();

/* Loop through the number of customer database                    */
while(print_instructions(),
            (quantity = get_number_of_customers()) != QUIT)
{

/* Allocate memory for the experimental scientific data values     */
/* and abort if memory is not available                            */
  if((p_customer_records =
      (struct customer*)malloc(sizeof(struct customer) * quantity))
                                                                                 == NULL)
  {
     printf("\nERROR NUMBER %d OCCURRED in main()", DB_ALLOC_ERROR);
     printf("\nCould not allocate memory for experimental data");
     printf("\nThe program is aborting");
     exit(DB_ALLOC_ERROR);
  }

/* Get, clean, sort, and print the database of customers           */
    get_customers(quantity, p_customer_records);
    clean_names(quantity, p_customer_records);
    sort_customers(quantity, p_customer_records);
    print_customers(quantity, p_customer_records);

/* Display end of database processing                               */
    printf("\n\n******* End of Customer Database Processing *******");
    printf("\n");

/* Free the database memory that was allocated                     */
    free(p_customer_records);
}

/* Print goodbye and terminate                                     */
printf("\nThanks for processing accounts. Have a nice day! :-)");
return 0;
}

This is where I get the quantity.

/**********************************************************************/
/*                      Get number of customers                       */
/**********************************************************************/
int get_number_of_customers()
{
int quantity; /* Quantity of experimental scientific data values   */

   do
   {
    printf("\n\nGet the number of customers for the database");
    printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - -");
    printf("\nHow many customers do you have (2 to 100, 0=quit): ");
            scanf ("%d", &quantity);
   } while (quantity == 1 ||
              quantity < QUIT || quantity > MAX_CUSTOMERS);

return quantity;
}

/**********************************************************************/
/*                     Get customers information                      */
/**********************************************************************/
void get_customers(int quantity,
                                struct customer *p_customer_records_start)
{
struct customer *p_customer; /* Points to each customer            */
char *p_last_name;

/* Loop through the array of customers and get information         */
for(p_customer = p_customer_records_start;
     (p_customer-p_customer_records_start) < quantity; p_customer++)
{

/* Get the customer's last name                                    */
    printf("\n- Customer Information -");
    printf("\n    Enter the customer's last name: ");

    p_last_name = p_customer->customer_name;

This is where my problems come up.

    do {
        *p_last_name = getchar();
         p_last_name++;
    } while (*(p_last_name - 1) != NEW_LINE);

    *(p_last_name - 1) = END_OF_STRING;

/* Get the amount the customer owes                                */
    printf("    Enter the amount owed: ");
    scanf ("%f", &p_customer->amount_owed);

/* Get the customer's priority                                     */
    printf("    Enter the customer's priority: ");
    scanf("%d", &p_customer->priority);

    while(p_customer->priority < 1 || p_customer->priority > 3)
    {
                printf("    Enter a valid priority (1-3): ");
                scanf ("%d", &p_customer->priority);
    }

If i use the while loop (previous explanation) here, the priority is never valid and an infinite loop begins.

}

return;
    }
Était-ce utile?

La solution

This is a common problem, and the solution is fairly simple: Always read a complete line every time you read something.

Never leave newlines in the input buffer, to mess up later reads. Don't (as it seems you are doing now) leave them there and try to skip them later, when reading text lines. Always consume the entire line the user typed, including the newline at the end.

The usual advice on exactly how to do this is to use fgets or something similar to read the lines, and then process the contents using atoi or sscanf or something similar. Another possibility is to always immediately read and throw away the newline character using getchar, when you have one left in the input buffer.

So never just do this:

scanf("%d", &p_customer->priority);

Either do this:

fgets(line, sizeof line, stdin);
sscanf(line, "%d", &p_customer->priority);

or, possibly, this:

scanf("%d", &p_customer->priority);
while (getchar() != '\n')
    ;

With error handling, which I have conveniently (for me) left out.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top