我写了一个程序来显示数组的内容,但它显示的是它的地址

Posted

技术标签:

【中文标题】我写了一个程序来显示数组的内容,但它显示的是它的地址【英文标题】:I wrote a program to display the content of an array, but it display with its address 【发布时间】:2019-12-11 04:06:35 【问题描述】:

我写了一个程序,它会打印一个奇数数组的内容,另一个打印偶数整数的内容,但是当我想重新打印数组时,它会在内存中显示它的地址, 我还想打印第一个数组和第二个数组,第二个数组围绕数组 1 和数组 2,这意味着数组 1 将位于中间,数组 2 位于左右两侧。 但我坚持重新打印阵列一, 这是我的代码,


#include <iostream>
#include <iomanip>
#include <string>

using namespace std;
int main ()

    int i,counter[25];
    int j,counter2[25];
    for(i=0;i<=20;i++)
        if(i%2==1)
            continue;
            counter[i]=i;
        cout<<counter[i]<<"  ";
    
    cout<<"\n";

    for(j=101;j<=115;j++)
        if(j%2==0)
            continue;
        counter2[j]=j;
        cout<<counter2[j]<<"  ";
    
    cout<<"\n\n";

          for(i=0;i<=20;i++)
            cout<<counter[i]<<"  ";
          
  return 0;


输出将是这样的:

0  2  4  6  8  10  12  14  16  18  20
101  103  105  107  109  111  113  115

0  1989701561  2  7208604  4  1990083356  6  1989764433  8  1989701373  10  -1841062257  12  4199040  14  4354336  16  7208680  18  1989725376  20

我很困惑它会打印地址??我应该为每个元素指定地址吗?

顺便说一句,第二个数组应该以 101 及以上开头。

【问题讨论】:

counter2 的大小为25,您在第二个循环中访问counter2[101] 和更高的索引。这会导致未定义的行为,您的程序可以做任何事情。数组的索引总是以0 开始,以size-1 结束。您看到的不是地址,而是由于未定义的行为而造成的无意义。 如果counter2 只有25 元素,for(j=101;j&lt;=115;j++) 如何工作? counter2[j]=j; 至少是数组末尾之外的 77 元素。 counter2 的大小为 25 是真的,但它里面的值应该由 101 到 115 组成,这就是为什么我用 101 值开始第二个数组,但它是正确的方法吗做吗? 其中的值可以101115,但它的index 不能。也许for (j = 0; j &lt;= 15; j++) counter2[j] = j + 101;?如果您要迭代尚未初始化的索引,您还应该初始化您的数组,例如counter[25] = 0; 我编辑了以0 开始counter2 的代码,并添加了另一个if-statement,它将忽略从0100 的值。这会正常工作吗? 【参考方案1】:

在您的回复中,前两行输出对于 counter 和 counter2 数组是正确的。

第三个输出是基于数组初始化时充满垃圾值的事实。

让我们暂时离开“counter2”数组并查看“counter”的代码。

我想就是这样。

int main ()

 int i,counter[25];
 int j,counter2[25];
 for(i=0;i<=20;i++)
    if(i%2==1)
        continue;
        counter[i]=i;
    cout<<counter[i]<<"  ";
 
 cout<<"\n";

      for(i=0;i<=20;i++)
        cout<<counter[i]<<"  ";
      
  return 0;

 

如果您仔细查看循环代码

 for(i=0;i<=20;i++)
    if(i%2==1)
        continue;
        counter[i]=i;
    cout<<counter[i]<<"  ";
 

你正在做的是检查这个条件是否为“真”

    if(i%2==1)
       continue;

那么你所做的“假”是

  counter[i]=i;
    cout<<counter[i]<<"  ";

这里的值被插入到你在 if 条件中比较的“i”的相应值中。

换句话说

如果你在比较

i=2
in
if(i%2==1)
this will go "false" and to next statement 
counter[i]=i;
i.e. counter[2]=2;

你基本上是像这样在数组中插入值:

_ 2 _ 4 _ 6 _ 8 _ 10 ...etc

它只修改数组中的特定值,而其他值保持不变。

第二个数组“counter2”也是如此。

【讨论】:

好吧,因为这个原因我做了counter[i]=i,这是一个错误。我现在很好理解并理解它 非常感谢您为我提供帮助的每一个解释,【参考方案2】:

标准输出上打印的值不是地址。它们是存储的值。

首先你需要知道的是每个变量在声明期间都会得到一个垃圾值,除非它没有被初始化。如果您初始化一个变量,那么该变量将携带该值,直到它被其他语句更改。

您可以看到偶数索引 0、2、4、...、20 的值与您在第一个 for 循环中设置的值相同。 但奇数索引处的值与您预期的不同。因为在第二个 for 循环中,您已经遍历了 from 101 to 115 并且没有在正确的索引处设置值。此外,在第二个循环中,您将值存储在数组 counter2 中,但最后,您正在打印数组 counter 中的值。

最后,当您打印数组counter 中的值时,程序会输出当时存储的值。如果它没有被初始化或分配其他值,它将是垃圾值。

【讨论】:

