med*_*ivh 1 c++ string while-loop
我正在制作一个玩具程序来从字符串创建类(例如,我向它提供“test1 test2”,它会生成 test1.cpp、test1.h、test2.cpp、test2.h)
\n\n该操作发生在该函数中:
\n\nbool makeClassesFromString(std::string classNames){\n\n bool returnValue = true;\n\n if (classNames == ""){\n\n returnValue = false;\n\n }\n else{\n\n std::istringstream issClassNames (classNames);\n std::string sClassName;\n\n while(issClassNames.good()){\n\n issClassNames >> sClassName;\n std::string sourceName = sClassName;\n sourceName += ".cpp";\n\n std::string headerName = sClassName;\n headerName += ".h";\n\n std::ofstream source(sourceName.c_str()), std::ios::app);\n std::ofstream header(headerName.c_str()), std::ios::app);\n\n //source << "#include \\"" << headerName << "\\"";\n\n\n source.close();\n header.close();\n\n }\n\n }\n\n return returnValue;\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这些文件以追加模式打开,以确保任何已存在的类不会被意外覆盖。
\n\n我最近返回到这个程序以包含一些额外的内容 - 特别是,旧版本只是创建了两个空文件,我想修改它以创建具有必要定义和包含的文件,这样我就不必手动进入并包含每次添加它们。这揭示了意想不到的行为 - 最后一个类将任何文本添加两次。
\n\n在上面的代码示例中,我已经注释掉了我开始处理此问题的行,但是当我不注释掉它时,我会得到如下行为:
\n\ninput:\nclassmaker.exe test1 test2\n\noutput:\ntest1.h\ntest2.h\ntest1.cpp //(Which contains: #include "test1.h")\ntest2.cpp //(Which contains: #include "test2.h"#include "test2.h"\nRun Code Online (Sandbox Code Playgroud)\n\n我的猜测是,我while(issClassNames.good())用最后一个类名返回了额外的时间(因此再次将字符串附加到源文件中),但我不确定是什么行为导致了这一点。
目前提出的解决方案:
\n\nifstream在以 模式打开之前,测试尝试以ofstream模式打开的文件是否已存在。(问题:没有解决运行while一次模式不必要的问题)编辑
\n\n我已经意识到: istringstream.good() 并不是真的比预期返回 true 一次,而是它的计算结果如下:
\n\ninput: "test1 test2"\n\nevaluation:\ngood = true; extract next to string //(succeeds, overwrites empty string with "test1")\ngood = true; extract next to string //(succeeds, overwrites "test1" with "test2")\ngood = true; extract next to string //(fails, Doesn\'t overwrite "test2")\ngood = false; break loop.\nRun Code Online (Sandbox Code Playgroud)\n\n编辑 2 + 3
\n\n嗯,这很容易解决。谢谢你们大家。不幸的是,我只能将一个答案标记为已接受,因此我选择了第一个发布的答案,但我感谢您的帮助。
\n\n最终的完整程序:
\n\n#include <iostream>\n#include <fstream>\n#include <string>\n#include <sstream>\n\nvoid makeClassesFromStdInput();\nvoid makeClassesFromParameter(int argc, const char** argv);\nbool makeClassesFromString(std::string classNames);\n\nint main(int argc, const char** argv){\n\n switch (argc) {\n\n case 0: //This shouldn\xe2\x80\x99t happen\n\n break;\n\n case 1:\n\n //This will keep making classes from the CLI until\n //the user breaks the process.\n makeClassesFromStdInput();\n break;\n\n default:\n\n //This will make classes from the parameters passed\n //to the program except the first parameter which is\n //assumed to be the program name.\n\n makeClassesFromParameter(argc, argv);\n break;\n\n }\n\n return 0;\n\n}\n\nvoid makeClassesFromStdInput(){\n\n std::cout << "Input class name and press enter.\\nWhitespace delimits class names.\\nA blank line ends the process.\\n>";\n bool running = true;\n std::string classNames;\n\n while(running){\n\n std::getline(std::cin, classNames);\n running = makeClassesFromString(classNames);\n\n }\n\n}\n\nvoid makeClassesFromParameter(int argc, const char** argv){\n\n std::string classNames = "";\n\n for(int i = 1; i<argc; i++){\n\n classNames += argv[i];\n classNames += " ";\n\n }\n\n makeClassesFromString(classNames);\n\n}\n\nbool makeClassesFromString(std::string classNames){\n\n bool returnValue = true;\n\n if (classNames == ""){\n\n returnValue = false;\n\n }\n else{\n\n std::istringstream issClassNames (classNames);\n std::string sClassName;\n\n while(issClassNames >> sClassName){\n\n std::string sourceName = sClassName;\n sourceName += ".cpp";\n\n std::string headerName = sClassName;\n headerName += ".h";\n\n std::ofstream source(sourceName.c_str(), std::ios::app);\n std::ofstream header(headerName.c_str(), std::ios::app);\n\n source << "#include \\"" << headerName << "\\"";\n\n //Header is slightly more involved because we want all capital letters\n for (std::string::size_type i=0; i<headerName.length(); ++i){\n\n if(headerName[i] == \'.\'){\n\n headerName[i] = \'_\';\n }\n else{\n\n headerName[i] = toupper(headerName[i]);\n }\n }\n\n header << "#ifndef __" << headerName << "\\n"\n << "#define __" << headerName << "\\n"\n << "\\n"\n << "\\n"\n << "#endif";\n\n source.close();\n header.close();\n\n }\n\n }\n\n return returnValue;\n\n}\nRun Code Online (Sandbox Code Playgroud)\n
流无法知道您将要阅读什么。在尝试读取后,您始终需要检查读取尝试是否成功:
while(issClassNames >> sClassName) {
// do whatever processing of sClassName you want to do
}
Run Code Online (Sandbox Code Playgroud)