【问题标题】:appending to a string does not change string value附加到字符串不会更改字符串值
【发布时间】:2013-08-18 08:50:46
【问题描述】:

我正在尝试为一个项目学习 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 对象的检查显示其“路径_”成员值只是“conf”而不是预期的“conf/log”。 我可以确定 CONFIG_PATH 是在 LOG_PATH 之前初始化的吗,这可能是问题吗?

编辑: 我阅读了标准,看来您不能依赖全局变量的任何初始化顺序。 这意味着 CONFIG_PATH 和 LOG_PATH 的声明显然是错误的,我可能应该将它们包装成这样的函数调用:

const IO::Path &getConfigPath(){
  static IO::Path config{"conf"};
  return config;
};

这就是字符串追加失败的原因吗?

【问题讨论】:

  • 为什么不使用+ 连接字符串?而且您不必在追加之前进行预订。
  • 好的。我真的很好奇。 push_back() 是否对单个字符表现出相同的问题,或者 nothing 似乎根本没有修改 parentPath
  • codepad.org/FyZh0ZMh,稍作修改,运行良好
  • 向我们展示您调用函数的行
  • 没有修改字符串。

标签: c++ c++11 stat


【解决方案1】:

忽略你问题的原因,我强烈建议你使用这个简单的版本:

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;
    }
}

【讨论】:

  • 我已经按照建议重写了代码(看起来确实干净多了),但似乎没有区别。
  • @Hans:那你的问题可能出在调用代码的某个地方。
【解决方案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;
    }
}

【讨论】:

  • 两者(strFinal.append(str1).append(str2)和strFinal = str1 + str2有什么区别吗?
  • 用 operator+ 代替 append 尝试过:没有进行连接。
【解决方案3】:

Here's an SSCCE demonstrating that your function works correctly。问题在于您没有向我们展示的代码。

【讨论】:

  • 我已经添加了调用代码。整个 Path 类型比较大,所以我添加了构造函数定义和调用代码。
  • 这应该是个评论。
【解决方案4】:

问题几乎可以肯定是一些配置问题(两个项目之间的编译器选项、链接器选项或预处理器定义不匹配),因为当我将两个项目合并为一个时,它不会发生。 感谢有关连接功能的 cmets:稍后我会将其重写为更易读的形式。 感谢大家提供帮助的 cmets。

编辑:发现问题。 预处理器#define 用于打开某些路径成员的依赖于 linux 的实现(主要是创建新目录和文件的函数)在主项目中打开,但在库中未打开。这可能是在链接库时引起的问题。现在就像一个魅力。

【讨论】:

  • 完成。问题确实是由于库中不存在预处理器指令,它用于“打开”某些函数的依赖于 linux 的实现。因为它们存在于可执行项目中,所以它可能会破坏链接过程。我想我现在知道“未定义的行为”是什么意思了:)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 2012-01-12
  • 2012-05-28
相关资源
最近更新 更多