【问题标题】:Reading quoted string in c++在 C++ 中读取带引号的字符串
【发布时间】:2015-10-12 02:16:47
【问题描述】:

我正在尝试从文件中读取带引号的字符串并将其存储在字符串中。我正在从文件中读取字符串,输入文件是这样的:

"Rigatoni" starch 2.99
"Mac & Cheese" starch 0.50
"Potato Salad" starch 3.59
"Fudge Brownie" sweet 4.99
"Sugar Cookie" sweet 1.50

我尝试做几件事:

1.

input.open(filename);
    if (input.fail())
    {
        std::cout << "File is not found!";
        exit(1);
    }   
    else
    {    
        std::string foodName = ""; std::string foodType = "";
        double cost;
        input >> foodName >> foodType >> cost;
        foodName = foodName.substr(1, foodName.size()-2);    
        std::cout << foodName << " " << foodType << " " << cost << std::endl;
    }


    input.close();

此版本仅适用于第一行。在第一行之后,我没有得到整个引用的单词。另一个版本读取整个引用的单词,但是,后面的单词和数字是分开的。

input.open(filename);
        if (input.fail())
        {
            std::cout << "File is not found!";
            exit(1);
        }   
        else
        {


            std::string line = "";
            while (std::getline(input, line, '\n')) //delimeter is new line
            {
                if (line != "")
                {
                    std::stringstream stream(line);
                    std::string foodName = "";
                    while (std::getline(stream, foodName, '"') ) //delimeter is double quotes
                    {                   
                        std::cout << "current word " << foodName << std::endl;
                    }
                }
            }
        }   input.close();

我的目标是阅读 3 个单独的单词。我查看了 stackoverflow 中的其他类似主题,但找不到适合我的问题的解决方案

【问题讨论】:

    标签: c++ ifstream


    【解决方案1】:

    这对于 C++14 的 std::quoted 来说变得微不足道:

    std::string foodName, foodType;
    double cost;
    while (fs >> std::quoted(foodName) >> foodType >> cost)
    {
    }
    

    是的,这将正确地将"some word" 解析为some word。没有支持 C++14 的编译器? (你应该,例如 Fedora 22 附带 GCC 5.1.0)然后使用 Boost。标准库在此 Boost 组件之后建模 std::quoted,因此它应该可以正常工作。

    您的代码中还有一些其他问题:

    1. 流有一个转换运算符来布尔。这意味着你可以这样做:if (!input.open(filename)) { ... }

    2. input.close() 是多余的。析构函数会自动关闭流。

    3. 你不检查输入是否有效,即if (!(input &gt;&gt; a &gt;&gt; b &gt;&gt; c)) { // error }

    【讨论】:

    • 我忘了说我需要使用 C++07/TR1。但是你的方法很容易使用。
    • 对于包含双引号的带引号的字符串(例如,两个双引号,“她说,”“Hello!”“”)是否有标准的转义序列?
    • 很好,+1!今天学到了一些新东西 (std::quoted)。
    • @franji1 不知道你的意思,但它正确处理嵌套引号。一般来说,它类似于 CSV 解析器。
    • @franji1 在您的情况下,将示例修改为:std::getline(std::cin, s); std::cout &lt;&lt; std::quoted(s); 输出为 "\"She said, \"\"Hello!\"\"\"" 我按字面意思粘贴了您的输入。
    【解决方案2】:

    我经常用这个来读引号:

    std::string skip; // throw this away
    std::string foodName;
    std::getline(std::getline(input, skip, '"'), foodName, '"');
    

    第一个 std::getline 读取(并删除)第一个引号。它返回输入流,因此您可以将其包装在另一个 std::getline 中,该 std::getline 会读取您的变量直到结束引号。

    例如这样:

    #include <string>
    #include <sstream>
    #include <iostream>
    
    std::istringstream input(R"~(
    "Rigatoni" starch 2.99
    "Mac & Cheese" starch 0.50
    "Potato Salad" starch 3.59
    "Fudge Brownie" sweet 4.99
    "Sugar Cookie" sweet 1.50
    )~");
    
    int main()
    {
        std::string skip; // dummy
        std::string foodName;
        std::string foodType;
        float foodValue;
    
        while(std::getline(std::getline(input, skip, '"'), foodName, '"') >> foodType >> foodValue)
        {
            std::cout << "food : " << foodName << '\n';
            std::cout << "type : " << foodType << '\n';
            std::cout << "value: " << foodValue << '\n';
            std::cout << '\n';
        }
    }
    

    输出:

    food : Rigatoni
    type : starch
    value: 2.99
    
    food : Mac & Cheese
    type : starch
    value: 0.5
    
    food : Potato Salad
    type : starch
    value: 3.59
    
    food : Fudge Brownie
    type : sweet
    value: 4.99
    
    food : Sugar Cookie
    type : sweet
    value: 1.5
    

    【讨论】:

    • 谢谢@Galik,这就是我要找的。​​span>
    猜你喜欢
    • 1970-01-01
    • 2015-10-29
    • 2017-03-28
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    相关资源
    最近更新 更多