質問
だから私は現在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;
}
}