1

getRegionTotal()私が現在検証に使用している関数です。ユーザーが「20」や-7などを入力すると、それを受け入れず、有効な値を取得するまで新しい値を要求し続けるという点で、これは非常にうまく機能します。ただし、ユーザーが北部地域の事故件数に 60.7 を入力すると、60 が受け入れられ、.7 の部分が削除されます。次に、南部地域の事故件数を尋ねると、通常の指示とより具体的な指示の両方が表示されます。

//These will hold the number of accidents in each region last year
int northTotal = 0;
int southTotal = 0;
int eastTotal = 0;
int westTotal = 0;
int centralTotal = 0;

//passing 0 for northTotal, southTotal etc. because main doesn't know
//values of them until the function returns a value. When it returns a value
//it will go into the variables on the left. getRegionTotal will get the number
//of accidents for a region from the user and prompt the user using the string that
//is in the first argument.
northTotal = getRegionTotal("North", northTotal);
southTotal = getRegionTotal("South", southTotal);
eastTotal = getRegionTotal("East", eastTotal);
westTotal = getRegionTotal("West", westTotal);
centralTotal = getRegionTotal("Central", centralTotal);


int getRegionTotal(string regionName, int regionTotal)
{
    //instructs user to enter number of accidents reported in a particular region
    cout << "\nNumber of automobile accidents reported in " << regionName << " " << cityName << ": ";
    //while regionTotal is not an integer or regionTotal is negative
    while (!(cin >> regionTotal) || (regionTotal < 0) )
    {
        //give user more specific instructions
        cout << "\nPlease enter a positive whole number for the number of\n";
        cout << "automobile accidents in " << regionName << " " << cityName << ": ";
        cin.clear(); //clear out cin object
        cin.ignore(100, '\n'); //ignore whatever is in the cin object
                                //up to 100 characters or until
                                // a new line character
    }
    //returns a valid value for the number of accidents for the region
    return regionTotal;
}
4

1 に答える 1

1

行全体を解析し、行全体を消費したことを確認してください。

iostream の場合:

#include <iostream>
#include <sstream>
#include <string>

for (std::string line; std::getline(std::cin, line); )
{
    std::istringstream iss(line);
    int result;

    if (!(iss >> result >> std::ws && iss.get() == EOF))
    {
        // error, die. For example:

        std::cout << "Unparsable input: '" << line << "'\n";
        continue;
    }

    // else use "result"
}

標準ライブラリを使用:

#include <errno>
#include <cstdlib>

char const * input = line.c_str();   // from above, say
char * e;
errno = 0;

long int result = std::strtol(input, &e, 10);

if (e == input || *e != '\0' || errno != 0)
{
    // error
}

2 つのアプローチは基本的に同じですが、前者の方が「慣用的な C++」である可能性があります。つまり、すでに既存の文字列がある場合、strtol-approach は正確なエラー処理を提供するため、適切な代替手段です。文字列全体を消費しましたか (そうでない場合は、e次の文字を指します); 文字列のいずれかを消費しましたか (そうでない場合は、e先頭を指します)。オーバーフローまたはアンダーフローがありましたか (チェックしてくださいerrno)。一方、iostreams アプローチでは、末尾の空白を消費できますが ( のおかげで>> std::ws)、strtol-solution では消費できません。

std::stolラップするものもありますが ( /などstrtolも同様です)、エラーが発生すると例外がスローされます。例外は、ユーザー入力の読み取りなどの通常の動作の制御フローを構築するための適切なツールではないと思います。また、これらのラッパーの動作を制御することはできません。たとえば、文字列全体を消費しなくても成功し (ただし、どこまで取得したかはわかりません)、基数を指定できません。strtoullstrtod

于 2013-09-24T08:07:19.160 に答える