我已经做了好几天了,终于让它像我想要的那样验证,一切正常。但是当我运行这个并且输入名字然后点击“Enter”时,控制台就会跳过一条线。当我第二次点击“Enter”时,程序继续进入下一个问题。任何想法为什么会这样?任何建议表示赞赏!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "person.h"
// Program Contstants
#define INTEREST .03 // Annual Interest Rate
#define CHAR_LEN 40 // Maximum Character Length
#define MAX_CUST 2 // Maximum Amount of Customers
#define MIN_PRIN 1000 // Minimum Principal Balance
#define MAX_PRIN 1000000 // Maximum Principal Balance
#define MIN_TERM 5 // Minimum Loan Term (Years)
#define MAX_TERM 30 // Maximum Loan Term (Years)
// Program Variables
struct person *customer = NULL; // Pointer to the "person" Structure
FILE *ifp; // File Pointer
int num_cust = 0;
// Function Prototypes
void addCustomer(); // Function to Add a Customer
struct person *findCustomer(int custID); // Function to Find a Customer
void printCustomer(); // Function to Print a Customer
float calcMonthlyPayment(float, int); // Function to Calculate monthlyPayment
float calcActualPayment(int, float); // Function to Calculate actualPayment
void flushLine(); // Function to Clear "scanf" Input
int main(void)
{
char input; // Local Variable to Hold User's Choice
ifp = fopen("Customers.txt", "w"); // Opens/Creates the File to be Written - Overwrites Existing File
for(;;) // Infinite "FOR" Loop to Run the Program
{
// Print Statements to Display the Menu
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); // Scans User Input and Assigns to "input" Variable
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
switch(toupper(input)) // Switch Statement to Control Function Calls. Converts input to Upper Case
{
case 'N': // If the User Chose "N"
ifp = fopen("Customers.txt", "a"); // Appends Data to the Open File
addCustomer(); // Calls the "addCustomer()" Function
break; // Break Statement to Exit the Switch Statement
case 'P': // If the User Chose "P"
printCustomer(); // Calls the "printCustomer()" Function
break; // Break Statement to Exit the Switch Statement
case 'Q': // If the User Chose "Q"
exit(0); // Exits the Program
default: // If the User Chose Anything Else
printf("Invalid Entry. Please Reenter.\n"); // Prints an Error Message
break; // Break Statement to Exit the Switch Statement
}
}
}
void addCustomer()
{
struct person *cur, *prev, *new_node; // Defines Pointers for the "person" Structure
new_node = malloc(sizeof(struct person)); // Allocates Space For a New Customer and Assigns it to the "new_node" Variable
if((new_node == NULL) || (num_cust == MAX_CUST)) // If the "new_node" Variable is Empty
{
printf("The Database is Full. You Cannot Add a New Customer."); // Alerts the User that there is No Room
return; // Return Statement
}
printf("\nEnter the Customer ID: "); // Prompts the User to Enter a Customer ID
scanf("%d", &new_node->custID); // Scans User Input and Assigns it to the "custID" field for the New Customer
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
while((new_node->custID <= 0) || (new_node->custID > MAX_CUST)) // Validates the Customer ID is Numeric and Between 0 - 100
{
printf("\nInvalid Entry. The Customer ID must be Numeric and Below %d.\n", MAX_CUST); // Prints an Error Message
printf("Enter the Customer ID: "); // Prompts the User to Reenter the Customer ID
scanf("%d", &new_node->custID); // Scans User Input and Assigns it to the "custID" field for the New Customer
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
}
for(cur = customer, prev = NULL; cur != NULL && new_node->custID > cur->custID; prev = cur, cur = cur->next)
{
continue;
}
if(cur != NULL && new_node->custID == cur->custID) // Tests Whether or Not the Customer ID is a Duplicate
{
printf("This Customer ID Already Exists.\n"); // Prints an Error Message
free(new_node); // Releases the Reserved Memory
return; // Return Statement
}
fprintf(ifp, "%s", "Customer ID:\t\t"); // Prints the Customer ID Heading to File
fprintf(ifp, "%d", new_node->custID); // Prints the Customer ID to File
printf("\nEnter Customer's First Name: "); // Prompts the User for the Customer's First Name
fgets(new_node->fName, 41, stdin); // Gets Input and Assigns it to the "fName" Variable
while(strlen(new_node->fName) == 0)
{
printf("\nYou Cannot Leave this Field Blank.");
printf("\nEnter the Customer's First Name: ");
gets(new_node->fName);
}
fprintf(ifp, "%s", "\nCustomer Name:\t\t"); // Prints the Customer Name Heading to File
fprintf(ifp, "%s", new_node->fName); // Prints the Customer's First Name to File
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
printf("\nEnter Customer's Last Name: "); // Prompts the User for the Customer's Last Name
scanf("%40[^\n]s", new_node->lName); // Scans the Input and Assigns it to the "lName" Variable
fprintf(ifp, "%s", " "); // Prints a Space to File
fprintf(ifp, "%s", new_node->lName); // Prints the Customer's Last Name to File
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
printf("\nEnter Customer's Street Address: "); // Prompts the User for the Customer's Address
scanf("%40[^\n]s", new_node->address); // Scans the Input and Assigns it to the "address" Variable
fprintf(ifp, "%s", "\nCustomer Address:\t"); // Prints the Customer Address Heading to File
fprintf(ifp, "%s", new_node->address); // Prints the Customer's Address to File
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
printf("\nEnter Customer's City: "); // Prompts the User for the Customer's City
scanf("%40[^\n]s", new_node->city); // Scans the Input and Assigns it to the "city" Variable
fprintf(ifp, "%s", "\n\t\t\t"); // Prints Spacing to File
fprintf(ifp, "%s", new_node->city); // Prints the Customer's City to File
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
printf("\nEnter Customer's 2-Digit State: "); // Prompts the User for the Customer's State
scanf("%2s", new_node->state); // Scans the Input and Assigns it to the "state" Variable
fprintf(ifp, "%s", ", "); // Prints Spacing to File
fprintf(ifp, "%s", new_node->state); // Prints the Customer's State to File
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
printf("\nEnter Customer's 5-Digit Zip Code: "); // Prompts the User for the Customer's Zip
scanf("%5s", new_node->zip); // Scans the Input and Assigns it to the "zip" Variable
fprintf(ifp, "%s", " "); // Prints Spacing to File
fprintf(ifp, "%s", new_node->zip); // Prints the Customer's Zip to File
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
printf("\nEnter the Customer's Principal: "); // Prompts the User for the Customer's Principal
scanf("%f", &new_node->principal); // Scans the Input and Assigns it to the "principal" Variable
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
// While Loop to Test for In-Range Principal Input
while((new_node->principal < MIN_PRIN) || (new_node->principal > MAX_PRIN))
{
printf("Invalid Entry. The Customer's Principal must be Between %d and %d.\n", MIN_PRIN, MAX_PRIN); // Prints an Error Message
printf("\nEnter Customer's Principal: "); // Prompts the User to Reenter the Principal
scanf("%f", &new_node->principal); // Scans the Input and Assigns it to the "principal" Variable
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
}
fprintf(ifp, "%s", "\nPrincipal:\t\t$"); // Prints the Principal Heading to File
fprintf(ifp, "%.2f", new_node->principal); // Prints the Customer's Principal to File
printf("\nEnter the Customer's Loan Term (In Years): "); // Prompts the User for the Customer's Loan Term
scanf("%d", &new_node->yearlyTerm); // Scans the Input and Assigns it to the "yearlyTerm" Variable
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
// While Loop to Test for In-Range Yearly Term Input
while((new_node->yearlyTerm < MIN_TERM) || (new_node->yearlyTerm > MAX_TERM))
{
printf("Invalid Entry. The Loan Term must be Between %d and %d.\n", MIN_TERM, MAX_TERM); // Prints an Error Message
printf("\nEnter the Customer's Loan Term (In Years): "); // Prompts the User to Reenter the Yearly Term
scanf("%d", &new_node->yearlyTerm); // Scans the Input and Assigns it to the "yearlyTerm" Variable
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
}
fprintf(ifp, "%s", "\nYearly Term:\t\t"); // Prints the Yearly Term Heading to File
fprintf(ifp, "%d", new_node->yearlyTerm); // Prints the Customer's Yearly Term to File
float payment = calcMonthlyPayment(new_node->principal, new_node->yearlyTerm); // Calls the "calcMonthlyPayment()" Function and Assigns it to the "payment" Variable
new_node->monthlyPayment = payment; // Assigns the "payment" Variable to the Customer's "monthlyPayment" Variable
fprintf(ifp, "%s", " Years\nMonthly Payment:\t$"); // Prints the Monthly Payment Heading to File
fprintf(ifp, "%.2f", new_node->monthlyPayment); // Prints the Customer's Monthly Payment to File
float actPayment = calcActualPayment(new_node->yearlyTerm, payment); // Calls the "calcActualPayment()" Function and Assigns it to the "actPayment" Variable
new_node->actualPayment = actPayment; // Assigns the "actPayment" Variable to the Customer's "actualPayment" Variable
fprintf(ifp, "%s", "\nActual Payment:\t\t$"); // Prints the Actual Payment Heading to File
fprintf(ifp, "%.2f", new_node->actualPayment); // Prints the Customer's Actual Payment to File
fprintf(ifp, "%s", "\n--------------------------------------------\n"); // Prints a Line Seperater to File
fclose(ifp); // Closes the .txt File
new_node->next = cur;
if (prev == NULL)
{
customer = new_node;
}
else
{
prev->next = new_node;
}
num_cust++;
}
struct person *findCustomer(int custID)
{
struct person *p;
for(p = customer; p != NULL && custID > p->custID; p = p->next)
{
continue; // DO I NEED THIS? Works through structure
}
if (p != NULL && custID == p->custID)
{
return p;
}
else
{
return NULL;
}
}
void printCustomer()
{
int custID;
struct person *p;
printf("\nEnter Customer ID: ");
scanf("%d", &custID);
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
p = findCustomer(custID);
if(p != NULL)
{
printf("\nCustomer ID:\t\t%d", p->custID);
printf("\nCustomer Name:\t\t%s %s", p->fName, p->lName);
printf("\nCustomer Address:\t%s", p->address);
printf("\n\t\t\t%s, %s %s", p->city, p->state, p->zip);
printf("\nCustomer Principal:\t$%.2f", p->principal);
printf("\nCustomer Loan Term:\t%d Years", p->yearlyTerm);
printf("\nMonthly Payment:\t$%.2f", p->monthlyPayment);
printf("\nActual Payment:\t\t$%.2f", p->actualPayment);
}
else
{
printf("The Customer ID Wasn't Found.\n");
}
}
float calcMonthlyPayment(float principal, int yearlyTerm)
{
int monthlyTerm = yearlyTerm * 12;
float monthlyIR = INTEREST / 12;
float payment = principal * monthlyIR * (pow(1 + monthlyIR, monthlyTerm) / (pow(1 + monthlyIR, monthlyTerm)-1));
return payment;
}
float calcActualPayment(int yearlyTerm, float monthlyPayment)
{
int monthlyTerm = yearlyTerm * 12;
float actPayment = monthlyPayment * monthlyTerm;
return actPayment;
}
void flushLine()
{
int c;
while((c = getchar()) != EOF && c != '\n')
{
continue;
}
}
Person.h
// Program Constants
#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;
float monthlyPayment;
float actualPayment;
struct person *next;
};
答案 0 :(得分:0)
你的姓氏代码非常接近。我将它复制为名字并进行了一些更改。
以下是addCustomer
中的更改:
// NOTE/BUG: original code
#if 0
printf("\nEnter Customer's First Name: "); // Prompts the User for the Customer's First Name
fgets(new_node->fName, 41, stdin); // Gets Input and Assigns it to the "fName" Variable
while(strlen(new_node->fName) == 0)
{
printf("\nYou Cannot Leave this Field Blank.");
printf("\nEnter the Customer's First Name: ");
fgets(new_node->fName,sizeof(new_node->fName),stdin);
}
// NOTE/FIX: modified code
#else
while (1) {
printf("\nEnter Customer's first Name: "); // Prompts the User for the Customer's First Name
scanf("%40[^\n]s", new_node->fName); // Scans the Input and Assigns it to the "fName" Variable
if (strlen(new_node->fName) != 0)
break;
printf("\nYou Cannot Leave this Field Blank.");
flushLine(); // Calls the "flushLine" Function to Clear the "scanf"
}
#endif