简体   繁体   English

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

[英]my for loop is making every value the last value (C++)

I have a user input a value, then define ports based on that value and the following 31 values. 我有一个用户输入一个值,然后根据该值和以下31个值定义端口。 These ports should then be stored in an array, but for some reason when I call from the array every value is the last value. 这些端口然后应存储在数组中,但是出于某种原因,当我从数组中调用时,每个值都是最后一个值。 (For example, if a user enters 5000, every value in the array ends up being 5031). (例如,如果用户输入5000,则数组中的每个值最终都是5031)。 It's something wrong with storing the actual numbers in the array since if I print the values as they are being created they are all correct. 将实际数字存储在数组中是有问题的,因为如果我在创建值时将其打印出来,它们都是正确的。 Excuse the inelegant code, I'm a newbie. 不好意思的代码,我是新手。 Thanks! 谢谢!

//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

Sorry should have put this before-- I have definitions in another file. 抱歉,应该在此之前-我在另一个文件中有定义。 I need port to be a character, hence portchar 我需要port成为角色,因此portchar

static int startingport;
static char portchar[6];
static char *portarray[32];

They will be pointing to the same underlying value, as you repeatedly use 'portchar' to print to and it happens to be a static char. 当您反复使用“ portchar”进行打印时,它们将指向相同的基础值,而它恰好是静态char。

portarray[0] -> portarray[1] -> ... portarray[2] -> all pointing to 'portchar' portarray [0]-> portarray [1]-> ... portarray [2]->所有都指向“ portchar”

All of them are pointing to the shared char array. 它们都指向共享char数组。 You need to fix a few things: 您需要修复一些问题:

  1. Since portarray is declared as an array of pointers, you would need individual buffers to point to. 由于portarray被声明为指针数组,因此需要单独的缓冲区指向。

  2. Change portarray to be declared as an array of std::string. 将portarray更改为声明为std :: string的数组。 You would get a copy. 您会得到一份副本。 Thus, you will have distinct values. 因此,您将拥有不同的价值。

  3. Keep portarray as an array of pointers, but, allocate a new portchar for each iteration of the loop and store these pointers. 将portarray保留为指针数组,但是,为循环的每次迭代分配一个新的portchar并存储这些指针。

_3 is not great, as you would have to manage the memory yourself. _3不好,因为您必须自己管理内存。

_2 is better, along with using a std::vector<> for portarray. _2更好,并且将std :: vector <>用于portarray。

_1 is generating copies of strings, which you need to decide if you want to pay that cost. _1正在生成字符串的副本,您需要确定是否要支付该费用。

First I want to echo Mike Seymour's comment that you should be using std::string s and a container, not char* and *char[] . 首先,我想回应Mike Seymour的评论,即您应该使用std::string s和一个容器,而不是char**char[] The higher level abstractions help mitigate a lot of the common issues related to pointer management and arithmetic. 更高级别的抽象有助于减轻许多与指针管理和算术相关的常见问题。

That said, this is a good teachable moment. 就是说,这是一个很好的教学时间。

What went wrong 什么地方出了错

Let's begin by telling ourselves that a pointer ( * ) is nothing more than an address. 让我们开始告诉自己,指针( * )只不过是一个地址。 Just like how I live at 555 First St, all objects in memory have an address. 就像我住在第一街555号一样,内存中的所有对象都有一个地址。 If I move out of my address and someone else moves in, when someone asks who lives at 555 First St, the answer at that moment will be whoever moved in, not me. 如果我搬出我的住址而其他人搬进去,当有人问谁住在第一街555号时,那一刻的答案将是搬进来的人, 而不是我。

If pointers are just addresses, then what is an array of pointers? 如果指针只是地址,那么指针数组是什么? Well, it's just a list of addresses! 好吧,这只是地址列表! Imagine a list with empty slots that can hold 32 addresses. 想象一个带有空槽的列表,该列表可以容纳32个地址。 This is what portarray is. 这就是portarray

So what does your loop do? 那你的循环做什么? Well there are three basic operations: 好吧,这里有三个基本操作:

sprintf(portchar, "%d", startingport+i);

This is equivalent to someone moving into the address portchar . 这相当于有人进入了地址portchar The address is still the same, there's just something new in there now. 地址仍然相同,现在有一些新内容。

cout << "defining port: " << portchar << endl;

This is the same as asking who lives at that address. 这与询问谁住在该地址相同。 Of course, you know what this is, it's just startingport+1 since startingport+1 just moved in! 当然,您知道这是什么,这只是startingport+1因为startingport+1刚刚移入!

Finally: 最后:

portarray[i] = portchar;

Pay close attention to this. 请密切注意这一点。 This says to copy down the address portchar into your list of addresses. 这表示将地址portchar复制到您的地址列表中。 Imagine you had a piece of paper and you wrote down "0: 555 First St" . 假设您有一张纸,然后写下了"0: 555 First St" This is not copying down who lives at that address, but the address itself. 不是复制那个地址的人,而是复制地址本身。 The next iteration of this loop, when it comes time to write down the address again, we'd write "1: 555 First St" , same as before. 此循环的下一个迭代,当需要再次写下该地址时,我们将写入"1: 555 First St" ,与之前相同。

So at the end of your loop, you'll have this nice list of addresses, and all of the addresses are exactly the same, because of course you never actually changed the address in your loop. 因此,在循环结束时,您将获得一个不错的地址列表,并且所有地址都完全相同,因为当然您实际上从未真正更改过循环中的地址

What can you do about it (without using std::string ) 您可以做什么(不使用std::string

If you're willing to manually manage the memory pointed to by portarray , you can fix your issues using heap allocated memory. 如果您愿意手动管理portarray指向的内存,则可以使用堆分配的内存来解决问题。 This is necessary because you need 32 unique addresses that you can put into portarray . 这是必需的,因为您需要可以将32唯一地址放入portarray Your statically allocated portchar gives you one address which is insufficiently. 您静态分配的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

To free up the memory later, you have to do: 要稍后释放内存,您必须执行以下操作:

for (int i=0; i<32; i++)
{
    delete[] portarray[i];
}

It looks messy, and that's because it is. 看起来很乱,那是因为。 As others have suggested, you can avoid this minefield by using std::string and containers. 正如其他人所建议的那样,您可以通过使用std::string和container来避开这个雷区。 If your code is amenable to those abstractions, I highly recommend using them. 如果您的代码适合这些抽象,我强烈建议您使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM