从迭代器分配字符串

时间:2014-06-22 20:26:58

标签: c++ stl

这是我遇到的一个问题,我有一个文件名向量,我想检查它们是以.jpg还是.png结尾,所以我用迭代器和STL做了一些代码,这也是我用来创建一个std: :将这些名称映射为键并使用值作为纹理,因此这是我的代码,它在第11行执行分段错误错误:

#include "TextureManager.h"

std::map<std::string,sf::Texture> createTextureArray(){
std::map<std::string,sf::Texture> textureArray;

std::vector<std::string>::iterator strIt;
std::string fName;

for(strIt = textureFileList().begin(); strIt != textureFileList().end(); strIt++){
    sf::Texture texture;
    fName = *strIt;
    if(fName[fName.size()] == 'g' && fName[fName.size()-1] == 'p' && fName[fName.size()-2] == 'j' && fName[fName.size()-3] == '.'){
        texture.loadFromFile(fName);
        textureArray[fName] = texture;
    }
    else if(fName[fName.size()] == 'g' && fName[fName.size()-1] == 'n' && fName[fName.size()-2] == 'p' && fName[fName.size()-3] == '.'){
        texture.loadFromFile(fName);
        textureArray[fName] = texture;
    }
}
return textureArray;
}

我认为这是尝试理解问题所需的唯一代码,但如果有人想要更多此代码,请Github repo

3 个答案:

答案 0 :(得分:4)

这不会显示在您的问题中,但textureFileList会按值返回,这意味着您会获得它返回的std::vector<std::string>的副本。您已经两次调用此函数,一次用于begin(),然后一次用于end(),这意味着您在不同的向量副本上调用这些函数。显然,一个副本的开头与另一个副本的结尾无关。不仅如此,这些副本之后立即被销毁,因为它们是临时的。相反,您应该存储一个副本并在其上调用beginend

std::vector<std::string> fileList = textureFileList();
for(strIt = fileList.begin(); strIt != fileList.end(); strIt++){

答案 1 :(得分:0)

fName[fName.size()]总是&#39; \ 0&#39;。

你应该使用

if(fName[fName.size()-1] == 'g' && fName[fName.size()-2] == 'p' && fName[fName.size()-3] == 'j' && fName[fName.size()-4] == '.'){

else if(fName[fName.size()-1] == 'g' && fName[fName.size()-2] == 'n' && fName[fName.size()-3] == 'p' && fName[fName.size()-4] == '.'){

答案 2 :(得分:0)

我认为函数textureFileList()通过引用返回std::vector<std::string>类型的对象。

由于访问字符串中不存在的字符,可能会发生分段错误。

if(fName[fName.size()] == 'g' && fName[fName.size()-1] == 'p' && fName[fName.size()-2] == 'j' && fName[fName.size()-3] == '.'){

索引fName.size()的字符串没有这样的字符。索引的有效范围是0,size() - 1,前提是size()不等于零。

你应该使用另一种方法。您必须使用成员函数rfind()找到句点,然后将子字符串与给定的扩展名进行比较。

这是一个例子

#include <iostream>
#include <string>

int main() 
{
    std::string s( "SomeFile.jpg" );

    std::string::size_type n = s.rfind( '.' );

    if ( n != std::string::npos && s.substr( n ) == ".jpg" )
    {
        std::cout << "It is a JPEG file" << std::endl;
    }

    return 0;
}        

输出

It is a JPEG file

您的for循环可以按以下方式编写

for ( const std::string &fName : textureFileList() )
{
    const char *ext[] = { "jpg", "png" };

    std::string::size_type n = s.rfind( '.' );

    if ( n != std::string::npos && 
         ( fName.substr( n + 1 ) == ext[0] || fName.substr( n + 1 ) == ext[1] ) )
    {
        sf::Texture texture;
        texture.loadFromFile( fName );
        textureArray[fName] = texture;
    }
}

如果你需要删除扩展名,那么你可以简单地写

fName.erase( n );

在这种情况下,fName必须在for语句中定义为非const引用。