【问题标题】:Storing String content in map on the basis of <key, value> c++基于<key, value> c++在map中存储String内容
【发布时间】:2021-09-05 05:38:42
【问题描述】:

我有一个字符串“parrot -color green -peak”。我想将此字符串以 格式存储在地图中。其中第一个字符串被视为二进制可执行对象,其余值应以 map 格式存储,其中(-string 表示键)下一个字符串被视为该特定键的值。如果值为空,则应存储为空字符串。但是从我的代码来看,它的存储键是值。还请检查从现有代码中观察到的预期输出和结果,以便更好地理解。提前致谢。

#include <iostream>
#include <string>
#include <map>

using namespace std;

int main() {
    // your code goes here
    string s = "parrot -color green -peak";
    char sep = '-';
    map<string, string> clArgs;
    
    // find first '-' and copy contents
    string executable_name = s.substr(0, s.find_first_of(sep));
    cout << "exec name = " << executable_name << endl;
    
    s.erase(0, s.find_first_of(sep));
    cout << "s = " << s << endl;
    
    // iterate over string and copy key-value pairs
    int pos;
    while ((pos = s.find_first_of(sep, 1)) != string::npos)
    {
        string keyVal = s.substr(0, pos);
        s = s.substr(pos);
        
        string key, value;
        key = keyVal.substr(0, keyVal.find_first_of(' '));
        keyVal = keyVal.substr(keyVal.find_first_of(' ')+1);
        value = keyVal.substr(0, keyVal.find_first_of(' '));
        clArgs[key] = value;
    }
    
    if (s.length() != 0)
    {
        // there is still last command line arg remaining
        // need to process it as well
        clArgs[s.substr(0, s.find_first_of(' '))] = s.substr(s.find_first_of(' ')+1);
    }
    
    cout << "Printing key-value pairs ...\n";
    for (map<string, string>::iterator it = clArgs.begin(); it != clArgs.end(); it++)
    {
        cout << "(key = " << it->first << ", value = " << it->second << ")\n";
    }
    return 0;
}
output from above code:-

exec name = parrot 
s = -color green -peak
Printing key-value pairs ...
(key = -color, value = green)
(key = -peak, value = -peak)

expected output:-

exec name = parrot 
s = -color green -peak
Printing key-value pairs ...
(key = -color, value = green)
(key = -peak, value = )

【问题讨论】:

  • 命令行解析器实现应该比您实现的更复杂一些。现在,您没有任何指示应该或不应该有哪些命令有参数。 -peak 是否有可能具有价值?如果需要一个值,那么这应该是一个错误——您不应该为尝试存储空白字符串而增加负担。
  • 检查find_first_ofs 是否真的找到任何东西是个好主意。
  • @PaulMcKenzie 我们不一定应该有价值观。在这个例子中 -peak
  • @molbdnilo 感谢您的建议。生病试一试:)
  • 您应该尝试使您的命令行解析器以其他解析器的工作方式运行。你应该已经设置了一个struct 来描述每个命令的特征,即命令的名称,命令是否必须有参数等。然后创建一个数组,映射,无论什么,结构。然后解析每个- 标记,将其与结构匹配以查看命令是否必须有参数。然后,您为获取参数而编写的代码开始发挥作用。现在,您假设每个命令都有一个参数,这显然是不正确的。

标签: c++ string algorithm stl unordered-map


【解决方案1】:
  1. 如果参数字符串是可选的,那么我建议您将输入解析为令牌,然后逐个令牌处理。
  2. 您当前假设键/值对的值始终存在。您不会在搜索空格字符后检查值是否存在。

【讨论】:

    【解决方案2】:

    您的代码相当复杂,可以从使用std::stringstreamstd::getline 中受益。字符串函数很容易传递无效索引。我建议您使用调试器来查找您的期望偏离的地方。使用getline 和一个流来拆分字符串很简单。稍微简单一点的版本可能如下所示:

    #include <iostream>
    #include <string>
    #include <map>
    #include <sstream>
    
    using namespace std;
    
    int main() {
        string s = "parrot -color green -peak";
        char sep = '-';
        map<string, string> clArgs;
    
        // extract first word
        std::stringstream ss{s};    
        std::string exec_name;
        std::getline(ss,exec_name,sep);
        
        // extract portions of the string separated by -
        std::string key_value_pair;
        while (std::getline(ss,key_value_pair,sep)) {
            // now extract first and second word 
            std::stringstream skvp{key_value_pair};
            std::string key;
            std::string value;
            skvp >> key >> value;
            clArgs[key] = value;
        }
    
        std::cout << exec_name << "\n";
        
        cout << "Printing key-value pairs ...\n";
        for (const auto& e : clArgs)
        {
            cout << "(key = " << e.first << ", value = " << e.second << ")\n";
        }
    }
    

    Output:

    parrot 
    Printing key-value pairs ...
    (key = color, value = green)
    (key = peak, value = )
    

    【讨论】:

    • 键应该有“连字符(-)”。从您的代码“连字符(-)”丢失!
    • @Amith Kotian 那是因为getline 读取所有内容但丢弃了分隔符。你当然可以加回来
    【解决方案3】:
    key = keyVal.substr(0, keyVal.find_first_of(' '));
    keyVal = keyVal.substr(keyVal.find_first_of(' ')+1);
    value = keyVal.substr(0, keyVal.find_first_of(' '));
    

    s 在第二次迭代中是“-peak”。 keyVal.find_first_of(' ')npos 并且通过 keyVal.find_first_of(' ')+1 访问字符不是您所期望的。您应该在递增之前检查它是否有 npos

    auto space = keyVal.find_first_of(' ');
    key = keyVal.substr(0, space);
    if (space != keyVal.npos) {
      keyVal = keyVal.substr(space + 1);
      value = keyVal.substr(0, keyVal.find_first_of(' '));
    } else {
      keyVal = "";
      value = "";
    }
    

    【讨论】:

    • ((unsigned type) -1)+1 将是 0,而不是 UB 问题。
    • 好吧 string.substr(0) 返回一个精确的副本,而不是 UB
    • @S.M.建议的代码没有多大帮助int pos; while ((pos = s.find_first_of(sep, 1)) != string::npos) { string keyVal = s.substr(0, pos); s = s.substr(pos); string key, value; auto space = keyVal.find_first_of(' '); key = keyVal.substr(0, space); if (space != keyVal.npos) { keyVal = keyVal.substr(space + 1); value = keyVal.substr(0, keyVal.find_first_of(' ')); } else { keyVal = ""; value = ""; } clArgs[key] = value; }
    • @S.M.请参阅先前评论中的代码 sn-p 并建议进行更改。让我知道你的意思是什么变化
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2010-10-21
    相关资源
    最近更新 更多