自动文件重命名 - const变量是否正在改变其值?

时间:2013-07-05 15:21:02

标签: c++ string winapi variables std

我是std命名空间的菜鸟,我正在编写循环遍历目录中所有jpeg文件的代码并删除任何感叹号。我正在尝试使用std::stringstd::vector。我的问题是我的变量tempname:const char tempname = (char) *filelist[j].c_str();随着向量filelist中的字符串的变化而变化(它不应该变化 - 它是一个常量变量。这是我的WinMain函数的主要内容:

std::vector<std::string> filelist;
if (!dirExists(directory)) //checks if a directory exists
{
    CreateDirectory("resized", NULL);
}
std::vector<std::string> filelist = findFiles("*.jpg"); //finds files in its directory with a given extension
int result; //for rename function
for (unsigned int j=0; j< filelist.size(); j++)
{
    std::string::size_type pos = filelist[j].find("!"); //check for exclamation points
    if (std::string::npos != pos) //found one at index "pos" in the string
    {
        switch (MessageBox(window, (LPCSTR)filelist[j].c_str(), "Illegal filename - Rename?", MB_YESNO)) //user input
        {
            case IDYES:
            {
                const char tempname = (char) *filelist[j].c_str(); //the problem
                //attempt to remove the exclamation point
                result = rename(&tempname, filelist[j].erase(pos, 1).c_str());
                if (result == 0)
                    MessageBox(window, "Renamed File", "Information", MB_OK);
                else
                    MessageBox(window, "Error renaming file", "Error", MB_OK);
                break;
            }
            case IDNO:
            {
                break;
            }
        }
    }
}

假设文件名包含不超过一个感叹号。如果我将tempname定义为const char*,这将是有意义的,因为它将是一个指针 - 如果它指向的数据发生了变化,tempname的值可能会在不违反const声明的情况下发生变化。但是拿走指针,我感到很困惑。

2 个答案:

答案 0 :(得分:3)

您意识到您的tempname声明意味着您将只复制一个字符?我很确定这不是你想要的。

您可能想要复制字符串本身并更改代码,如下所示:

            std::string const tempname = filelist[j];
            //attempt to remove the exclamation point
            result = rename(tempname.c_str(), filelist[j].erase(pos, 1).c_str());

至于为什么你所谓的const变量如果你操纵底层字符串会改变它的值,请记住,在你的原始声明中,tempname是一个值的指针,所有你说的就是指针不会改变它的值。它没有,但是指针确实如此。

此外,当将c_str与字符串操作组合时,你几乎进入了危险区域 - 看一下c_str here的文档,它明确指出在字符串对象上调用mutating成员函数可能会使结果无效c_str()调用。将std :: string与C字符串惯用法混合时必须小心。

答案 1 :(得分:0)

您发布的代码具有未定义的行为,这意味着 什么都可能发生。您定义了一个chartempname, 然后将其地址传递给renamerename要求 指向'\0'终止字符串的指针;唯一合法的 字符串将是一个空字符串。

如果您将tempname的定义替换为:

char const* tempname = filelist[j].c_str();

然后你有未定义的行为;打电话给 filelist[j].erase使此指针无效。在实践中,它 事实上将继续指向filelist[j]中的数据 (因为事实上,erase不会重新分配,所以 tempname将继续指向第一个字符 filelist[j])。

你可能想要的是:

std::string newName( filelist[j] );
newName.erase( std::remove( newName.begin(), newName.end(), '!' ),
               newName.end() );
result = rename( filelist[j].c_str(), newName.c_str() );
filelist[j] = newName;