那么如何忽略每个变量得到的垃圾值而不打印出来呢? 我是否应该声明另一个变量并将其初始化为zero,这意味着它将忽略这些garbage 值? @coder 如何忽略垃圾值完全取决于您。您可以使用initializing while declarationassigning with the proper value that you should。对于这个问题,我认为您想在奇数索引1 3 5 ... 15 处设置奇数值1 3 5 ... 15,对吗?如果是,则在数组counter 而不是counter2 中评估该值。并且还在第二个for 循环中迭代from 1 to 15【参考方案3】:

您没有打印地址。您正在打印未初始化的整数值。问题在于您对数组的初始化。原因是线路 counter2[j] = j; 正在尝试索引数组的第 j 个元素,但 j 从 101 递增到 115。如果您只是想获得从 101 到 115 的偶数,请执行以下操作:

for (int j = 0; j <= 7; j++)

    counter2[j] = (100 + 2*(j + 1) - 1);

当你想编写一个 for 循环来将元素插入数组时,你通常希望递增的变量代表你要编辑的元素的索引。

【讨论】:

你能帮我解释一下这句话吗counter2[j] = (100 + 2*(j + 1) - 1) 因为我试图弄清楚它是怎么来的,但是我的大脑在数学上真的很糟糕 您希望 j 代表您尝试添加的元素的 index。该表达式(100 + 2*(j + 1) - 1) 采用该值(从 0 到 7 的整数)并给出从 101 到 115 的奇数。如果 j = 0,那么 counter2[j] 将是 101。如果 j = 1,它将是 103,等等。这些 您想要的值,对吧?【参考方案4】:

在 C/C++ 中,当您使用整数字面量声明具有自动存储持续时间的数组时,例如:

    int i,counter[25];
    int j,counter2[25];

countercounter2 的有效索引是 0 &lt;= index &lt; 25。在您的代码中,尽管您有 if 语句,但当您这样做时:

for(j=0;j<=115;j++)
    if(j%2==0)
        continue;
        if(j<101 && j>0)
            continue;
    counter2[j]=j;
    cout<<counter2[j]<<"  ";

您将101 通过115 作为索引传递给:

    counter2[j]=j;
    cout<<counter2[j]<<"  ";

这超出了数组边界并在您的代码中调用未定义行为

此外,对于由于您的检查而未通过分配值来初始化的所有索引:

    if(i%2==1)
        continue;

    if(j%2==0)
        continue;

导致countercounter2 中的那些元素没有被分配一个持有indeterminate 值的值。任何尝试访问具有自动存储持续时间且其值为不确定的变量的值都会导致未定义的行为。为避免跳过索引时出现问题,请在声明数组时将数组的所有元素初始化为零,例如

    int i,counter[25] = 0;
    int j,counter2[25] = 0;

总而言之,你可以这样做:

#include <iostream>
#include <iomanip>
#include <string>

int main (void) 

    int i,counter[25] = 0;
    int j,counter2[25] = 0;

    for (i = 0; i <= 20; i++)
        if (i % 2 == 1)
            continue;
        counter[i]=i;
        std::cout << counter[i] << "  ";
    
    std::cout << "\n";

    for (j = 0; j <= 15; j++)
        int v = j + 101;
        if (v % 2 == 0)
            continue;
        counter2[j] = v;
        std::cout << counter2[j] << "  ";
    
    std::cout<<"\n\n";

    for(i = 0; i <= 20; i++) 
        std::cout << counter[i] << "  ";
    
    std::cout << '\n';

注意: 包括整个 namespace std 不被认为是好的做法。老年人喜欢合理间隔的代码...)

使用/输出示例

$ ./bin/array_shift_idx
0  2  4  6  8  10  12  14  16  18  20
101  103  105  107  109  111  113  115

0  0  2  0  4  0  6  0  8  0  10  0  12  0  14  0  16  0  18  0  20

查看一下,如果您还有其他问题,请告诉我。

使用单独的索引变量

当您有一个固定数组并且您要向该数组中读取一些可能/可能不小于数组中元素总数的值时,您将希望保留一个单独的变量(或计数器) 保存填充的元素数。然后在对数组进行迭代时,可以从0 &lt;= i &lt; filled进行迭代。

在您的例子中,您使用 for 循环变量作为 values 以及使用循环变量作为 index。当您测试 value 然后 continue; 如果它不是您想要的,您跳过填充相关的 index。要解决此问题,您只需保留保存数组中最后填充索引的单独值。例如:

#define NELEM 25    /* if you need a constant, #define one (or more) */

int main (void) 

    int counter[NELEM]  = 0,  /* initialize array elements zero */
        counter2[NELEM] = 0,
        ndx1 = 0, ndx2 = 0;     /* separate indexes for counter/counter2 */

变量ndx1ndx2是最后填写的索引countercounter2。现在,当您循环时,您只会在为数组分配值时增加索引,例如

    for (int i = 0; ndx1 < NELEM; i++)     /* fill counter w/even values */
        if (i % 2 == 1)
            continue;
        counter[ndx1++] = i;                /* assign value/advance index */
    

