【问题标题】:understanding/clarifying logic of code in c理解/澄清c中代码的逻辑
【发布时间】:2016-06-24 10:26:40
【问题描述】:

以下是来自 www.tutorialspoint.com 的代码,我在这里学习算法和数据结构的基础知识。本教程代码给出了一个 ex。对数组的插入操作。

    #include <stdio.h>
    main() {
       int LA[] = {1,3,5,7,8};
       int item = 10, k = 3, n = 5;
       int i = 0, j = n;

       printf("The original array elements are :\n");

       for(i = 0; i<n; i++) {
          printf("LA[%d] = %d \n", i, LA[i]);
       }

       n = n + 1;

       while( j >= k){
          LA[j+1] = LA[j];
          j = j - 1;
       }

       LA[k] = item;

       printf("The array elements after insertion :\n");

       for(i = 0; i<n; i++) {
          printf("LA[%d] = %d \n", i, LA[i]);
       }
    }

我理解它在给定 k 值作为数组索引添加新项目的代码。并且在编译和运行时运行良好,没有任何错误。让我困惑的是 while 循环中 LA[j+1] = LA[j] 行的逻辑。

我的理解是在 c 中你必须声明数组的大小。但在前。代码 int LA[] = {1,3,5,7,8}; 括号 [ ] 为空。所以我不确定它是固定大小还是可以将更多元素添加到数组中。

现在j 被赋予n 的值,即5(数组长度)。数组声明有5个元素,数组索引为0到4。

(在while循环的第一次迭代中)所以LA[j + 1]LA[5 + 1]LA[6]。现在数组只有 5 个索引为 0 到 4 的元素。所以根据我的说法,即使在假设可以将更多元素添加到数组之后,它如何将 LA[j] 的值分配给 LA[j + 1]。它说 LA[6] = LA[5] 但索引 5 处没有任何内容,因为最后一个索引是 4。

我曾尝试在 google 上搜索,但除了代码或部分代码外,我不确定要搜索什么。而且用代码搜索也没有用。

请帮助我理解。谢谢。

【问题讨论】:

  • 当您不理解某些代码时,您可以随时尝试使用调试器单步执行它 - 这有助于使逻辑更加清晰。
  • www.tutorialspoint.com 是否真的将其作为良好代码的示例,还是您应该修复的非常糟糕的代码示例?如果提供此代码作为好代码示例,我建议另找地方学习c
  • 我正在学习算法和数据结构。他们提供的代码运行并确实向数组中添加了一个元素。我已经编译并运行了代码及其工作。我还不知道如何调试 c 代码。将谷歌并尝试
  • 它只对@JVLJewels 有效。此代码调用未定义的行为。确保您阅读了答案并接受了答案。

标签: c arrays algorithm initialization


【解决方案1】:
int LA[] = {1,3,5,7,8};

相当于:

int LA[5] = {1,3,5,7,8};

空括号只是告诉编译器自动将元素的数量设置为数组的大小。


是的,你是对的,L[6] 是越界访问,因为L 的大小为 5。所以,正如你所说的,索引在 [0, 4] 中,所以 L[5] 也是越界!

这段代码错了!


阅读更多关于未定义行为Undefined, unspecified and implementation-defined behavior

【讨论】:

  • 是的。这就是我困惑的原因。但是,如果代码越界,为什么它会给出正确的输出呢?这就是我想要弄清楚的。感谢您抽出时间回答我的问题。
  • @JVLJewels 未定义的行为意味着程序可能会也可能不会按您的预期工作。例如,它今天可能会在您的机器上按您期望的那样工作,但明天就不行了。在我的机器上,它可能不像你今天所期望的那样工作。我已经编辑了我的答案,希望对您有所帮助!
【解决方案2】:

首先,这是一个非常糟糕的代码,由非常弱的程序员编写并且具有未定义的行为。

例如数组LA

int LA[] = {1,3,5,7,8};

只有 5 个元素。

但是在这些循环中

   while( j >= k){
      LA[j+1] = LA[j];
      ^^^^^^^
      j = j - 1;
   }

   for(i = 0; i<n; i++) {
              ^^^^ n is already set to 6
      printf("LA[%d] = %d \n", i, LA[i]);
   }

尝试写入数组以外的内存。 还有一些神奇的值,例如n = 5。至少写出来会好很多

n = sizeof( LA ) / sizeof( *LA )

考虑到 C 中没有参数的函数 main 应该像这样声明

int main( void )

该程序可以看起来例如以下方式

#include <stdio.h>

int main( void ) 
{
    int a[] = { 1, 3, 5, 7, 9 };
    const size_t N = sizeof( a ) / sizeof( *a );

    while ( 1 )
    {
        printf( "The original array elements are:" );
        for ( size_t i = 0; i < N; i++ ) printf( " %d", a[i] );
        printf( "\n" );

        printf( "\nEnter a number to insert in the array (0 - exit): " );
        int value;

        if ( scanf( "%d", &value ) != 1 || value == 0 ) break;

        printf( "Enter a position in the array where to insert: " );
        size_t pos;

        if ( scanf( "%zu", &pos ) != 1 ) break;

        size_t j = N;

        if ( pos < N )
        {
            while ( --j != pos ) a[j] = a[j-1];
            a[j] = value;
        }           

        printf( "\nThe array elements after insertion:");

        for ( size_t i = 0; i < N; i++ ) printf( " %d", a[i] );
        printf( "\n\n" );
    }

    return 0;
}

它的输出可能看起来像

The original array elements are: 1 3 5 7 9

Enter a number to insert in the array (0 - exit): 2
Enter a position in the array where to insert: 1

The array elements after insertion: 1 2 3 5 7

The original array elements are: 1 2 3 5 7

Enter a number to insert in the array (0 - exit): 6
Enter a position in the array where to insert: 4

The array elements after insertion: 1 2 3 5 6

The original array elements are: 1 2 3 5 6

Enter a number to insert in the array (0 - exit): 0

算法背后的逻辑很简单。如果您有一个包含 N 个元素的数组,并且想要在位置 pos 中插入一个小于 N 的值,那么您需要从位置 pos 开始向右移动所有元素并将新值写入索引为pos 的元素。原始数组最右边的元素将丢失,因为它将被前面的元素覆盖。程序输出显示了这个结果。

正如您正确指出的那样,在程序中定义为具有5 元素的数组的有效索引范围是[0, 4]

当一个数组被声明时没有它的维度,如本例所示

int a[] = { 1, 3, 5, 7, 9 };

然后编译器根据初始值设定项的数量确定其维度。因此上述声明等价于

int a[5] = { 1, 3, 5, 7, 9 };

【讨论】:

  • 感谢您抽出时间回答我的问题。你的回答很有见地,也提供了更多的c编程知识。你知道它为什么在越界时运行并给出正确的输出吗?
  • @JVLJewels 由于行为未定义,因此结果可以是包括正确输出在内的任何结果。:) 这意味着覆盖数组之外的内存并不会阻止输出它。:)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
相关资源
最近更新 更多