【问题标题】:config parser printing blanks配置解析器打印空白
【发布时间】:2014-07-13 07:20:59
【问题描述】:

只是为了好玩(谁知道我以后可能会使用它),我用 C++ 编写了一个配置文件解析器。它似乎并不困难,并且在我编写它时看不到任何问题。但是,当我对其进行测试时,配置解析器没有捕获任何内容。我已经通过代码三遍了。谁能告诉我这个问题?

#include <istream> // for std::basic_stream<char> (aka std::string)
#include <string> // for std::basic_string<char> (aka std::string)
#include <map> // for std::map<t, t>
#include <cctype> // for character type testing, c style

std::map<std::string, std::string> configParser(std::istream &stream, const char &comment, const char &seperator) {
    std::map<std::string, std::string> options; // to hold key, value pairs
    std::string key, value; // so options[key] = value
    bool seperatorFound; // for differentiating between key and value

    while(stream) { // operate on the stream while its good
        char current = stream.get(); // current will hold the next character returned from the stream

        if(current == '\n') { // current is a newline
            options[key] = value; // add the key, value pair as an option found
            key = ""; // reset key
            value = ""; // reset value
            seperatorFound = false; // reset seperatorFound
            continue; // jump back up to the top
        }

        else if(isspace(current)) { // current is one of: \r, \t, [SPACE]
            continue; // eat the white space and jump back up to the top
        }

        else if(current == comment) { // current is a comment marker
            getline(stream, key, '\n'); // eat the rest of the line. i use key since its alreay there
                                        // no since in creating a string object to eat a line
            key = ""; // reset key
            continue; // jump back up to the top
        }

        else if(current == seperator) { // current is a seperator marker
            seperatorFound = true; // update the seperator state
            continue; // jump back up to the top
        }

        else { // current must be a symbol
            if(!seperatorFound) { // haven't found the seperator yet. as a result, must be a key
                key += current; // give key the next letter
                continue; // jump back up to the top
            }

            // otherwise, it must be a value
            value += current; // give value the next letter instead.
        }
    }

    return options;
}

#include <iostream>
#include <sstream>

int main() {
    std::map<std::string, std::string> options;
    std::string line;

    while(true) {
        getline(std::cin, line);
        std::istringstream stream(line);

        options = configParser(stream, '#', ':');

        for(auto iterator = options.begin(); iterator != options.end(); iterator++) {
            std::cout<< iterator->first <<" : "<< iterator->second << std::endl;
        }

        std::cout<< std::endl << std::endl;
    }
}

【问题讨论】:

  • 科林发现了错误,我想;但通常只是做一些调试,以一种或另一种方式来查找错误。即使是简单的 printf 调试也会有所帮助。

标签: c++ string map config


【解决方案1】:

您的解析器大部分都可以工作,但包装器不能。 getline 不会捕获 '\n',并且您的解析器不会从没有 '\n' 的行中捕获结果。

将你的 main() 简化为:

int main() {
    std::map<std::string, std::string> options;
    std::string line;

    options = configParser(std::cin, '#', ':');

    for(auto iterator = options.begin(); iterator != options.end(); iterator++) {
        std::cout<< iterator->first <<" : "<< iterator->second << std::endl;
    }

     std::cout<< std::endl << std::endl;
}

而且它大部分都有效。

【讨论】:

  • 为什么不for(auto const &amp; p : options) std::cout &lt;&lt; p.first etc
  • 好吧,我知道了,但解析器不会永远运行下去吗?
【解决方案2】:

问题 1: 您的 line 实际上并不包含换行符,因为 getline 会丢弃它。一个可能的解决方案是:std::istringstream stream(line + '\n');

问题 2: seperatorFound 未初始化。应该初始化为false。

问题 3:你应该检查流是否良好你得到一个字符。也就是说,你应该这样做:

while(true) {
    char current = stream.get();
    if (!stream) break;

【讨论】:

  • 好的,谢谢...所以我当时只是很愚蠢...还有,我为什么要事后检查?如果它不好然后我尝试提取一个字符怎么办?因为我没有测试它不会是无效的吗?
  • 是的,它确实不应该在这里产生影响,但这样做是一种很好的做法,因为在某些情况下它很重要。
  • 关心扩展?不要试图变得困难。我只是没有做过很多现实世界的编程,所以我很好奇什么时候可以这样做
  • 嗯,问题是你现在这样做的方式是循环体运行的次数比它需要的多一次。一个可能导致不良行为的简单示例是读取流的内容并将它们转储到文件中:流的最后一个字符将被写入文件两次。
  • 啊好吧我明白你的意思了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 2015-05-18
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多