我有一个用户输入值,然后根据该值和以下31个值定义端口。然后应将这些端口存储在一个数组中,但由于某些原因,当我从数组调用时,每个值都是最后一个值。 (例如,如果用户输入5000,则数组中的每个值最终都为5031)。将实际数字存储在数组中是有问题的,因为如果我在创建它们时打印它们都是正确的。 请原谅那些不雅的代码,我是新手。谢谢!
//enter own ports
using namespace std;
cout << "enter a port number between 1000-9999: "; // gets port from user input
cin >> startingport;
for (int i=0; i<32; i++) // defines 32 ports starting with user input
{
sprintf(portchar, "%d", startingport+i);
cout << "defining port: " << portchar << endl; // gives correct value
portarray[i] = portchar;
}
cout << portarray[0] << endl; // gives incorrect value
很抱歉应该把它放在前面 - 我在另一个文件中有定义。我需要端口成为一个字符,因此portchar
static int startingport;
static char portchar[6];
static char *portarray[32];
答案 0 :(得分:0)
它们将指向相同的底层值,因为您反复使用'portchar'进行打印,它恰好是一个静态字符。
portarray [0] - &gt; portarray [1] - &gt; ... portarray [2] - &gt; 都指向'portchar'
所有这些都指向共享的char数组。你需要解决一些问题:
由于portarray被声明为指针数组,因此需要指向各个缓冲区。
将portarray更改为声明为std :: string的数组。你会得到一份副本。因此,您将拥有不同的价值观。
将portarray保持为指针数组,但是,为循环的每次迭代分配一个新的portchar并存储这些指针。
_3并不好,因为你必须自己管理记忆。
_2更好,同时使用std :: vector&lt;&gt;对于portarray。
_1正在生成字符串的副本,您需要决定是否要支付该费用。
答案 1 :(得分:0)
首先,我想回应Mike Seymour的评论,即你应该使用std::string
和容器,而不是char*
和*char[]
。更高级别的抽象有助于缓解许多与指针管理和算术相关的常见问题。
那就是说,这是一个很好的教育时刻。
让我们开始告诉自己指针(*
)只不过是一个地址。就像我居住在555 First St一样,内存中的所有对象都有一个地址。如果我离开我的地址并且其他人搬进来,当有人问谁住在第一街555号时,那个时刻的答案就是那些搬进去的人,不是我。
如果指针只是地址,那么什么是指针数组?嗯,它只是一个地址列表!想象一个带有空插槽的列表,可以容纳32个地址。这就是portarray
。
那么你的循环是做什么的?那么有三个基本操作:
sprintf(portchar, "%d", startingport+i);
这相当于有人进入地址portchar
。地址仍然相同,现在只有新的东西。
cout << "defining port: " << portchar << endl;
这与询问住在该地址的人一样。当然,你知道这是什么,它只是startingport+1
,因为startingport+1
刚刚进入!
最后:
portarray[i] = portchar;
密切注意这一点。这表示将地址portchar
复制到您的地址列表中。想象一下,你有一张纸,你写下了"0: 555 First St"
。这是不正在复制该地址生活的人,而是地址本身。在这个循环的下一次迭代中,当需要再次写下地址时,我们会像以前一样写"1: 555 First St"
。
所以在你的循环结束时,你将拥有这个漂亮的地址列表,并且所有地址都完全相同,因为你当然从未真正更改了地址你的循环。
std::string
)如果您愿意手动管理portarray
指向的内存,则可以使用堆分配的内存来修复问题。这是必要的,因为您需要32
个唯一的地址,您可以将其放入portarray
。您的静态分配portchar
会为您提供一个不充分的地址。
// Assuming you've removed your portchar declaration
for (int i=0; i<32; i++) // defines 32 ports starting with user input
{
portarray[i] = new char[6]; // This dynamically allocates memory
sprintf(portarray[i], "%d", startingport+i);
cout << "defining port: " << portarray[i] << endl; // gives correct value
}
cout << portarray[0] << endl; // gives correct value
要在以后释放内存,你必须这样做:
for (int i=0; i<32; i++)
{
delete[] portarray[i];
}
它看起来很乱,因为它是。正如其他人所建议的那样,您可以使用std::string
和容器来避开这个雷区。如果您的代码适合这些抽象,我强烈建议您使用它们。