作为一名c ++初学者,我编写了以下代码:
int main(void){
struct car{
char * make[200];
int manfYear;
};
int num=0;
cout << "How many cars do you wish to catalogue? ";
cin >> num;
car * Cars = new car [num];
for (int i=1;i<=num;i++){
cout << "Car #" << i << ":" << endl << "Please enter the make: ";
cin.getline(*Cars->make,200);
cout << "Please enter the year made: ";
cin >> Cars->manfYear;
}
我的问题是,当我需要进入汽车模型时运行程序时,我无法理解我遇到段错误的问题。有人可以解释一下我做错了吗?
据我所知,我正在传递一个指向数组“make”的指针,它应该可以使它工作。我的理解是否已经结束?
提前致谢 丹
答案 0 :(得分:4)
我马上就看到了四个问题:
第1期
在struct
,您有:
char * make[200];
在英语中,这就是说,“创建一个包含200个字符指针的数组”,当我想要说“创建一个包含200个字符的数组”时。所以你应该改为:
char make[200]
。
第2期
您从1
开始循环。这将跳过数组中的第一辆汽车 - 记住数组是零索引的。所以你应该改为:
for (int i = 0 ; i < num ; i++)
出于显示目的,您可以说:
cout << "Car #" << (i+1) << ":" << endl << "Please enter the make: ";
第3期
你说的地方:
cin.getline(*Cars->make,200);
和
cin >> Cars->manfYear;
在这些行中您指定用户正在填充哪辆车?无处。如果您使用i
进行循环,则需要实际提及i
。这些应该有效:
cin.getline(Cars[i].make,200);
和
cin >> Cars[i].manfYear;
请注意,我们使用的是.
,而不是->
。这是因为Cars
数组中的项是实际实例,而不是指针。 Cars
数组本身就是一个指针,但不是它的内容。
第4期
首先指出这一点的@Ben C的所有功劳:将>>
运算符与getline()
上的cin
函数混合在一起会导致奇怪的行为,而剩下的{{1}来自CR
进入>>
来电。您可以使用全部getline()
(缺点:您在阅读make时没有强制执行>>
限制)或全部200
(缺点:您必须使用字符串缓冲区然后将它们转换为汽车数量和年份),或者在每次调用cin.getline()
后放置cin.ignore()
,如下所示:
>>
和
cin >> num;
cin.ignore();
同样,所有信用都归@Ben C所有,首先注意到这一点。
最后但并非最不重要
按照惯例,类/结构具有大写名称,变量具有小写/大写名称。考虑将cin >> Cars[i].manfYear;
cin.ignore();
从struct
重命名为car
,将数组从Car
重命名为Cars
。换句话说,你现在拥有的资本化逆转。
最后,我同意所有其他海报:您应该考虑使用cars
代替string
数组。
答案 1 :(得分:2)
首先,使用string
代替差的旧C char[]
。
下一步:您不希望char * make[200];
。你想要char make[200];
。 char * make[200]
是一个包含200个char
指针的数组,可以用作200个以空字符结尾的字符串 - 但是,每个字符串必须new[]
。只需使用char make[200];
和cin.getline(Cars->make, 200);
。
答案 2 :(得分:2)
char * make[200]
声明一个包含200个指针的数组;我猜这不是你想要的。
如果您只是想存储一个字符串,我建议您改为查看C ++ string
类型。
#include <iostream>
#include <string>
int main()
{
using namespace std;
struct car
{
string make;
int manfYear;
};
int num=0;
cout << "How many cars do you wish to catalogue? ";
cin >> num;
car * Cars = new car [num];
for (int i=1;i<=num;i++)
{
cout << "Car #" << i << ":" << endl << "Please enter the make: ";
std::cin.ignore();
getline(cin, Cars[i-1].make);
cout << "Please enter the year made: ";
cin >> Cars[i-1].manfYear;
}
}
您的代码还有其他一些小问题。
1)你一直在使用Cars->manfYear
- 这只会指向数组的第一个元素。我假设你不想要那个;根据{{1}}使用下标语法将访问数组中的单个car对象。 (请记住,数组索引从零开始! - 实际上,你的 for 循环变量从零开始实际上会更加惯用)
2)警惕Cars[i-1].manfYear
和std::getline
符号一起工作的方式。 >>
(流提取运算符)经常会留下任何换行符,这意味着您可能会在调用getline时看到“奇怪”的行为。如果你将两者混合在一起,那么使用像>>
之类的东西可以帮助你丢弃换行符。
答案 3 :(得分:1)
首先,char *make[200]
不是一个最多200个字符的字符串,而是指向char
的200个字符串。
第二件事:您正在cin.getline
中使用*
取消引用指针:会发生的情况是您获得了200 char*
指针的第一个单元格中包含的值。但是你没有初始化单指针,只是更高级别的指针,所以你得到了一个段错误。
只需将char* make[200]
更改为char make[200]
,将*Cars->make
更改为Cars[i].make
。
答案 4 :(得分:1)
首先,C ++中的数组是从0..n-1索引的,所以你的循环需要从
运行for (int i = 0; i < num; i++) { ... }
其次,您已将make
声明为指针的200元素数组char
;这很可能不你想要什么。如果make
应该存储字符串,请将其声明为char
的简单数组:
struct car{
char make[200];
int manfYear;
};
最后,将您的getline
电话重写为
cin.getline(Cars[i].make, sizeof Cars[i].make); // fixed per comment below
即使将Cars
声明为指针,也可以使用上的下标运算符,就像它是一个数组一样;通过这样做,您隐式取消引用Cars
,因为a[i]
被解释为*(a + i)
。这也意味着您将使用.
组件选择运算符而不是->
运算符,因为Cars[i]
的类型为car
,而不是car *
。