从中加载字符串时出现sscanf问题

时间:2014-03-11 18:11:21

标签: c++ string winapi opengl std

所以,我在OpenGL中为我的项目制作了一个模型加载器。 我正在加载Wavefront OBJ模型文件。 它加载很好,但最大的问题是加载MTL文件时。

我使用sscanf从文件中读取数据。 MTL材料在文件中告知图像的名称。

类似于:map_Kd image.bmp

当我从文件中读取图像名称时出现问题。

我使用LoadImage()函数从位图文件中获取像素数据。 当我告诉它加载给定文件名时,它会抛出一个Unhandled Exception消息()。 是的,我有项目文件夹中的图像及其所有子文件夹,以防出现问题。

这是消息:

Unhandled exception at 0x57e1d51c (msvcr100d.dll) in OBJ MODEL LOADER.exe: 0xC0000005: Access violation reading location 0x622e656d.

这是我用来加载图片的功能:

GLuint load_texture(char* path)
{
    GLuint tex;
    HBITMAP bm = 0;
    bm = (HBITMAP)LoadImage(NULL, path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    BITMAP b;
    GetObject(bm, sizeof(b), &b);
    glEnable(GL_TEXTURE_2D);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, b.bmWidth, b.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, b.bmBits);

return tex;
}

这是获取图像名称的功能(等等......):

void load_material(char* mtlpath, int loc, MODEL &m)
{
    std::ifstream a(mtlpath);
    std::vector<std::string*> file;
    char buff[255];
    if(!a.is_open())
    {
        MessageBox(g_hwnd, "Error when loading a specific material in the MTL file", "MTL(II) ERROR", 0);
    }

    while(!a.eof())
    {
        a.getline(buff, 255);
        file.push_back(new std::string(buff));
    }

    char* name;
    char* image;
    GLuint ii;

    sscanf(file[loc]->c_str(), "newmtl %c*",&name);
    for(int i = loc; i < file.size(); i++)
    {
        if((file[i]->c_str()[0] == 'm'))// && (file[i]->c_str()[1] == 'a') && (file[i]->c_str()[2] == 'p') && (file[i]->c_str()[3] == '_') && (file[i]->c_str()[4] == 'K') && (file[i]->c_str()[5] == 'd'))
        {
            sscanf(file[i]->c_str(), "map_Kd %s", &image);
            SetWindowText(g_hwnd, image);
            break;
        }
    }
    std::ofstream s("aa.txt");
    s << image;
    s.close();
    ii = 0;
    m.m.push_back(new material(name, image, ii));
    a.close();
}

我已经尝试将%s(sscanf调用)更改为%* c,%c,%* c,%c [^]和其他多个。

我还要提一下,我试图直接将我的图像名称放在&#34;图像&#34;变量没有从文件中检索它,它完全像那样。

如何从字符串中成功检索图像名称?

顺便说一下,我不想使用任何其他东西(MCI,SDL);

2 个答案:

答案 0 :(得分:0)

简而言之:将std::vector<std::string*>替换为std::vector<std::string>,将scanf替换为std::stringstream

答案 1 :(得分:0)

%c读取单个字符,但您尝试读取字符串,因此需要使用%s

%ssscanf()一起使用时,必须事先预先分配目标缓冲区,但您没有这样做。您正在将未初始化的char*指针传递给sscanf(),因此它会尝试将字符串数据写入随机内存,从而导致崩溃。

尝试更像这样的东西:

void load_material(char* mtlpath, int loc, MODEL &m)
{
    std::ifstream a(mtlpath);
    std::vector<std::string> file;
    char buff[256];

    if (!a.is_open())
    {
        MessageBox(g_hwnd, "Error when loading a specific material in the MTL file", "MTL(II) ERROR", 0);
    }

    while (a.getline(buff, 255))
    {
        buff[a.gcount()] = '\0';
        file.push_back(buff);
    }
    a.close();

    char name[256] = {0};
    char image[256] = {0};
    GLuint ii;

    sscanf(file[loc].c_str(), "newmtl %255s", name);
    for(int i = loc; i < file.size(); i++)
    {
        if (sscanf(file[i].c_str(), "map_Kd %255s", image) == 1)
        {
            SetWindowText(g_hwnd, image);
            break;
        }
    }

    std::ofstream s("aa.txt");
    s << image;
    s.close();
    ii = 0;
    m.m.push_back(new material(name, image, ii));
}

或者,摆脱sscanf(),在这种情况下你真的不需要它:

void load_material(char* mtlpath, int loc, MODEL &m)
{
    std::ifstream a(mtlpath);
    std::vector<std::string> file;
    std::string buff;

    if (!a.is_open())
    {
        MessageBox(g_hwnd, "Error when loading a specific material in the MTL file", "MTL(II) ERROR", 0);
    }

    while (std::getline(a, buff))
        file.push_back(buff);
    a.close();

    std::string name;
    std::string image;
    GLuint ii;

    if (file[loc].compare(0, 7, "newmtl ", 7) == 0)
        name = file[loc].substr(7);

    for(int i = loc; i < file.size(); i++)
    {
        if (file[i].compare(0, 7, "map_Kd ", 7) == 0)
        {
            image = file[i].substr(7);
            SetWindowText(g_hwnd, image.c_str());
            break;
        }
    }

    std::ofstream s("aa.txt");
    s << image;
    s.close();
    ii = 0;
    m.m.push_back(new material(name.c_str(), image.c_str(), ii));
}