【问题标题】:Function to remove an element from a sorted array从排序数组中删除元素的函数
【发布时间】:2013-04-28 07:17:22
【问题描述】:

我在从排序数组中删除元素时遇到了一些问题(必须删除元素的所有实例)。当我运行我的程序时,我遇到了分段错误。我不知道为什么会这样,因为函数 remElem(int*, int*, int) 其中第一个 arg 是一个数组,第二个 arg 是一个数组的长度(当元素被删除时它会改变),第三个 arg 是一个元素被删除 - 在我使用 switch 语句和其他函数扩展程序之前正常工作,如 shuffle(int*, int) (用于洗牌数组的元素)和 insElem(int*, int*, int) (用于插入元素进入排序数组。我不知道出了什么问题,请帮忙。我将提供代码与 cmets。还有一些其他小问题与 cmets 一起提供。提前谢谢你:)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_LEN 1000


void initArray(int*, int);
void printArray(int*, int);
void swap(int*, int*);
void insSort(int*, int);
void insElem(int*, int*, int);
void remElem(int*, int*, int);
void shuffle(int*, int);


int main() {
    int array[MAX_LEN];
    int len, elem, comm;

    srandom(time(NULL));

    printf("Number of elements? >> ");
    scanf("%d", &len);

    initArray(array, len);

    do {
        printf("Command? (6 for help) >> ");
        scanf("%d", &comm);
        switch (comm) {
            case 1:
                printArray(array, len);
                break;
            case 2:
                shuffle(array, len);
                break;
            case 3:
                insSort(array, len);
                break;
            case 4:
                printf("Insert element? >> ");
                scanf("%d", &elem);
                insElem(array, &len, elem);
                break;
            case 5:
                printf("Remove element? >> ");
                scanf("%d", &elem);
                remElem(array, &len, elem);
                break;
            case 6:
                printf("Help:\n");
                printf("1 - Print\n");
                printf("2 - Shuffle\n");
                printf("3 - Sort\n");
                printf("4 - Insert element\n");
                printf("5 - Remove element\n");
                printf("6 - Help (this screen)\n");
                printf("0 - Quit\n");
                break;
            case 0:
                break;
            default :
                printf("Wrong input! Repeat!\n");
        }
    } while (comm);

    return EXIT_SUCCESS;
}


/*Initializes array with n random numbers from 0 to 9 (including)*/
void initArray(int a[], int n) {
    int i;

    for (i = 0; i < n; i++)
        a[i] = random() % 10;
}


/*Prints n elements of an array*/
void printArray(int a[], int n) {
    int i;

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


/*Swaps the values of two variables*/
void swap(int *i, int *j) {
    *i = *i + *j;
    *j = *i - *j;
    *i = *i - *j;
    /*I saved up some memory yaaaaaaay :3 */
    /*I spent some processing time nooooo :| */
    /*Which is better... with or without tmp variable???*/
    /*I suppose it depends on application... clearly, this
      method doesnt work with structures, for example*/
}


/*Sorts the elements of an array using insertion sort algorythm*/
void insSort(int a[], int n) {
    int i, j;

    for (i = 1; i < n; i ++)
        for (j = i; j > 0 && a[j] < a[j-1]; j--)
            swap(&a[j], &a[j-1]);
}


/*Inserts an element into a sorted array*/
/*Wassn meant to be working with unsorted arrays
  in that case unpreddictable results*/
void insElem(int a[], int *n, int e) {
    int i, j;

    (*n)++;
    for (i = 0; a[i] < e && a[i+1] < e; i++);

    for (j = *n; j > i + 1; j--)
        a[j] = a[j-1];

    a[i+1] = e;
}


/*Removes an element from a sorted array*/
/*Wassn meant to be working with unsorted arrays
  in that case unpreddictable results*/
void remElem(int a[], int *n, int e) {
    int i, j;

    for (i = 0; i < *n; i++) {
        while (a[i] == e) {
            for (j = i; j < *n; j++)
                a[j] = a[j+1];
        (*n)--;
        }
    }
}


/*Shuffles the elements of an array*/
/*I just did this on the fly...
  are there any known algorythms for doing this*/
void shuffle(int a[], int n) {
    int i;

    for (i = 0; i < n; i++)
        swap(&a[rand()%n], &a[rand()%n]);
}

【问题讨论】:

  • 为什么n参数必须通过地址传递给insElemremElem
  • 您的swap() 不正确。使用临时变量(或更好 - std::swap())。为了节省内存,请使用 xor (^) 但没有理由这样做。
  • @Elazar 这是 C。std::swap 不可用。
  • 当你遇到崩溃时,你应该做的第一件事就是在调试器中运行时尝试同样的事情。它会告诉你崩溃发生在哪里,让你检查甚至遍历函数调用堆栈,也让你检查变量。
  • @michaelb958 你是对的,但不要提它。

标签: c arrays sorting shuffle


【解决方案1】:

以下情况可能会导致越界访问,从而导致未定义的行为:

        for (j = i; j < *n; j++)
            a[j] = a[j+1];

考虑当j == (*n)-1a[j+1] 会发生什么。

至于swap() 函数,您看起来很聪明的实现存在整数溢出和未定义行为的风险。只需使用一个临时变量,让编译器担心效率。

【讨论】:

    【解决方案2】:

    在这个循环中:

    for (j = i; j < *n; j++)
      a[j] = a[j+1];
    

    j = *n - 1 时,您将访问数组边界之外的内存。这会调用未定义的行为,结果可能是任何东西,所以我相信它解释了你的崩溃。至于程序之前没有崩溃的方式 - 这可以做任何事情,它也可能没有负面影响。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 1970-01-01
      • 2011-10-31
      • 2020-04-28
      相关资源
      最近更新 更多