配置分析器打印空白 只是为了好玩(谁知道我稍后会用到它),我在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; } } #include//for std::basic_流(又称std::string) #包含//标准::基本字符串(也称标准::字符串) #include//for std::map #包含//用于字符类型测试,c样式 std::map configParser(std::istream和stream、const char和comment、const char和separator){ std::map options;//保存键、值对 std::string key,value;//so options[key]=value bool separatorfound;//用于区分键和值 while(溪流){//在溪流好的时候对其进行操作 char current=stream.get();//current将保存从流返回的下一个字符 如果(current=='\n'){//current是换行符 options[key]=value;//将key、value对添加为找到的选项 key=”“;//重置键 value=”“;//重置值 separatorfound=false;//重置separatorfound 继续;//跳回到顶部 } 否则,如果(isspace(current)){//current是下列之一:\r\t,[SPACE] 继续;//吃下空白,然后跳回到顶部 } 如果(current==comment){//current是注释标记,则为else getline(stream,key,'\n');//吃掉行的其余部分。我使用key,因为它总是在那里 //没有,因为创建字符串对象吃线 key=”“;//重置键 继续;//跳回到顶部 } 如果(current==分隔符){//current是分隔符标记,则为else separatorfound=true;//更新分隔符状态 继续;//跳回到顶部 } 否则{//current必须是一个符号 如果(!separatorfound){//尚未找到分隔符。因此,必须是键 key+=current;//给key下一个字母 继续;//跳回到顶部 } //否则,它必须是一个值 value+=current;//改为给value下一个字母。 } } 返回选项; } #包括 #包括 int main(){ 地图选项; std::字符串行; while(true){ getline(标准::cin,line); std::istringstream(线); options=configParser(流“#”和“:”); for(自动迭代器=options.begin();迭代器!=options.end();迭代器++){ std::coutfirst

配置分析器打印空白 只是为了好玩(谁知道我稍后会用到它),我在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; } } #include//for std::basic_流(又称std::string) #包含//标准::基本字符串(也称标准::字符串) #include//for std::map #包含//用于字符类型测试,c样式 std::map configParser(std::istream和stream、const char和comment、const char和separator){ std::map options;//保存键、值对 std::string key,value;//so options[key]=value bool separatorfound;//用于区分键和值 while(溪流){//在溪流好的时候对其进行操作 char current=stream.get();//current将保存从流返回的下一个字符 如果(current=='\n'){//current是换行符 options[key]=value;//将key、value对添加为找到的选项 key=”“;//重置键 value=”“;//重置值 separatorfound=false;//重置separatorfound 继续;//跳回到顶部 } 否则,如果(isspace(current)){//current是下列之一:\r\t,[SPACE] 继续;//吃下空白,然后跳回到顶部 } 如果(current==comment){//current是注释标记,则为else getline(stream,key,'\n');//吃掉行的其余部分。我使用key,因为它总是在那里 //没有,因为创建字符串对象吃线 key=”“;//重置键 继续;//跳回到顶部 } 如果(current==分隔符){//current是分隔符标记,则为else separatorfound=true;//更新分隔符状态 继续;//跳回到顶部 } 否则{//current必须是一个符号 如果(!separatorfound){//尚未找到分隔符。因此,必须是键 key+=current;//给key下一个字母 继续;//跳回到顶部 } //否则,它必须是一个值 value+=current;//改为给value下一个字母。 } } 返回选项; } #包括 #包括 int main(){ 地图选项; std::字符串行; while(true){ getline(标准::cin,line); std::istringstream(线); options=configParser(流“#”和“:”); for(自动迭代器=options.begin();迭代器!=options.end();迭代器++){ std::coutfirst,c++,string,map,config,C++,String,Map,Config,您的解析器大部分工作正常,但包装器不工作。getline不会捕获'\n',并且您的解析器不会从没有'\n'的行捕获结果 将main()简化为: intmain(){ 地图选项; std::字符串行; options=configParser(std::cin,#',':'); for(自动迭代器=options.begin();迭代器!=options.end();迭代器++){ std::coutfirst第1期:您的行实际上不包含换行符,因为getline会丢弃它。一个可能的解决方案是:st

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

将main()简化为:

intmain(){
地图选项;
std::字符串行;
options=configParser(std::cin,#',':');
for(自动迭代器=options.begin();迭代器!=options.end();迭代器++){

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

问题2:未初始化Separator或Found
。应将其初始化为false

第3期:您应该在获得字符后检查流是否良好。也就是说,您应该执行以下操作:

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

为什么不
for(自动const&p:选项)std::我看不出我有这个功能,但是解析器不会永远运行下去吗?我想科林发现了错误;但一般来说,只要做一些调试,以某种方式找到错误。即使是简单的printf调试在这里也会有所帮助。好的,谢谢你…所以我当时只是很愚蠢…还有,我为什么要在事后检查呢?如果它不好,然后我会怎么办试着提取一个字符?因为我没有测试它,它不是无效的吗?是的,它确实不应该在这里产生影响,但是这样做是一个很好的实践,因为有些情况下它很重要。想扩展吗?不想太难。我只是没有做过很多真实世界的编程,所以我很好奇人们什么时候可以做soWell,事情是这样的按照现在的方式,循环体运行的时间比需要的时间多一次。一个可能导致不良行为的简单示例是读取流的内容并将其转储到文件中:流的最后一个字符将写入文件两次。啊,好的,我明白你的意思了
while(true) {
    char current = stream.get();
    if (!stream) break;