为什么我的功能无休止地循环

时间:2014-04-29 01:07:48

标签: c++

#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;
}

我只需要用户在调用函数时只输入一组新信息。 添加功能是我最关心的。为什么它无休止地砍掉?

假设在最后一个记录之后添加一个学生的记录(姓名,部分和成绩) 当前的电子表格。您的电子表格应该能够容纳20个学生记录。如果 目前已经有20学生档案,你的代码应该提示“电子表格已满。能够 未添加“。

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

在这里,这应该解决它。究竟发生了什么正是Chnossos所怀疑的。当cin >>输入缓冲区没有清除换行符时,除非你调用cin.ignore()忽略它。但是,如果没有换行符,你将最终等待它,让你输入额外的输入来实现目标。

现在,getline(cin, var)使用换行符,因此在使用此函数后您无需忽略,否则您还将等待更多数据。

我没有把它看得太厉害,但是我编写了这个并且它正在工作,因此我相信你只是得到了太多的新行而且消耗不够,因此它看起来像是一个无限循环。

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

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

#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;
}

答案 2 :(得分:0)

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

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

如果您只在程序需要整数时输入整数,那么您的代码将无法循环#34;。显然你在预期整数时输入了单词。

要解决此问题,有两件事要做。首先,总是测试输入函数是否失败。完成cin >> command;后,也可以:

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

但是一旦发生故障状态就很快就能检测出来。在add函数内,在最后cin之后,您应该执行:

if ( !cin )
{
    cout << "Invalid input entered - discarding entry\n";
    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>。请注意,在这个版本中你不需要丢弃&#34;垃圾&#34;,因为垃圾是在串流中被破坏的。

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