2

コマンドライン引数として2つのintを受け取るプログラムを作成しようとしています。intは両方とも0より大きい必要があります。charから変換する必要があることは理解していますが、これまでにatoiを使用して行ったことがありますが、これは行うべきではないことがわかっています。人々がsstreamsとstrtolを使用しているのを見たことがありますが、この場合、それらがどのように機能するかはわかりません。これを達成するための最良の方法は何ですか?

#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

const int N = 7;
const int M = 8;//N is number of lines, M number of values

//--------------
//-----Main-----
//--------------
int main(int argc, char* argv[])
{
    if((argc != 0) && (argv[0] != NULL) && (argv[1] != NULL))
    {       
        N = argv[0];
        M = argv[1];
    }
    else
    {
        cout << "Invalid or no command line arguments found. Defaulting to N=7 M=8.\n\n" << endl;
    }


    //Blah blah blah code here

    return 0;
}
4

3 に答える 3

1

C++ 11 にstoiは、stol,stollがあります: http://en.cppreference.com/w/cpp/string/basic_string/stol

文字列が正しい形式でない場合、これらは例外をスローしinvalid_argumentます。out_of_range

を使用することに特に問題atoiはありませんが、C 関数であるため例外を報告するメカニズムがありません。したがって、戻り値しかありません-問題は、のすべての戻り値atoiが有効な値であるため、戻り値0を「0」の正しい解析または解析の失敗として区別する方法がありません。また、atoi は、値が使用可能な値の範囲外であるかどうかのチェックを行いません。最初の問題は自分でチェックすることで簡単に修正できますが、2 番目の問題は実際に文字列を解析する必要があるため、より困難です。これは、そもそも外部関数を使用するという点を無効にします。

istringstream次のように使用できます。

C++11 より前:

int val;
std::istringstream iss(arg[i]);
iss >> val;
if (iss.fail()) {
   //something went wrong
} else {
    //apparently it worked
}

C++11:

int val;
std::istringstream iss(arg[i]);
iss >> val;
if(iss.fail()) {
   if(!value) {
       //wrong number format
   } else if(value == std::numeric_limits<int>::max() || 
             value == std::numeric_limits<int>::min() 
   {
       //number too large or too small
   }
} else {
   //apparently it worked
}

違いは、C++11 より前では、(標準に従って) フォーマット エラーのみが検出され、エラー時に値が上書きされないことです。C++11 では、値は、フォーマット エラーの場合は 0 で上書きされ、数値が大きすぎたり小さすぎて型に収まらない場合は max/min で上書きされます。どちらも、エラーを示すためにストリームに失敗フラグを設定します。

于 2012-12-12T18:24:31.330 に答える
0

この特定のケースでは、atoi正常に動作します。の問題は、何らかのエラーを示すために返されることと、入力が. だったことを示すためatoiに返されることを区別できないことです。000

ただし、あなたの場合、有効な入力は 0 より大きい必要があります。入力が0変換できなかったのか、それとも変換できなかったのかは気にしません。いずれにせよ、デフォルト値に設定するためにやっています。

そのため、私は次のようなことをします:

int convert(char *input, int default) { 
    int x = atoi(input);
    return x==0 ? default : x;
}

if (argc > 1)
    N = convert(argv[1], 7);

if (argc > 2)
    M = convert(argv[2], 8);

argv[0]従来、呼び出されているプログラムの名前を保持していることに注意してください。コマンドラインで渡された引数は、そのまま受け取られargv[1]ますargv[argc-1]

于 2012-12-12T18:22:00.163 に答える
0

constまず、値を変更するため、M と N に修飾子を使用することはできません。

int N = 7;
int M = 8;//N is number of lines, M number of values

次に、 をチェックする必要はありません。(引数の数) が 3 以上かどうかをチェック(argv[0] != NULL) && (argv[1] != NULL)するだけです。argc

if(argc >= 3)

次に、これを整数に変換する必要があります。を使用したくない場合atoi、および C++11 コンパイラがない場合は、C++stringstreamまたは Cを使用する必要があります。strtol

stringstream ss;
int temp;
ss << argv[1]; // Put string into stringstream
ss >> temp;    // Get integer from stringstream
// Check for the error:
if(!ss.fail())
{
    M = temp;
}

// Repeat 
ss.clear(); // Clear the current content!
ss << argv[2]; // Put string into stringstream
ss >> temp;    // Get integer from stringstream
// Check for the error:
if(!ss.fail())
{
    N = temp;
}

したがって、コード全体は次のようになります。

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <sstream>
using namespace std;

int N = 7;
int M = 8;//N is number of lines, M number of values

//--------------
//-----Main-----
//--------------
int main(int argc, char* argv[])
{
    if(argc >= 3)
    {       
       stringstream ss;
       int temp;
       ss << argv[1]; // Put char into stringstream
       ss >> temp;    // Get integer from stringstream
       // Check for the error:
       if(!ss.fail())
       {
           M = temp;
       }

       // Repeat
       // empty
       ss.clear();
       ss << argv[2]; // Put char into stringstream
       ss >> temp;    // Get integer from stringstream
       // Check for the error:
       if(!ss.fail())
       {
           N = temp;
       }

    cout << M << " " << N;
    }
    else
    {
        cout << "Invalid or no command line arguments found. Defaulting to N=7 M=8.\n\n" << 

endl;
    }


    //Blah blah blah code here

    return 0;
}

また、C ヘッダー ファイルには、接尾c辞ではなく接頭.h辞 (<cstdio>の代わりに<stdio.h>)が含まれます。

于 2012-12-12T18:26:53.483 に答える