为什么我的函数无休止地循环

Why is my function endlessly looping

本文关键字:循环 无休止 函数 我的 为什么      更新时间:2023-10-16
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
void add(string names[], int section[], int grade[]);
void printRecords(const string names[], const int sections[], const int grades[], int size);
void insertionSort(int numbers[], int size);
void display(const int numbers[], int size);
int main(){
    //command
    string command;
    //add
    string names[20] = { "" };
    int sections[20];
    int grades[20];

    cout << "Enter a command (add, print, drop, sort, average, quit):n";
    cin >> command;
    while (command != "quit"){
        if (command == "add"){
            add(names,sections, grades);
        }
        else if (command == "print"){
            printRecords(names, sections, grades, 20);
        }
        else if (command == "drop"){
            cout << command;
        }
        else if (command == "sort"){
            cout << command;
        }
        else if (command == "average"){
            cout << command;
        }
        else if (command == "smallest"){
            cout << command;
        }
        else{
            cout << "Invalid command.n";
        }
        cin >> command;
    }
    cout << "Quitting the program.n";
    return 0;
}
void printRecords(const string names[], const int sections[], const int grades[], int size) {
    int i;
    for (i = 0; i < size; i = i + 1) {
        cout << "[" << i << "]:t";
        cout << setw(20) << left << names[i];
        cout << setw(5) << sections[i];
        cout << setw(10) << grades[i];
        cout << "n";
    }
    return;
}
void insertionSort(int numbers[], int size) {
    int i;
    int j;
    int toInsert;
    // outer loop i is the element we are to insert in to the sorted portion.
    // [0, i-1] is the sorted range.
    for (i = 1; i < size; i = i + 1) {
        toInsert = numbers[i];
        j = i - 1;
        while (j >= 0 && numbers[j] > toInsert) {
            numbers[j + 1] = numbers[j];
            j = j - 1;
        }
        // either j >= 0 and numbers[j] <= toInsert
        // or j = -1 here
        // we want to store toInsert at numbers[j+1]
        numbers[j + 1] = toInsert;
    }
    return;
}
void add(string names[], int sections[], int grades[]){
    int i = 0;
    while (names[i] != "" && i < 20){
        i = i + 1;
    }
    cin >> names[i];
    cin >> sections[i];
    cin >> grades[i];
        return;
}

我只需要用户在调用函数时只输入一次新的信息集。add函数是我最关心的。为什么它没完没了地修剪?

假设在当前电子表格。你的电子表格应该能够容纳多达20份学生记录。如果已经有20个学生记录,您的代码应该提示"电子表格已满。可以不添加。">

cin >> command更改为getline(cin, command)

