如何 return 空终止的 const char* 向量?
How to return a vector of null terminated const char*?
我正在尝试逐行读取文件。
将每一行转换为空终止字符串。
将所有行推入一个向量并 return 它。
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 字符串都是在堆栈中创建的,而函数 return 是一个 char* 向量到任何地方。
我正在尝试通过以下方式在堆上分配内存:
OneLine = new char[LineStr.size()+1];
但是我卡住了,因为一旦分配了我就不能复制任何东西进去;内容是常量。
我究竟要如何在 const char* 上使用 new 关键字并在它意识到它是 const 之前同时向其添加内容?
(更何况我还得一个一个删除,另一边...真是一团糟)
编辑:
我宁愿 return 一个向量,但这一切都是因为我不知道将向量转换为 const char** 的快速(一行)方法:
void glShaderSource(GLuint shader,
GLsizei count,
const GLchar **string,
const GLint *length);
返回 std::vector<char*>
充满了问题。
您必须为每一行分配内存。该函数的客户端必须添加代码以释放内存。客户端代码变得比它需要的更复杂。
客户端函数必须知道 char*
是使用 malloc
还是 operator new
分配的。他们必须根据用于分配内存的方法遵循适当的内存释放方法。再一次,客户对函数的作用和作用了解得太多了。
一个更好的方法是 return 只是一个 std::vector<std::string>
.
std::vector<std::string> FileContents;
std::string LineStr;
while (fromFile.good()==true)
{
getline(fromFile,LineStr);
FileContents.push_back(LineStr);
}
fromFile.close();
return FileContents;
如果必须return一个std::vector<char*>
,可以使用:
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;
您可以在 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::data & std::transform
我假设 typedef char Flchar;
在您的(OpenGL?)库中的某处,或者至少
static_assert("Flchar same size as char", sizeof(Flchar) == sizeof(char));
顺便说一句,我们都知道 sizeof(char)
始终为 1,因此您可以在 static_assert
中编码 sizeof(Flchar)==1
结合 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 的回答仍然是最准确的。
我正在尝试逐行读取文件。 将每一行转换为空终止字符串。 将所有行推入一个向量并 return 它。
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 字符串都是在堆栈中创建的,而函数 return 是一个 char* 向量到任何地方。
我正在尝试通过以下方式在堆上分配内存:
OneLine = new char[LineStr.size()+1];
但是我卡住了,因为一旦分配了我就不能复制任何东西进去;内容是常量。
我究竟要如何在 const char* 上使用 new 关键字并在它意识到它是 const 之前同时向其添加内容?
(更何况我还得一个一个删除,另一边...真是一团糟)
编辑: 我宁愿 return 一个向量,但这一切都是因为我不知道将向量转换为 const char** 的快速(一行)方法:
void glShaderSource(GLuint shader,
GLsizei count,
const GLchar **string,
const GLint *length);
返回 std::vector<char*>
充满了问题。
您必须为每一行分配内存。该函数的客户端必须添加代码以释放内存。客户端代码变得比它需要的更复杂。
客户端函数必须知道
char*
是使用malloc
还是operator new
分配的。他们必须根据用于分配内存的方法遵循适当的内存释放方法。再一次,客户对函数的作用和作用了解得太多了。
一个更好的方法是 return 只是一个 std::vector<std::string>
.
std::vector<std::string> FileContents;
std::string LineStr;
while (fromFile.good()==true)
{
getline(fromFile,LineStr);
FileContents.push_back(LineStr);
}
fromFile.close();
return FileContents;
如果必须return一个std::vector<char*>
,可以使用:
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;
您可以在 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::data & std::transform
我假设 typedef char Flchar;
在您的(OpenGL?)库中的某处,或者至少
static_assert("Flchar same size as char", sizeof(Flchar) == sizeof(char));
顺便说一句,我们都知道 sizeof(char)
始终为 1,因此您可以在 static_assert
sizeof(Flchar)==1
结合 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 的回答仍然是最准确的。