我的for循环使每个值都成为最后一个值(C ++)

时间:2015-04-29 18:17:40

标签: c++ arrays for-loop

我有一个用户输入值,然后根据该值和以下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];

2 个答案:

答案 0 :(得分:0)

它们将指向相同的底层值,因为您反复使用'portchar'进行打印,它恰好是一个静态字符。

portarray [0] - &gt; portarray [1] - &gt; ... portarray [2] - &gt;    都指向'portchar'

所有这些都指向共享的char数组。你需要解决一些问题:

  1. 由于portarray被声明为指针数组,因此需要指向各个缓冲区。

  2. 将portarray更改为声明为std :: string的数组。你会得到一份副本。因此,您将拥有不同的价值观。

  3. 将portarray保持为指针数组,但是,为循环的每次迭代分配一个新的portchar并存储这些指针。

  4. _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和容器来避开这个雷区。如果您的代码适合这些抽象,我强烈建议您使用它们。