0

input(時間と価格)が次のようになっているファイルを読み取ろうとしています。時間、分、秒の値を保持する12:23:31 67 12:31:23 78 [...]を作成しました。struct以前strtokは、個々の値をトークン化し、atofそれらを保存するために使用していました。ただし、時間をトークン化しようとするとエラーが発生します:変換できませんstd::string' to 'char*' for argument 1 to 'char*'

struct time
{
    int hours;
    int minutes;
    int seconds;
    double price;
};

int main()
{
    string file, input;
    time* time_array;
    char* tok;

    cout << "Enter a file name to read input: ";
    cin >> file;

    ifstream file_name(file.c_str());

    file_name >> input;
    file_name >> input;

    //while(!file_name.eof())
    for(int i = 0; i < 4; i++)
    {
        time_array = new time;
        file_name >> input;
        tok = strtok(input, ":"); //ERROR HERE
        while(tok != NULL)
        {
            *time_array.hours = atof(tok[0]);
            *time_array.minutes = atof(tok[1]);
            *time_array.seconds = atof(tok[2]);
        }
        file_name >> input;
        *time_array.prine = atof(input);
    }
}
4

4 に答える 4

4

strtok私はこの仕事にはまったく使いません1。Cのようなツールを使用する場合は、fscanfを使用してデータを読み取ります。

// note there here `file_name` needs to be a FILE * instead of an ifstream.
fscanf(file_name, "%f:%f:%f %f", &hours, &minutes, &seconds, &price);

ただし、C ++を作成するほとんどの人は、よりタイプセーフなものを好みます。1つの可能性は、 Boost.formatを使用してデータを読み取るために、本質的に同じフォーマット文字列を使用することです。

別の可能性は、ストリームエクストラクタを使用することです。

char ignore1, ignore2;
file >> hours >> ignore1 >> minutes >> ignore2 >> seconds >> price;

これが何をするか/どのように機能するかについて:各エクストラクタは入力ストリームから1つのアイテムを読み取ります。それぞれのエクストラクタfloatは数値を読み取ります。それぞれのエクストラクタはchar1文字を読み取ります。この場合、次のように表示されます。99:99:99 99ここで、9は「数字」を意味します。したがって、数値、コロン、数値、コロン、数値、および別の数値を読み取ります(エクストラクタは空白を自動的にスキップします)。2つのコロンは変数に読み込まれchar、無視するか、実際にコロンであることを確認して、入力データが正しい形式であることを確認できます。

その手法の完全なコンパイル可能なデモを次に示します。

#include <iostream>


int main() {
    float hours, minutes, seconds, price;
    char ignore1, ignore2;

    std::cin >> hours >> ignore1 >> minutes >> ignore2 >> seconds >> price;

    std::cout << "H:" << hours 
              << " M:" << minutes 
              << " S:" << seconds 
              << " P:" << price << "\n";
    return 0;
}

確かにもっと多くの可能性がありますが、少なくともそれらはいくつかの合理的なものです。


  1. 正直なところ、自分が使う仕事があるstrtokどうかはわかりませんが、少なくとも少しは誘惑されたり、あまりstrtokデザインされていなかったので使えるようになっているところもあります。しかし、この場合、似たようなものを使う理由すら見当たらないstrtok
于 2012-12-06T15:39:16.700 に答える
1

strtokstring引数としてを取りません-それは。を取りますchar*。ヘッダー内のすべての関数と同様に、cstringC ++文字列ではなくC文字列で機能するC関数であり、通常はC++では使用しないでください。

代わりに、文字列クラスのメソッドを使用してください。

于 2012-12-06T15:29:31.093 に答える
1

簡単に言うと、変更可能な文字列が必要なため、 std::stringwithを直接使用することはできません。からCスタイルの文字列を取得するために使用する場合でも、読み取り専用です。strtokstrtokc_str()std::string

本当に使用したい場合はstrtok、たとえば次のようにして、文字列を変更可能なバッファに複製する必要があります。

char* str = strdup(input.c_str());

これを行う場合free(str)は、関数の最後で呼び出すようにしてください。そうしないと、メモリリークが発生します。

于 2012-12-06T16:08:44.990 に答える
0

この方法を使用すると、単純なケースを簡単に作成できますstring::find。ただし、Boost.Tokenizerを見てください。

strtokを返すため、std :: string.c_str()では機能しませんconst char*。引数としてではなく、 。strtokを取ります。stringchar*

于 2012-12-06T15:28:27.600 に答える