指向结构的指针数组
Array of pointers to structs
编辑:我对 C++ 和整个编程还很陌生。
我应该制作一个程序,其中我使用结构和结构数组。
Security council < > Member of Security council
我的任务是使用 "UML aggregation" 的概念创建一个使用结构和结构数组的程序。 (我希望你明白我想说的是什么)
由于安全理事会的成员是安全理事会的一部分,而不是相反,因此安全理事会的结构必须有一个成员数组。(请耐心等待)
//example
struct Member_sc{
char * name;
int age;
};
struct Security_council{
Member_sc members[10];
};
现在,我已经创建了这个程序并且一切正常(据我的老师说),但现在她告诉我创建一个精确的副本,但我必须使用数组而不是 "members" 数组指向 Member_sc 结构的指针。由于我还没有完全弄清楚指针是如何工作的,所以我遇到了一些问题。
如果需要,我可以 post 原始程序的代码,但它包含 4 个文件(主文件、头文件和一些函数文件),尝试起来会很痛苦 post在这里。
这是原型(目前全部在一个文件中)
#include <iostream>
using namespace std;
struct member_sc{
string name;
};
struct security_council{
member_sc *point;
security_council **search; // ignore this for now
int n;
security_council():n(0){}
};
void in_mem( member_sc &x){
getline(cin,x.name);
}
void out_mem(member_sc &x){
cout<<x.name<<endl;
}
void in_SC(security_council &q, member_sc &x){
int num; //number of members
cin>>num;
for(int i=0; i<num; ++i){
in_mem(x);
q.point[q.n]=x;
q.n++;
}
}
void out_SC(security_council &q,member_sc &x){
for(int i=0; i<q.n; ++i){
out_mem(q.point[i]);
}
}
int main(){
member_sc y;
security_council x;
in_mem(y); // works
out_mem(y); // works
in_SC(x,y); // crashes after i input the number of members i want
out_SC(x,y); //
system("pause");
return 0;
}
在您输入您希望在您的安全委员会中加入的成员数量后,程序崩溃。
我的思路对吗?还是应该使用动态内存分配?
除此之外(我的老师给了我一个额外的任务)使用指针创建一个搜索功能。我认为指向指针的指针可能对此有好处,但我不确定。
如有任何帮助或建议,我们将不胜感激。
(一旦我弄清楚指向结构的指针是如何工作的,我想我会搞清楚搜索的事情)
由于要求您使用指针数组,请执行此操作:替换
Member_sc members[10];
和
Member_sc* members[10];
然后使用动态内存分配填充该数组。作为一个好的形式,在程序结束时记得释放你使用的动态内存。
你问题的第一部分是这样的:
cin >> num;
这只读取已键入的数字并在换行符处停止。然后,在 in_mem
中对 getline
的调用立即读取换行符。你需要做的:
cin >> num;
cin.ignore();
这将耗尽所有剩余输入的输入流,或者可以这么说。
然而,您的核心问题是您没有为“point
”分配任何指向的内存。
指针只是一个变量,它保存的值恰好是内存中某个事物的地址(从 0 开始的偏移量)。如果你要去机场并在post-it note上写"Gate 23",post it note是一个指针,"Gate 23"是值。
在您的代码中,该变量未初始化,如果您幸运的话,它要么是 0,要么是内存中的某个随机地址,如果您不那么幸运。
打个机场的比方:你到了机场,发现你的post-it note上面写着"pizza"。没有帮助。
你的老师实际上指定了一个"array of pointers"。分解一下:指向什么的指针? member_sc
,即member_sc*
。现在把它变成一个数组
member_sc* pointers[10];
注意:这不好,现代 C++ - 在现代 C++ 中,您可能会使用称为智能指针 (std::unique_ptr) 的东西。
std::unique_ptr<member_sc[]> pointers(new member_sc[10]);
现在你有 10 个指针而不是一个,所有这些都需要一些分配来指向。最简单的方法是使用 new
关键字和复制构造函数:
for (int i = 0; i < num; i++) {
in_mem(x);
pointers[q.n] = new member_sc(x); // make a clone of x
q.n++;
}
或现代 C++
for (int i = 0; i < num; i++) {
in_mem(x); // x is temporary for reading in
pointers[q.n] = std::make_unique<member_sc>(x);
q.n++;
}
但是这种方法有一个限制:您最多只能有 10 个安全委员会成员。你如何解决这个问题?好吧,现代 C++ 的答案是使用 std::vector
std::vector<member_sc> members;
// ditch n - vector tracks it for you.
// ...
for (int i = 0; i < num; ++i) {
in_mem(x);
q.members.push_back(x);
// q.n is replaced with q.members.size()
// which is tracked automatically for you
}
但我猜你的老师希望你在用现代奢侈品忘记它们之前真正理解指针。
我们需要重新使用上面刚刚使用的指针内容,并将 "pointers" 更改为指针数组。
这意味着我们需要一个指向一组 pointer-to-member_sc.
的指针
member_sc** pointers;
我们需要为此分配一些内存以指向:
cin >> num;
cin.ignore();
if (num == 0) {
// do something
return;
}
pointers = new member_sc[num];
幸运的是,使用指向数组的指针与使用数组一样简单,唯一的主要区别是您丢失了数组的大小信息——您所拥有的只是地址,而不是维度。
for (int i = 0; i < num; i++) {
in_mem(x);
q.pointers[i] = new member_sc(x);
q.n++;
}
我故意不为您提供完整的工作示例,因为这显然是针对 class。
您从未初始化点成员引用的内存,然后在语句 q.point[q.n]=x;
中尝试使用它。
基本上,在读入成员数量后,在读入单个成员的for循环之前,需要分配一个适当数量的member_sc
个对象的数组,并将其存储在q.point
。使用完毕不要忘记释放内存。
完成后,您还可以从 in_SC
和 out_SC
中删除 member_sc &x
参数,因为这样就没有必要了。
最后,您输入的一些验证似乎已经到位。考虑一下如果用户输入一个负数会发生什么,并且您尝试直接使用它来确定要分配的内存大小。
下面是一个简单示例,展示了如何使用动态分配的结构数组:
#include <iostream>
#include <string>
struct member_sc {
std::string name;
};
void test_array(int count)
{
if (count <= 0) {
return; // Error
}
// Allocate an array of appropriate size
member_sc* members = new member_sc[count];
if (members == nullptr) {
return; // Error
}
// ... fill in the individual array elements
for(int i(0); i < count; ++i) {
// ... read from input stream
// I'll just generate some names to keep it simple
members[i].name = "User A";
members[i].name[5] += i; // Change the last character, so we have different names
}
// Now let's try printing out the members...
for(int i(0); i < count; ++i) {
std::cout << i << ": " << members[i].name << "\n";
}
delete[] members;
}
int main(int argc, char** argv)
{
for(int count(1); count <= 10; ++count) {
std::cout << "Test count=" << count << "\n";
test_array(count);
std::cout << "\n";
}
return 0;
}
当然,这种代码风格还有很多其他问题,但我认为这不是这个问题的重点。例如:
- 与其使用裸指针,不如使用某种智能指针更合适。
- 不要使用简单的数组,而是使用某种集合,例如向量。
编辑:我对 C++ 和整个编程还很陌生。
我应该制作一个程序,其中我使用结构和结构数组。
Security council < > Member of Security council
我的任务是使用 "UML aggregation" 的概念创建一个使用结构和结构数组的程序。 (我希望你明白我想说的是什么)
由于安全理事会的成员是安全理事会的一部分,而不是相反,因此安全理事会的结构必须有一个成员数组。(请耐心等待)
//example
struct Member_sc{
char * name;
int age;
};
struct Security_council{
Member_sc members[10];
};
现在,我已经创建了这个程序并且一切正常(据我的老师说),但现在她告诉我创建一个精确的副本,但我必须使用数组而不是 "members" 数组指向 Member_sc 结构的指针。由于我还没有完全弄清楚指针是如何工作的,所以我遇到了一些问题。
如果需要,我可以 post 原始程序的代码,但它包含 4 个文件(主文件、头文件和一些函数文件),尝试起来会很痛苦 post在这里。
这是原型(目前全部在一个文件中)
#include <iostream>
using namespace std;
struct member_sc{
string name;
};
struct security_council{
member_sc *point;
security_council **search; // ignore this for now
int n;
security_council():n(0){}
};
void in_mem( member_sc &x){
getline(cin,x.name);
}
void out_mem(member_sc &x){
cout<<x.name<<endl;
}
void in_SC(security_council &q, member_sc &x){
int num; //number of members
cin>>num;
for(int i=0; i<num; ++i){
in_mem(x);
q.point[q.n]=x;
q.n++;
}
}
void out_SC(security_council &q,member_sc &x){
for(int i=0; i<q.n; ++i){
out_mem(q.point[i]);
}
}
int main(){
member_sc y;
security_council x;
in_mem(y); // works
out_mem(y); // works
in_SC(x,y); // crashes after i input the number of members i want
out_SC(x,y); //
system("pause");
return 0;
}
在您输入您希望在您的安全委员会中加入的成员数量后,程序崩溃。 我的思路对吗?还是应该使用动态内存分配?
除此之外(我的老师给了我一个额外的任务)使用指针创建一个搜索功能。我认为指向指针的指针可能对此有好处,但我不确定。
如有任何帮助或建议,我们将不胜感激。 (一旦我弄清楚指向结构的指针是如何工作的,我想我会搞清楚搜索的事情)
由于要求您使用指针数组,请执行此操作:替换
Member_sc members[10];
和
Member_sc* members[10];
然后使用动态内存分配填充该数组。作为一个好的形式,在程序结束时记得释放你使用的动态内存。
你问题的第一部分是这样的:
cin >> num;
这只读取已键入的数字并在换行符处停止。然后,在 in_mem
中对 getline
的调用立即读取换行符。你需要做的:
cin >> num;
cin.ignore();
这将耗尽所有剩余输入的输入流,或者可以这么说。
然而,您的核心问题是您没有为“point
”分配任何指向的内存。
指针只是一个变量,它保存的值恰好是内存中某个事物的地址(从 0 开始的偏移量)。如果你要去机场并在post-it note上写"Gate 23",post it note是一个指针,"Gate 23"是值。
在您的代码中,该变量未初始化,如果您幸运的话,它要么是 0,要么是内存中的某个随机地址,如果您不那么幸运。
打个机场的比方:你到了机场,发现你的post-it note上面写着"pizza"。没有帮助。
你的老师实际上指定了一个"array of pointers"。分解一下:指向什么的指针? member_sc
,即member_sc*
。现在把它变成一个数组
member_sc* pointers[10];
注意:这不好,现代 C++ - 在现代 C++ 中,您可能会使用称为智能指针 (std::unique_ptr) 的东西。
std::unique_ptr<member_sc[]> pointers(new member_sc[10]);
现在你有 10 个指针而不是一个,所有这些都需要一些分配来指向。最简单的方法是使用 new
关键字和复制构造函数:
for (int i = 0; i < num; i++) {
in_mem(x);
pointers[q.n] = new member_sc(x); // make a clone of x
q.n++;
}
或现代 C++
for (int i = 0; i < num; i++) {
in_mem(x); // x is temporary for reading in
pointers[q.n] = std::make_unique<member_sc>(x);
q.n++;
}
但是这种方法有一个限制:您最多只能有 10 个安全委员会成员。你如何解决这个问题?好吧,现代 C++ 的答案是使用 std::vector
std::vector<member_sc> members;
// ditch n - vector tracks it for you.
// ...
for (int i = 0; i < num; ++i) {
in_mem(x);
q.members.push_back(x);
// q.n is replaced with q.members.size()
// which is tracked automatically for you
}
但我猜你的老师希望你在用现代奢侈品忘记它们之前真正理解指针。
我们需要重新使用上面刚刚使用的指针内容,并将 "pointers" 更改为指针数组。
这意味着我们需要一个指向一组 pointer-to-member_sc.
的指针member_sc** pointers;
我们需要为此分配一些内存以指向:
cin >> num;
cin.ignore();
if (num == 0) {
// do something
return;
}
pointers = new member_sc[num];
幸运的是,使用指向数组的指针与使用数组一样简单,唯一的主要区别是您丢失了数组的大小信息——您所拥有的只是地址,而不是维度。
for (int i = 0; i < num; i++) {
in_mem(x);
q.pointers[i] = new member_sc(x);
q.n++;
}
我故意不为您提供完整的工作示例,因为这显然是针对 class。
您从未初始化点成员引用的内存,然后在语句 q.point[q.n]=x;
中尝试使用它。
基本上,在读入成员数量后,在读入单个成员的for循环之前,需要分配一个适当数量的member_sc
个对象的数组,并将其存储在q.point
。使用完毕不要忘记释放内存。
完成后,您还可以从 in_SC
和 out_SC
中删除 member_sc &x
参数,因为这样就没有必要了。
最后,您输入的一些验证似乎已经到位。考虑一下如果用户输入一个负数会发生什么,并且您尝试直接使用它来确定要分配的内存大小。
下面是一个简单示例,展示了如何使用动态分配的结构数组:
#include <iostream>
#include <string>
struct member_sc {
std::string name;
};
void test_array(int count)
{
if (count <= 0) {
return; // Error
}
// Allocate an array of appropriate size
member_sc* members = new member_sc[count];
if (members == nullptr) {
return; // Error
}
// ... fill in the individual array elements
for(int i(0); i < count; ++i) {
// ... read from input stream
// I'll just generate some names to keep it simple
members[i].name = "User A";
members[i].name[5] += i; // Change the last character, so we have different names
}
// Now let's try printing out the members...
for(int i(0); i < count; ++i) {
std::cout << i << ": " << members[i].name << "\n";
}
delete[] members;
}
int main(int argc, char** argv)
{
for(int count(1); count <= 10; ++count) {
std::cout << "Test count=" << count << "\n";
test_array(count);
std::cout << "\n";
}
return 0;
}
当然,这种代码风格还有很多其他问题,但我认为这不是这个问题的重点。例如:
- 与其使用裸指针,不如使用某种智能指针更合适。
- 不要使用简单的数组,而是使用某种集合,例如向量。