質問

だから私は現在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++ Primer Plus 5th editionの第3章のみです。

役に立ちましたか?

解決

文字列 really に標準ライブラリ内の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;
}

他のヒント

Safe C ++ Way

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());
}

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

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

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

C Way One

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

#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 はそのカウントに含まれないと規定されていますが、いくつかのソースは互いに矛盾しています。 &gt; = を比較して正しく理解するのが最善です( sscanf のマンページを参照)。 n は、処理された文字の量に設定されます。文字列のサイズと比較されます。 2つの書式指定子の間のスペースは、オプションの末尾の空白を考慮します。

結論

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

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 ++」-yではありません。

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

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;
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top