(注意:这里所有元素都被填充了,但你明白了。你使用独立变量。一个代表你的生成和一个用于数组的索引

同样,对于 counter2 数组,您可以这样做:

    for (int i = 0; ndx2 < NELEM; i++)     /* fill counter2 w/odd values */
        int v = i + 101;                    /* add 101 to each value */
        if (v % 2 == 0)
            continue;
        counter2[ndx2++] = v;               /* assign value/advance index */
    

使用上面的一个简短示例,用从0 开始的偶数 值填充counter 的元素,并用从@ 开始的奇数 值填充counter2 987654351@ 并确保每个数组中的所有值都是连续的,可能类似于:

#include <iostream>
#include <iomanip>

#define NELEM 25    /* if you need a constant, #define one (or more) */

int main (void) 

    int counter[NELEM]  = 0,  /* initialize array elements zero */
        counter2[NELEM] = 0,
        ndx1 = 0, ndx2 = 0;     /* separate indexes for counter/counter2 */

    for (int i = 0; ndx1 < NELEM; i++)     /* fill counter w/even values */
        if (i % 2 == 1)
            continue;
        counter[ndx1++] = i;                /* assign value/advance index */
    

    for (int i = 0; ndx2 < NELEM; i++)     /* fill counter2 w/odd values */
        int v = i + 101;                    /* add 101 to each value */
        if (v % 2 == 0)
            continue;
        counter2[ndx2++] = v;               /* assign value/advance index */
    

    std::cout<<"counter:\n";                /* output counter values */
    for (int i = 0; i < ndx1; i++) 
        if (i && i % 10 == 0)               /* 10 values per-row */
            std::cout << '\n';
        std::cout << std::setw(4) << counter[i];
    

    std::cout<<"\n\ncounter2:\n";           /* output counter2 values */
    for (int i = 0; i < ndx2; i++) 
        if (i && i % 10 == 0)               /* 10 values per-row */
            std::cout << '\n';
        std::cout << std::setw(4) << counter2[i];
    
    std::cout << '\n';

使用/输出示例

$ ./bin/array_shift_idx2
counter:
   0   2   4   6   8  10  12  14  16  18
  20  22  24  26  28  30  32  34  36  38
  40  42  44  46  48

counter2:
 101 103 105 107 109 111 113 115 117 119
 121 123 125 127 129 131 133 135 137 139
 141 143 145 147 149

您可以调整循环限制以仅填充0 - 20101 - 115(如果您愿意),或者您可以简单地迭代少于NELEM 次来产生您想要的输出。完全取决于你。关键是,由于您保留了单独的索引来捕获每个数组中已填充的元素数量,因此您可以采用任何一种方式,并且永远不会遍历任一数组中最后一个填充的元素。

只填写counter2中的第一个8个奇数值

例如,如果您只想将101 - 115 添加到counter2 并且不填写其他元素,您只需进行更改:

    for (int i = 0; i <= 15; i++)          /* fill counter2 w/odd values */
        int v = i + 101;                    /* add 101 to each value */
        if (v % 2 == 0)
            continue;
        counter2[ndx2++] = v;               /* assign value/advance index */
    

现在counter2 的输出将是:

counter2:
 101 103 105 107 109 111 113 115

【讨论】:

现在我理解了您在代码中编辑的每一行,但最后一个输出 0 0 2 0 4 0 6 0 8 0 10 0 12 0 14 0 16 0 18 0 20 在元素之间打印 0,这是因为我们初始化了 counter 和 @具有0 值的 987654366@ 数组,或者? 是的,由于您的if (i % 2 == 1) continue;,您永远不会为元素1, 3, 5, 7,... 赋值。因此,counter[i]=i; 永远不会为这些索引分配值。因此,在您循环 for(i = 0; i &lt;= 20; i++) 输出 counter[i] 的最后,您输出的 indeterminate 值恰好在声明数组时位于该地址的内存中。 (声明数组时,数组内存不会自动归零)。您可以像我对int counter[25] = 0; 所做的那样初始化所有值以避免这个问题。 如果您希望 0, 2, 4, 6, ... 按顺序存储在 counter 中,那么您需要重构填充 counter 数组的第一个 for 循环中的逻辑,这样您就不会留下索引未设置。 (您可以使用第二个计数器作为索引来执行此操作,该索引仅在值为even 时增加)试一试,如果您无法使其工作,请删除另一条评论(在您试一试之后)我很乐意为您提供进一步的帮助。 我尝试初始化一个新的计数器counter3[25] 并让它等于counter3[i]= counter[i+1] 并显示它,但它不起作用。这一步我真的很迷茫 好吧,等一下,我的错,你误会了。我的意思是使用单独的计数器索引,而不是数组。我给你举个例子。

以上是关于我写了一个程序来显示数组的内容,但它显示的是它的地址的主要内容,如果未能解决你的问题,请参考以下文章

如何让RichTextBox自动调整大小

程序应该显示文件的最后 5 行,但它不适用于大文件

显示 dojo 简单对话框时出错

如何检查我是不是在javascript中提交空白输入?我写了一个程序,但它不工作

显示来自 for 循环的数组内容

UWP 应用程序崩溃而不是显示消息对话框