【问题标题】:How to return a vector of null terminated const char*?如何返回一个空终止的 const char* 向量?
【发布时间】:2015-07-21 05:10:35
【问题描述】:

我正在尝试逐行读取文件。 将每一行转换为以空字符结尾的字符串。 将所有行推入向量并返回。

vector<const char*> TypeGLscene::LoadGLshader (string ThisFile)
{
ifstream fromFile;
fromFile.open(ThisFile);
if (fromFile.good()==false)
{
    cout<<"Could not find file: "<<ThisFile<<endl;
    exit(1);
}

vector<const char*>  FileContents;
const char*    OneLine;
string         LineStr;

while (fromFile.good()==true)
{
    getline(fromFile,LineStr);
    OneLine = LineStr.c_str();
    FileContents.push_back(OneLine);
}

fromFile.close();
return FileContents;

问题是所有的 char 字符串都是在堆栈中创建的,函数返回一个 char* 的向量到无处。

我正在尝试通过以下方式在堆上分配内存:

OneLine = new char[LineStr.size()+1];

但我卡住了,因为一旦分配,我就无法将任何内容复制到其中;内容为 const。

我到底要如何在 const char* 上使用 new 关键字并在它意识到它是 const 之前同时向它添加内容?

(更不用说我必须一个接一个地删除它们,另一方面......真是一团糟)

编辑: 我宁愿返回一个向量,但这一切都是因为我不知道将向量转换为 const char** 的快速(单行)方法:

void glShaderSource(GLuint shader,
                    GLsizei count,
                    const GLchar **string,
                    const GLint *length);

【问题讨论】:

  • 有什么原因不能返回std::vector&lt;std::string&gt;
  • 为什么向量元素必须是const char *?考虑将它们设为strings,或者如果您真的需要char *,则以 C 方式分配它们。
  • 因为 glshaderSource 需要一个 const char* 数组,如果我陷入困境并将整个着色器放在一行中,那么我不会收到有用的编译器错误消息(如果所有错误都出现在第 1 行,如果整个着色器在一行中)
  • 你不需要每行有一个字符串来获得正确的消息,你只需要在每行的末尾有 \n 个字符(即读取整个文件,而不是每行与getline)。 glShaderSource 中的多个字符串是为了在代码来自不同文件时使用。
  • @Jerem。我不知道这个。我将它作为一个字符串尝试,每行带有 \n 并且它也可以工作(并且它为编译错误提供了行号)。感谢您的提示!

标签: c++ pointers constants


【解决方案1】:

返回std::vector&lt;char*&gt; 充满了问题。

  1. 您必须为每一行分配内存。该函数的客户端必须添加代码以释放内存。客户端代码变得比它需要的更复杂。

  2. 客户端函数必须知道char*是使用malloc还是operator new分配的。他们必须根据用于分配内存的方法遵循适当的内存释放方法。再一次,客户对函数的作用和它是如何做的了解太多。

更好的方法是只返回一个std::vector&lt;std::string&gt;

std::vector<std::string>  FileContents;
std::string LineStr;

while (fromFile.good()==true)
{
    getline(fromFile,LineStr);
    FileContents.push_back(LineStr);
}

fromFile.close();
return FileContents;

如果你必须返回一个std::vector&lt;char*&gt;,你可以使用:

std::vector<char*>  FileContents;
std::string LineStr;

while (fromFile.good()==true)
{
    getline(fromFile,LineStr);
    char* line = new char[LineStr.size()+1];
    strcpy(line, LineStr.c_str());
    FileContents.push_back(line);
}

fromFile.close();
return FileContents;

【讨论】:

  • 这是一个私有函数(在这种情况下,我是客户,必须在另一端处理所有这些,我一点也不喜欢它)。如果我知道一种快速的单行方式将 vector 输入 void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
  • 很确定没有这样的方法。
  • @ThomasAn,在这种情况下,请使用我回答中的第二个代码块。
【解决方案2】:

您可以在 C++11 中转换然后调用 glShaderSource

std::vector<std::string> vec;

使用

{
  std::vector<const Glchar*> veccstr 
     = std::transform(vec.begin(), vec.end(), 
                      [](const std::string&s){
                         return static_cast<const Flchar*>(s.c_str()); });
  glShaderSource(shader, veccstr.size(), veccstr.data(), &length);
}

了解 C++11 std::vector::datastd::transform

我假设您的(OpenGL?)库中某处有一个typedef char Flchar;,或者至少是

static_assert("Flchar same size as char", sizeof(Flchar) == sizeof(char));

顺便说一句,我们都知道 sizeof(char) 始终为 1,因此您可以将 sizeof(Flchar)==1 编码为 static_assert

【讨论】:

    【解决方案3】:

    结合 Sahu 和 Jerem 的建议,我完全改变了策略并简单地(从文件读取函数)返回一个字符串,每个着色器行都有换行符:

    string TypeGLscene::LoadGLshader (string ThisFile)
    {
       ifstream fromFile;
       fromFile.open(ThisFile);
       if (fromFile.good()==false)
       {
           cout<<"Could not find file: "<<ThisFile<<endl;
           exit(1);
       }
    
       string  FileContents, oneLine;
    
       while (fromFile.good()==true)
       {
           getline(fromFile,oneLine);
           FileContents += (oneLine + "\n");
       }
       fromFile.close();
       //FileContents=FileContents.c_str();
       return FileContents;
    }
    

    然后将那个字符串输入到 glshaderSource

    char* ShaderChapters[1]; ShaderChapters[0]=&fileContent[0];
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(VertexShaderID,1,ShaderChapters,0);
    glCompileShader(VertexShaderID);
    

    尽管如此,考虑到原始问题的措辞,Sahu 的回答仍然是最准确的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      相关资源
      最近更新 更多