C++ 在c+;中读取只有字符指针的文件+;
我需要将文件内容读入某些对象,不幸的是,我不能随意使用std::string,因此必须使用char指针。 然而,当我这样做的时候,我会直接从记忆中得到一些奇怪的信号,然而,这些信号并不起作用。 因此,我直接从istream而不是std库使用getline进行了重建,但情况也是一样。 如何在不使用std::string的情况下正确读取文件C++ 在c+;中读取只有字符指针的文件+;,c++,pointers,char,getline,C++,Pointers,Char,Getline,我需要将文件内容读入某些对象,不幸的是,我不能随意使用std::string,因此必须使用char指针。 然而,当我这样做的时候,我会直接从记忆中得到一些奇怪的信号,然而,这些信号并不起作用。 因此,我直接从istream而不是std库使用getline进行了重建,但情况也是一样。 如何在不使用std::string的情况下正确读取文件 PortsContainer game::ParsePort(std::istream& stream) { PortsContainer po
PortsContainer game::ParsePort(std::istream& stream)
{
PortsContainer ports;
bool passFirstRow = false;
char* portLine = new char[1000000];
int i = 0;
while (!stream.eof())
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
if (portLine[0] == '\0' || portLine == nullptr || portLine[0] == '#')
continue;
std::stringstream ss(portLine);
if (!passFirstRow) {
char* name = new char[100];
while (!ss.eof()) {
ss.getline(name, sizeof name, ';');
Port* port = new Port();
//port->name = const_cast<char*>(name);
port->name = const_cast<char*>(name);
ports.addItem(port);
}
passFirstRow = true;
} else {
i++;
}
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
}
return ports;
}
PortsContainer game::ParsePort(std::istream& stream, std::error_code& errorBuffer)
{
try
{
return ParsePort(stream);
}
catch (std::system_error exception)
{
errorBuffer = exception.code();
}
}
PortsContainer game::GetAvailablePorts()
{
PortsContainer ports;
std::ifstream stream("./ports.csv");
std::error_code errorBuffer;
ports = ParsePort(stream, errorBuffer);
if (errorBuffer)
return PortsContainer();
return ports;
}
ports容器游戏::解析端口(std::istream&stream)
{
港口集装箱港口;
bool passFirstRow=false;
char*portLine=新字符[1000000];
int i=0;
而(!stream.eof())
{
如果(!流)
抛出标准::系统错误(错误::流错误);
if(端口线[0]='\0'| |端口线==nullptr | |端口线[0]='|')
继续;
std::stringstream ss(端口线);
如果(!passFirstRow){
字符*名称=新字符[100];
而(!ss.eof()){
ss.getline(名称,名称的大小,;);
端口*端口=新端口();
//端口->名称=常量(名称);
端口->名称=常量(名称);
端口。附加项(端口);
}
passFirstRow=true;
}否则{
i++;
}
如果(!流)
抛出标准::系统错误(错误::流错误);
}
返回端口;
}
PortsContainer游戏::ParsePort(std::istream&stream,std::error\u code&errorBuffer)
{
尝试
{
返回端口(流);
}
捕获(标准::系统错误异常)
{
errorBuffer=exception.code();
}
}
PortsContainer游戏::GetAvailablePorts()
{
港口集装箱港口;
std::ifstream流(“./ports.csv”);
std::error\u代码errorBuffer;
ports=ParsePort(流,errorBuffer);
if(errorBuffer)
返回端口容器();
返回端口;
}
您没有用任何数据填充portLine
。事实上,您根本没有从流中读取任何数据
您误用了eof()
。在首次尝试读取操作之前,eofbit
标志不会更新。因此,您必须先阅读,然后才能删除eof()
您正在泄漏端口线
和名称
缓冲区。更糟糕的是,由于不允许使用std::string
,这意味着Port::name
成员是char*
指针,这意味着您(可能)有多个Port
对象指向内存中的同一物理缓冲区。如果Port
稍后尝试释放该缓冲区,例如在其析构函数中,则会出现内存错误
请尝试类似以下内容:
PortsContainer game::ParsePort(std::istream& stream)
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
PortsContainer ports;
bool passFirstRow = false;
// better would be to use std::unique_ptr<char[]>, std::vector<char>,
// or std::string instead so the memory is freed automatically ...
char *portLine = new char[1000000];
int i = 0;
do
{
if (!stream.getline(portLine, 1000000))
{
delete[] portLine; // <-- free the buffer for line data...
throw std::system_error(Error::STREAM_ERROR);
}
if ((stream.gcount() == 0) || (portLine[0] == '#'))
continue;
if (!passFirstRow)
{
std::istringstream iss(portLine);
// better would be to use std::unique_ptr<char[]>, std::vector<char>,
// or std::string instead so the memory is freed automatically ...
char* name = new char[100];
while (iss.getline(name, 100, ';'))
{
if (iss.gcount() == 0) continue;
Port *port = new Port();
port->name = name; // <-- assumes ownership is transferred!
ports.addItem(port);
name = new char[100]; // <-- have to reallocate a new buffer each time!
}
delete[] name; // <-- free the last buffer not used...
passFirstRow = true;
} else {
++i;
}
}
while (!stream.eof());
delete[] portLine; // <-- free the buffer for line data...
return ports;
}
PortsContainer game::ParsePort(std::istream& stream, std::error_code& errorBuffer)
{
try
{
return ParsePort(stream);
}
catch (const std::system_error &exception)
{
errorBuffer = exception.code();
return PortsContainer(); // <-- don't forget to return something!
}
}
PortsContainer game::GetAvailablePorts()
{
std::ifstream stream("./ports.csv");
std::error_code errorBuffer;
return ParsePort(stream, errorBuffer); // <-- no need to check errorBuffer before returning!
}
首先我建议你阅读。然后你应该记住C++中的代码> char < /c>字符串实际上被称为null终止字节串。空终止符(不要与空指针混淆)很重要。还要记住,您分配的内存不会被初始化,甚至读取它也会导致未定义的行为。最后,您可能有一些内存泄漏。sizeof name
您希望得到什么值?我不能随意使用std::string YAIT(另一个不称职的老师)不允许您使用std::string
,但允许您使用基于std::stringstring
的std::string
的stringstream
,既然您从未从stream
中读取数据,那么读取工作是如何进行的呢?感谢您的支持和解释,我现在在最后,它崩溃了,但这是在不同的部分,我要修复。关于这根绳子,我也觉得很可笑,但不幸的是我无能为力。我得到容器的东西是因为它确保学生理解指针、堆栈和堆等东西背后的逻辑,但是std::string的东西只是“那不是一个容器吗?哦,是的,你是对的,你不能使用它”。因此,它背后没有任何逻辑,除了愤怒管理之外,根本不教任何东西。最初的答案更相关。正如我之前的评论所指出的,本课程的这一部分希望让学生/我学习内存管理,因此不允许使用智能指针。由于某些原因,我得到内存泄漏,但我将能够解决这些问题。再次感谢您提供的解决方案。我将代码恢复为使用原始char*
指针,但我保留了其他代码作为额外建议。++。我认为在C++课程中强调手动内存管理与语言的观点是相反的。对我来说,这是以后应该教的东西,也许只有当学生表示有兴趣使用这些设施时,因为出于某种原因,stdlib的RAII课程不能满足他们的需要。对于大多数人来说,STDLIB做了所需要的,并且应该教给他们更多有用的东西,IMO @ BealStReSyd:是的,很多人同意STL应该首先被教,因为它是C++标准的核心,然后更低级别的技术应该被教导为更高级的主题,如算法设计、优化等。
PortsContainer game::ParsePort(std::istream& stream)
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
PortsContainer ports;
bool passFirstRow = false;
// since you are using std::error_code, that means you are
// using C++11 or later, so use std::unique_ptr to ensure
// safe memory management...
std::unique_ptr<char[]> portLine(new char[1000000]);
int i = 0;
do
{
if (!stream.getline(portLine.get(), 1000000))
throw std::system_error(Error::STREAM_ERROR);
if ((stream.gcount() == 0) || (portLine[0] == '#'))
continue;
if (!passFirstRow)
{
std::istringstream iss(portLine.get());
// use std::unique_ptr here, too...
std::unique_ptr<char[]> name(new char[100]);
while (iss.getline(name.get(), 100, ';'))
{
if (iss.gcount() == 0) continue;
// use std::unique_ptr here, too...
std::unique_ptr<Port> port(new Port);
port->name = name.release(); // <-- assumes ownership is transferred!
// better to make Port::name use std::unique_ptr<char[]> and then std::move() ownership of name to it...
ports.addItem(port.get());
port.release();
name.reset(new char[100]); // <-- have to reallocate a new buffer each time!
}
passFirstRow = true;
} else {
++i;
}
}
while (!stream.eof());
return ports;
}
PortsContainer game::ParsePort(std::istream& stream)
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
PortsContainer ports;
bool passFirstRow = false;
std::string portLine;
int i = 0;
while (std::getline(stream, portLine))
{
if (portLine.empty() || (portLine[0] == '#'))
continue;
if (!passFirstRow)
{
std::istringstream iss(portLine);
std::string name;
while (std::getline(iss, name, ';'))
{
if (name.empty()) continue;
std::unique_ptr<Port> port(new Port);
port->name = name; // <-- make Port::name be std::string as well!
ports.addItem(port.get());
port.release();
}
passFirstRow = true;
} else {
++i;
}
}
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
return ports;
}