0

我正在尝试读取一个具有输入(时间和价格)的文件: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++ 的人更喜欢类型安全的东西。一种可能性是使用基本相同的格式字符串来使用Boost.format读取数据。

另一种可能性是使用流提取器:

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

至于这是做什么/如何工作的:每个提取器从输入流中读取一个项目。每个提取器float读取一个数字。每个提取器char读取一个字符。在这种情况下,我们希望看到:99:99:99 99,其中9表示“一个数字”。因此,我们读取一个数字、一个冒号、一个数字、一个冒号、一个数字和另一个数字(提取器会自动跳过空格)。这两个冒号被读入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

strtok不以 astring作为其论点 - 它以char*. 与标头中的所有函数一样,cstring它是一个适用于 C 字符串(而不是 C++ 字符串)的 C 函数,通常不应在 C++ 中使用。

请改用字符串类的方法。

于 2012-12-06T15:29:31.093 回答
1

简短的回答是您不能直接使用std::stringwith strtok,因为strtok需要它可以修改的字符串。即使您使用c_str()从 a 获取 C 风格的字符串std::string,它仍然是只读的。

如果您真的想使用strtok,则需要将字符串复制到可修改的缓冲区中,例如:

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

如果这样做,请确保free(str)在函数末尾调用,否则会导致内存泄漏!

于 2012-12-06T16:08:44.990 回答
0

Your simple case can easily be built using the string::find method. However, take a look at Boost.Tokenizer.

strtok will not work with std::string.c_str() because it returns const char*. strtok does not take a string as an argument, but rather a char*.

于 2012-12-06T15:28:27.600 回答