这是我遇到的一个问题,我有一个文件名向量,我想检查它们是以.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
答案 0 :(得分:4)
这不会显示在您的问题中,但textureFileList
会按值返回,这意味着您会获得它返回的std::vector<std::string>
的副本。您已经两次调用此函数,一次用于begin()
,然后一次用于end()
,这意味着您在不同的向量副本上调用这些函数。显然,一个副本的开头与另一个副本的结尾无关。不仅如此,这些副本之后立即被销毁,因为它们是临时的。相反,您应该存储一个副本并在其上调用begin
和end
:
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引用。