我编写了一个代码来读取文件,将其存储在结构中并显示它。但不知何故,它给了我一个分段错误,我不知道为什么。有人可以帮助我吗?
输出:
file: /home/neel/map2.txt
file opened
Start Intersection
a->road: 4
a->roadId[0]: 1
a->lane[0][0]: 2
a->lane[0][1]: 2
a->roadId[1]: 2
a->lane[1][0]: 2
a->lane[1][1]: 2
a->roadId[2]: 3
Segmentation fault
代码:
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace std;
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
cout<<"file opened"<<endl;
while (!file.eof())
{
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
cout<<"Intersection inserted"<<endl;
delete a;
}
}
文字档案:
4
1
2
2
2
2
2
3
2
2
4
2
2
答案 0 :(得分:6)
您的lane
是一个包含2个元素的数组,但是当您的内循环中的i
到达2
时,您正在尝试打印a->lane[2][0]
,而不是{{1}}存在。
答案 1 :(得分:2)
file>>a->lane[i][0]; //wrong
file>>a->lane[i][1]; //wrong
指数应相反:
file>>(a->lane[0][i]); //correct
file>>(a->lane[1][i]); //correct
为了清楚起见,我添加了括号。
此外,您的程序中存在内存泄漏。应该有delete
个new
语句,以确保没有内存泄漏。所以写下这些:
delete [] a->roadId;
delete [] a->lane[0];
delete [] a->lane[1];
delete a; //you've written only this!
注意delete a
应该是解除内存释放时的最后一条语句!
答案 2 :(得分:2)
我不是故意讨厌,但是这段代码有足够的问题,几乎很难决定从哪些开始。
using namespace std;
这是第一个红旗。我所能说的只是using namespace std;
是一个糟糕的主意。使用其他名称空间是可以接受的,但使用std
时,应始终避免(IMO)。
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
这让我感到非常糟糕。 std::vector
是一件好事。用它。您可能需要考虑为结构类型定义operator>>
,而不仅仅是一个哑数据结构,因此您可以直接读取它。即使你不这样做,从你使用它的方式来看,你真正想要的更像是:
struct road {
long long Id;
short lane[2];
};
struct Intersection {
int road_count;
road *roads;
};
然后,您需要获得许多道路,而不是几个相同大小的并行阵列,而每个道路都有自己的数据。 std::vector
虽然更好。
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
不是定义ifstream对象然后单独打开它,而是通常计划将名称传递给ctor,以便在单个操作中定义和打开,如:
std::ifstream file(argv[1]);
但是,你通常也想添加一些错误检查,所以你只能尝试使用命令行参数作为文件名,如果已经传递了一个,如下所示:
if (argc < 2) {
std::cerr << "Usage: your_command <filename>\n";
return EXIT_FAILURE;
}
然后您将拥有定义ifstream
的代码。
while (!file.eof())
这是另一个主要问题。这种形式的循环基本上总是错误的(包括这种情况,从事物的外观)。
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
似乎没有理由动态分配它。或许,你是一个正在恢复(或者可能没有恢复)的Java或C#程序员吗? Java要求动态分配用户定义类的所有对象,但C ++不能。
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
我更喜欢将用于读取数据的代码与用于显示数据的代码分开。除了像家庭作业(或调试)这样的东西,你很少想要在阅读时显示大量原始数据。在任何情况下,阅读代码通常应该位于该类的operator>>
,以及该类的operator<<
中的显示代码。
cout<<"Intersection inserted"<<endl;
这似乎是一种彻头彻尾的谎言。您实际上没有将Intersection
插入任何内容。
delete a;
当您退出动态分配Intersection
时,您也可以消除此问题。如果您坚持手动处理所有动态分配,则需要在此之前删除组件以避免内存泄漏(更喜欢std::vector
的另一个原因)。
我知道这可能听起来很消极,这让我有点不知所措。一方面,我真的喜欢提出更好的做事方式。与此同时,这看起来很像家庭作业,我非常犹豫不决,只是发布更好的代码。我试图提供一些关于更好方法的提示,但是意识到它们可能没有你想要的那么具体 - 我为此道歉,但鉴于它可能是功课我不认为我可以成为一个更具体。