3

次の列挙型を宣言しました:

  enum periods {one, five, ten, fifteen, thirty};

そして今、それをメイン関数のコマンドライン引数として渡したいと思っています。

int main(int argc, char* argv[]) {

  periods mp;
  if (argc == 2) {
      std::string min_prd(argv[2]);
      mp=atoi(min_prd.c_str());
 }

そしてコンパイラは不平を言います:

error: invalid conversion from ‘int’ to ‘periods’

enum は int だと思ったので、atoi() を実行しました。コードを修正するにはどうすればよいですか?

4

4 に答える 4

7

明示的にキャストする必要があります:

mp=static_cast<periods>(atoi(min_prd.c_str()));
于 2012-05-15T03:53:15.537 に答える
3

私は次の列挙型を宣言しました:

enum periods {one, five, ten, fifteen, thirty};

そして今、私はそれを私のメイン関数のコマンドライン引数として渡したいと思います。

periods mp = atoi(argv[2]);   // simplified for answer...

したがって、いくつかの問題があります。

  • atoiによって返されたintを列挙型にキャストする必要があります...static_cast<periods>(...)
  • 「0」のargv[2]は列挙識別子「one」にマップされ、「1」は「five」などにマップされることに注意してください。
    • 実際に「1」を「1」、「5」から「5」などにマップする場合、最も簡単な方法は列挙型を変更することですenum periods { one = 1, five = 5, ten = 10, fifteen = 15, thirty = 30 };。ただし、例は明らかに少し工夫されているため、何が最適かを推測することは不可能です。あなたの本当のニーズのために
  • 検証はありません

関数を作成することをお勧めします。

periods to_periods(const std::string& s)
{
    if (s == "one") return one;
    if (s == "five") return five;
    if (s == "ten") return ten;
    if (s == "fifteen") return fifteen;
    if (s == "thirty") return thirty;
    throw std::runtime_error("invalid conversion from text to periods");
}

(さらに多くの場合、std::mapまたはソートstd::vectorを使用してこれらの関連付けを追跡することは珍しくありません。これにより、再利用可能なアルゴリズムと同じデータで、列挙型数値からテキストIDへの変換をサポートできます。)

于 2012-05-15T03:59:17.837 に答える
3

簡単な解決策は、使用することですstatic_cast(他の回答がすでに投稿しているため):

periods mp;
if (argc == 2)
{
   std::string min_prd(argv[1]); //the index should be 1
   mp = static_cast<periods>(atoi(min_prd.c_str()));
}

ただし、入力文字列のエラーをチェックしないため、 c-string を int に変換するために使用しないatoiでください。したがって、安全ではありません。atoi

C++11 はより安全な変換関数を提供するため、次のように使用できますstd::stoi

try
{
   periods mp;
   if (argc == 2)
   {
      //std::stoi could throw exception on error in input
      mp = static_cast<periods>(std::stoi(argv[1]));
   }
   //use mp here
}
catch(std::exception const & e)
{
   std::cout << "exception caught with message : " << e.what() << std::endl;
}

これでより良い解決策になりました。


ただし、次のように使用できる代替ソリューションがあります。

period mp;
if (argc == 2)
{
   mp = to_period(argv[1]); //how should we implement it?
   if (mp == period_end)
   {
       std::cout << "command line input error" << std::endl;
       return 0;
   }
}

問題は、to_period関数をどのように実装するかです。

このソリューションでは、列挙値のコマンド ライン引数oneがその文字列表現であると想定していることに注意してください。つまり、整数表現では"one"なく、文字列表現になります。1

このソリューションを次のように実装します。

  • まず、次のようなヘッダー ファイルを作成しますperiod_items.h

    //period_items.h
    E(one)
    E(five)
    E(ten)
    E(fifteen)
    E(thirty)
    
  • 次に、次のような別のヘッダー ファイルを作成しますperiod.h

    //period.h
    #include <string>
    
    enum period 
    {
       #define E(item)  item,
         #include "period_items.h"
       #undef E
       period_end
    };
    
    period to_period(std::string const & name)
    {
       #define E(item)  if(name == #item) return item;
         #include "period_items.h"
       #undef E
       return period_end;
    }
    

これで、関数を単純に含めperiod.hて使用できるようになりました。to_period:-)

period別の解決策では、複数形ではなく単数形を使用したことに注意してくださいperiods。適切だと感じperiodます。

この関数を次のように追加することもできますperiod.h

std::string to_string(period value)
{
    #define E(item)  if(value == item) return #item;
        #include "period_items.h"
    #undef E
    return "<error>";
}

今、あなたはこれを書くことができます:

#include "period.h"

period v = to_period(argv[1)); //string to period
std::string s = to_string(v);  //period to string

それが役立つことを願っています。

于 2012-06-04T19:53:09.563 に答える
2

ランダムに推測すると、本当に必要なのは次のようなものです。

periods mp;
if (argc < 2) {
    mp=one; // default value
} else if (strcmp(argv[1], "one")==0) {
    mp=one;
} else if (strcmp(argv[1], "five")==0) {
    mp=five;
} else if (strcmp(argv[1], "ten")==0) {
    mp=ten;
} else if (strcmp(argv[1], "fifteen")==0) {
    mp=fifteen;
} else if (strcmp(argv[1], "thirty")==0) {
    mp=thirty;
} else {
    fprintf(stderr, "I can't possibly comprehend periods = '%s'\n", argv[1]);
    return -1;
}
于 2012-05-15T04:04:29.680 に答える