6

そのため、現在C ++を学んでおり、これまでに学んだスキルをテストするプログラムを作成することにしました。ここで、私のコードで、ユーザーが入力した値がdoubleであるかどうかを確認したいのですが、doubleでない場合は、ifループを設定して、再入力するように求めます。私が抱えている問題は、ユーザーが入力した変数のタイプを確認する方法です。たとえば、ユーザーが文字または文字列を入力した場合、エラーメッセージを出力できます。これが私のコードです:

//cubes a user entered number
#include <iostream>
using namespace std;

double cube(double n); //function prototype

int main()
{
    cout << "Enter the number you want to cube: "; //ask user to input number
    double user;
    cin >> user;  //user entering the number

    cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number

    return 0;
}

double cube (double n) //function that cubes the number
{
    return n*n*n; // cubing the number and returning it
}

編集:私は始めたばかりで、あなたのコードについて少しも手がかりがないと言わざるを得ませんが、あなたのリンクをチェックします。ちなみに、テンプレートの操作方法はまだ学習していません。データの処理について学習しています。C++PrimerPlus第5版の第3章のみです。

4

5 に答える 5

12

安全な C++ の方法

を使用して、このための関数を定義できますstd::istringstream

#include <sstream>  

bool is_double(std::string const& str) {
    std::istringstream ss(str);

    // always keep the scope of variables as close as possible. we see
    // 'd' only within the following block.
    {
        double d;
        ss >> d;
    }

    /* eat up trailing whitespace if there was a double read, and ensure
     * there is no character left. the eof bit is set in the case that
     * `std::ws` tried to read beyond the stream. */
    return (ss && (ss >> std::ws).eof());
}

それが何をするかを理解するのを助けるために(いくつかの点は単純化されています):

  • 指定された文字列で初期化された入力文字列ストリームの作成
  • を使用して double 値を読み取りますoperator>>。これは、空白をスキップして double を読み取ろうとすることを意味します。
  • double を読み取ることができなかった場合はabc、ストリームでfailビットが設定されます。3abcのような場合は成功し、fail-bit は設定されないことに注意してください。
  • fail-bit が設定ssされている場合、ゼロ値に評価されます。これはfalseを意味します。
  • double が読み取られた場合は、末尾の空白をスキップします。その後、ストリームの最後にいる場合 (最後を超えて読み取ろうとするとtrueeof()が返されることに注意してください。まさにそれを行います)、は true を返します。このチェックは、私たちのチェックに合格しないことを確認することに注意してください。std::wseof3abc
  • 右と左の両方のケースがtrue&&に評価された場合、呼び出し元に true を返し、指定された文字列が double であることを通知します。

int同様に、および他のタイプをチェックします。テンプレートの操作方法を知っていれば、これを他のタイプにも一般化する方法がわかります。ちなみに、これはまさにboost::lexical_castあなたに提供するものです。確認してください: http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm

C ウェイ ワン

この方法には利点 (高速) がありますが、大きな欠点もあります (テンプレートを使用して一般化できず、生のポインターを操作する必要があります)。

#include <cstdlib>
#include <cctype>  

bool is_double(std::string const& s) {
    char * endptr;
    std::strtod(s.c_str(), &endptr);
    if(endptr != s.c_str()) // skip trailing whitespace
        while(std::isspace(*endptr)) endptr++;
    return (endptr != s.c_str() && *endptr == '\0');
}

strtod最後に処理された文字に設定さendptrれます。私たちの場合、これは終端のヌル文字です。変換が実行されなかった場合、 endptr は に指定された文字列の値に設定されますstrtod

C ウェイ 2

std::sscanfトリックを行うものがあるかもしれません。しかし、何かを監視するのは簡単です。これを行う正しい方法は次のとおりです。

#include <cstdio>

bool is_double(std::string const& s) {
    int n;
    double d;
    return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 && 
            n == static_cast<int>(s.size()));
}

std::sscanf変換されたアイテムを返します。規格で%nは はその数に含まれないと明記されていますが、いくつかの情報源は互いに矛盾しています。正しく理解するには、比較>=するのが最善です ( のマンページを参照してくださいsscanf)。n処理された文字の量に設定されます。文字列のサイズと比較されます。2 つの書式指定子の間のスペースは、オプションの末尾の空白を考慮します。

結論

初心者の場合はstd::stringstream、C++ の方法を読んで実行してください。C++ の一般的な概念に慣れるまでは、ポインターをいじらないでください。

于 2008-12-02T02:43:44.170 に答える
7

標準ライブラリには、文字列に実際に doubleが含まれているかどうかを確認する適切な方法はありません。おそらくBoostを使用したいと思うでしょう。次のソリューションは、 C++ Cookbookのレシピ 3.3 に触発されています。

#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;

double cube(double n);

int main()
{
    while(true)
    {
        cout << "Enter the number you want to cube: ";
        string user;
        cin >> user;

        try
        {
            // The following instruction tries to parse a double from the 'user' string.
            // If the parsing fails, it raises an exception of type bad_lexical_cast.
            // If an exception is raised within a try{ } block, the execution proceeds
            // with one of the following catch() blocks
            double d = lexical_cast <double> (user);   

            cout << "The cube of " << d << " is " << cube(d) << "." << endl;
            break;
        }
        catch(bad_lexical_cast &e)
        {
            // This code is executed if the lexical_cast raised an exception; We
            // put an error message and continue with the loop
            cout << "The inserted string was not a valid double!" << endl;
        }
    }
    return 0;
}

double cube (double n)
{
    return n*n*n;
}
于 2008-12-02T03:00:55.897 に答える
1

sscanfは、やりたいことを実行できます。適切に処理された引数の数を返します。これで始められるはずです:

//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;

double cube(double n); //function prototype

int main()
{
        cout << "Enter the number you want to cube: "; //ask user to input number
        string user;
        cin >> user;  //user entering the number

        // Convert the number to a double.
        double value;
        if(sscanf(user.c_str(), "%lf", &value) != 1)
        {
                cout << "Bad!  " << user << " isn't a number!" << endl;
                return 1;
        }

        cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number

        return 0;
}

double cube (double n) //function that cubes the number
{
        return n*n*n; // cubing the number and returning it
}

他の回答に投稿された他の方法には、長所と短所があります。これは末尾の文字に問題があり、「C++」ではありません。

于 2008-12-02T03:09:26.253 に答える
0

私は始めたばかりで、あなたのコードについて少しも手がかりがないと言わざるを得ませんが、あなたのリンクをチェックします. ところで、私はまだテンプレートの操作方法を学んでいません。データの扱いについて学んでいます。C++ Primer Plus 5th edition の第 3 章だけです。

于 2008-12-02T02:49:41.770 に答える
0

Cにフォールバックしてstrtodを使用できます

プログラムは文字列を読み取り、文字列を double に変換しようとする関数に渡します。

bool is_double(const char* strIn, double& dblOut) {
    char* lastConvert = NULL;
    double d = strtod(strIn, &lastConvert);
    if(lastConvert == strIn){
        return false;
    } else {
       dblOut = d;
       return true;
    }
}
于 2008-12-02T02:51:28.910 に答える