我正在尝试为项目学习c ++,而且我遇到了字符串连接的问题。 我的应用程序由应用程序本身和静态链接的库项目组成。 在库中,我定义了一个表示文件系统路径的类型,充当std :: string路径文字的包装器。 我已经定义了一个函数来将父文件夹的路径与文件/文件夹本身的(用户提供的)名称连接起来,并根据需要添加路径分隔符。 功能代码如下所示:
std::string normalize(std::string parentPath, const std::string& name) {
if (name.empty()) {
return parentPath;
} else {
parentPath.reserve(parentPath.length()+name.length()+1);
if (*name.begin() != Path::SEGMENT_SEPARATOR) {
parentPath.append(1,Path::SEGMENT_SEPARATOR);
}
if(*name.rbegin() != Path::SEGMENT_SEPARATOR){
parentPath.append(name);
}else{
parentPath.append(name.begin(), --name.end());
}
return parentPath;
}
}
(Path :: SEGMENT_SEPARATOR是一个const char'/')
问题在于:每次调用string :: append似乎都没有做任何事情。 我用gdb调试了函数,而且parentPath的内容没有改变。 我检查了用户输入,在输入中查找“/ 0”或其他无效字符(“名称”),但没有发现任何错误。
当我将完全相同的函数移动到应用程序项目(在库项目之外)时,它确实按预期工作(使用相同的输入)。
两个项目都使用相同的工具集(GCC 4.8.1并使用C ++ 11方言)和相同的编译器参数进行编译(所有警告都打开,代码中没有收到警告)。 我的代码中有什么东西能以这种方式破坏string :: append吗?
编辑:该函数来自:
Path::Path(const Path& parent, const std::string& name) : path_(normalize(parent.path_, name)) { }
Path::Path(const Path& parent, const char* name) : Path(parent, std::string(name)) {}
反过来从(头文件)调用:
extern const IO::Path CONFIG_PATH;
extern const IO::Path LANGUAGES_PATH;
使用cpp文件中的定义:
const IO::Path Game::CONFIG_PATH{"conf"};
const IO::Path Game::LOG_PATH{CONFIG_PATH,"log"};
检查LOG_PATH对象将其“path_”成员值显示为“conf”而不是“conf / log”。 我可以确定在LOG_PATH之前初始化CONFIG_PATH,这可能是问题吗?
编辑: 我读了标准,似乎你不能依赖于全局变量的任何初始化顺序。 这意味着CONFIG_PATH和LOG_PATH的声明显然是错误,我应该把它们包装成这样的函数调用:
const IO::Path &getConfigPath(){
static IO::Path config{"conf"};
return config;
};
这可能是字符串追加失败的原因吗?
答案 0 :(得分:2)
您可以使用
string str1, str2, strFinal;
strFinal = str1 + "some static string" + str2;
我认为你应该
仅供参考:
std::string normalize(std::string parentPath, const std::string& name)
{
if (name.empty())
return parentPath;
else
{
if (name[0] != '/')
parentPath += '/';
if(name[name.length()-1] != '/')
parentPath += name;
else
parentPath.append(name.begin(), name.end()-1);
return parentPath;
}
}
答案 1 :(得分:2)
忽略问题的原因,我强烈建议您使用这个简单的版本:
std::string normalize(std::string parentPath, const std::string& name)
{
if (name.empty())
return parentPath;
else
{
if (name.front() != Path::SEGMENT_SEPARATOR)
parentPath += Path::SEGMENT_SEPARATOR;
if(name.back() != Path::SEGMENT_SEPARATOR)
parentPath += name;
else
parentPath.append(name.begin(), name.end()-1);
return parentPath;
}
}
答案 2 :(得分:2)
Here's an SSCCE demonstrating that your function works correctly。问题在于您不向我们展示的代码。
答案 3 :(得分:0)
问题几乎可以肯定是一些配置问题(编译器选项,链接器选项或两个项目之间的预处理器defs不匹配),因为当我将两个项目合并为一个时,它不会发生。 感谢对连接函数的评论:稍后我将把它重写为更易读的形式。 感谢大家的有益评论。
编辑:发现了问题。 用于打开某些Path成员(主要是创建新目录和文件的函数)的Linux依赖实现的预处理器#define在主项目中打开,但在库中没有打开。当链接库时,这可能导致问题。现在就像一个魅力。