在这里,这应该会解决它。发生的事情正是Chnossos所怀疑的。当您cin >>时,除非您调用cin.ignore((忽略换行符,否则输入缓冲区不会清除换行符。但是,如果没有换行符,您最终会等待它,从而输入额外的输入。

现在,getline(cin, var)使用换行符,所以在使用此函数后不需要忽略,否则您也将等待更多数据。

我没有太仔细地看,但我对它进行了编码,它正在工作,因此我认为你只是得到了太多的换行符,而消耗的不够,因此它看起来像是一个无限循环。

有更雄辩的方法可以做到这一点,但基本要点是字符串使用getline(),对于其他类型,如果之后使用cin.ignore(),则可以继续使用cin >>

我建议你也多查一下。这是代码。

#include <string>
 #include <iostream>
#include <iomanip>
using namespace std;
void add(string names[], int section[], int grade[]);
void printRecords(const string names[], const int sections[], const int grades[], int size);
void insertionSort(int numbers[], int size);
void display(const int numbers[], int size);
int main(){
//command
string command;
//add
string names[20] = { "" };
int sections[20];
int grades[20];

cout << "Enter a command (add, print, drop, sort, average, quit):n";
getline(cin, command);
while (command != "quit"){
    if (command == "add"){
        add(names,sections, grades);
    }
    else if (command == "print"){
        printRecords(names, sections, grades, 20);
    }
    else if (command == "drop"){
        cout << command;
    }
    else if (command == "sort"){
        cout << command;
    }
    else if (command == "average"){
        cout << command;
    }
    else if (command == "smallest"){
        cout << command;
    }
    else{
        cout << "Invalid command.n";
    }
    getline(cin, command);
}
cout << "Quitting the program.n";
return 0;
}
void printRecords(const string names[], const int sections[], const int grades[], int size) {
    int i;
    for (i = 0; i < size; i = i + 1) {
        cout << "[" << i << "]:t";
        cout << setw(20) << left << names[i];
        cout << setw(5) << sections[i];
        cout << setw(10) << grades[i];
        cout << "n";
    }
    return;
}
void insertionSort(int numbers[], int size) {
     int i;
     int j;
    int toInsert;
    // outer loop i is the element we are to insert in to the sorted portion.
    // [0, i-1] is the sorted range.
    for (i = 1; i < size; i = i + 1) {
        toInsert = numbers[i];
        j = i - 1;
        while (j >= 0 && numbers[j] > toInsert) {
            numbers[j + 1] = numbers[j];
            j = j - 1;
        }
        // either j >= 0 and numbers[j] <= toInsert
        // or j = -1 here
        // we want to store toInsert at numbers[j+1]
        numbers[j + 1] = toInsert;
    }
    return;
}
void add(string names[], int sections[], int grades[]){
    int i = 0;
    while (names[i] != "" && i < 20){
        i = i + 1;
    }
    getline(cin, names[i]);
    cin >> sections[i];
    cin.ignore();
    cin >> grades[i];
cin.ignore();
    return;
}

问题是,如果您试图读取一个整数,例如cin >> sections[i];,但您键入的字符不是数字,则此操作将失败,cin将进入失败状态

之后,cin将保持失败状态,直到您通过执行cin.clear()来取消该状态。此操作也不会从流中删除问题字符,因此您通常希望将clear()与另一个读取操作结合起来,以读取并丢弃问题字符。

如果您只在程序需要整数时键入整数,那么您的代码将不会"无休止地循环"。很明显,当它需要整数时,你已经输入了单词。

要解决此问题,需要做两件事。首先,始终测试输入函数是否失败。在完成cin >> command;之后,还要执行:

if ( !cin )
{
    break;    // exit instead of infinitely looping
}

但是,故障状态一出现就检测出来是很好的。在add函数中,在最后一个cin之后,您应该执行:

if ( !cin )
{
    cout << "Invalid input entered - discarding entryn";
    names[i] = "";
    cin.clear();
    string junk;
    getline(cin, junk);
}

(还有其他方法可以忽略垃圾,但我认为这一种很容易理解(。

最后,add函数使用格式化提取(即>>(,因此您无法判断此人是否按Enter键。如果你想让他们按Enter键总是意味着他们已经完成了当前条目的输入(无效条目将被丢弃(,那么你需要使用std::getline将整行存储在一个字符串中,然后使用stringstream从该行进行格式化提取。

例如,add函数可以是:

void add(string names[], int sections[], int grades[])
{
    int i = 0;
    while (names[i] != "" && i < 20){
        i = i + 1;
    if ( i == 20 )
        return;
    string line;
    getline(cin, line);
    istringstream iss(line);
    iss >> names[i] >> sections[i] >> grades[i];
    if ( !iss )
    {
         names[i] = "";
         cerr << "Invalid entry ignored.n";
    }
}

您可能需要#include <sstream>。注意,在这个版本中,你不需要丢弃"垃圾",因为垃圾在字符串流中,无论如何都会被销毁。

根据经验,如果您混合了字符串和整数输入,那么使用getline加上stringstream将使您的程序更加用户友好。