【问题标题】:review: remove duplicate from an array [closed]审查:从数组中删除重复项[关闭]
【发布时间】:2021-11-27 13:55:12
【问题描述】:

我想出了一个从数组中删除重复项的代码,并希望它检查错误(例如,可以为数组索引设置 sizeof 吗)?

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>

int main()
{
        int a[] = {1,2,4,4,5,6,2,7, INT32_MAX};
        int flag[sizeof(a)] = {0}, i=0,j=0; 

        while (a[i] != INT32_MAX ) {
                 if(a[i] != a[i+1])
                        a[j++] = a[i];
#if 0
                if(0 == flag[a[i]]) {
                        flag[a[i]] = 1;
                        a[j++] = a[i];
                }
#endif
        i++;
        }

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

【问题讨论】:

  • 提示:你不需要 flags 数组。
  • sizeof(a) 是错误的。想想如果a 包含一个大数字(例如 2000)会发生什么。你会在某个时候寻址flag[2000]....重写你的代码没有flag 数组,你不需要它。
  • @Jabberwocky,确实尝试过没有标志数组的其他版本,但它似乎只适用于排序数组。
  • 代码审查请求应发送至codereview.stackexchange.com
  • 提示:你基本上需要 3 个嵌套循环:一个循环从 0 扫描数组到末尾,下一个内层循环搜索当前数字的重复项,最内层循环移动剩余的数字。一张纸和一支铅笔在这里最有帮助。

标签: arrays c loops duplicates integer


【解决方案1】:

这个数组的初始化

int a[] = {1,2,4,4,5,6,2,7, INT32_MAX};

没有意义。通常int 类型可以与int32_t 类型不同。所以不清楚为什么这个值会出现在初始化列表中,为什么代码依赖这个值。

要删除整数数组中的重复元素,不需要标记值。

此外,在您的代码中,由于 while 循环中的条件,值 INT32_MAX 不会出现在结果子数组中

while (a[i] != INT32_MAX ) {

一般来说,字符数组中可以不存在标记值。

通常a[i] 也可以大于sizeof( a )。所以这个 if 语句

if(0 == flag[a[i]])

没有意义,可以调用未定义的行为。

代码如下所示

int a[] = {1,2,4,4,5,6,2,7 };
const size_t N = sizeof( a ) / sizeof( *a );

size_t n = 0;

for ( size_t i = 0; i != N; i++ )
{
    size_t j = 0;

    while ( j != n && a[j] != a[i] ) j++;

    if ( j == n ) a[n++] = a[i];
}

for ( size_t i = 0; i != n; i++ )
{
    printf( "%d ", a[i] );
}
putchar( '\n' );

这是一个演示程序

#include <stdio.h>

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

    size_t n = 0;

    for ( size_t i = 0; i != N; i++ )
    {
        size_t j = 0;

        while ( j != n && a[j] != a[i] ) j++;

        if ( j == n ) a[n++] = a[i];
    }

    for ( size_t i = 0; i != n; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );    

    return 0;
}

程序输出是

1 2 4 5 6 7 

如果你想在写for循环的时候使用一个标记值

for ( size_t i = 0; i != N && a[i] != SentinelValue; i++ )

SentinelValue 是某个值。

然后在循环之后你应该写

a[n++] = SentinelValue;

【讨论】:

  • 我认为INT32_MAX是哨兵值
  • @Jabberwocky 这没有任何意义。该任务不需要哨兵值。
  • 你是对的,这里不需要哨兵值,但是看看OP的代码:他显然是使用INT32_MAX作为哨兵值:while (a[i] != INT32_MAX )
  • @Jabberwocky 这是他的错误。此类任务不需要哨兵值。
  • 忘记我的第二条评论,我删除它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 2014-06-08
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 2011-06-29
相关资源
最近更新 更多