gpt4 book ai didi

c - 运行 printf 如何更改我的 int 变量中的值?

转载 作者:太空宇宙 更新时间:2023-11-04 08:17:22 26 4
gpt4 key购买 nike

关闭。这个问题需要 debugging details 。它目前不接受答案。












想改进这个问题?更新问题,使其成为 Stack Overflow 的 on-topic

5年前关闭。




Improve this question




我第一次用 C 编写一个类,使用 gcc 作为我的编译器。

作为第 10,000,000 个提出这个问题的人,我想提前道歉。

对于那些对阅读所有这些不感兴趣的人,我在下面提出了实际问题(最后一段)。

我的代码在这个问题的末尾被复制。我只用一个 10 int 数组完成了分配,并且排序工作正常,但是如果我将其更改为 11 长度数组,事情就会变得很奇怪。对于这个问题,我说的是我的代码如何处理要排序的 11 个数字的数组。

我遇到了一个问题,我认为这与以不可预测/不正确的方式处理内存的编写不佳的代码有关。我发现了许多具有类似问题的 stackoverflow 问题,但经过我所有的故障排除和搜索后,我仍然卡住了。我发现的所有问题都没有解决我的问题的解决方案。我也相信我的合并排序算法很可能有缺陷并且可能导致问题,但我还没有找出我到底做错了什么,因为它有时可以正常工作。

大多数 S.O.我看到的问题必须处理将函数范围地址传回调用函数或声明但未初始化的变量。我查看了我的代码,没有发现任何这些问题的实例,但我相信我的问题具有类似的性质。

如果我添加一个 printf("");在我的 merge() 函数定义中的任何位置声明,代码对数组进行正确排序。 printf 语句实际上必须至少有一个字符,如果我把它放在任何其他函数中,它就没有效果。我在下面的代码中做错了什么,它允许简单地调用 printf 来更改我的函数传递的值?

注意:我已经在带有 GCC 的 linux 环境以及带有 MinGW GCC 的 Windows 上编译了它,它在每种情况下的表现都不同,但在这两种情况下它都被破坏并且似乎是同一个问题。

我的简单合并排序实现的代码如下:

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

#define NUMVALS 11

//function prototypes
void printArrValues(int*, int);
void mergeSort(int*, int, int);
void merge(int*, int, int, int, int);
void showArraySorting(int*);

//define some data to sort
int intArrValsDesc[NUMVALS] = {10,9,8,7,6,5,4,3,2,1,0};
int intArrValsAsc[NUMVALS] = {1,2,3,4,5,6,7,8,9,10,11};
int intArrValsPreset1[NUMVALS] = {6,6,2,2,1,1,6,2,1,1,4};
int intArrValsPreset2[NUMVALS] = {13,99,23,1,57,29,19,456,9,9,34};

//self explanatory
int main() {
//show a few different sorting scenarios
//showArraySorting(intArrValsAsc);
//showArraySorting(intArrValsDesc);
//showArraySorting(intArrValsPreset1);
showArraySorting(intArrValsPreset2);

return(0);
}

/*
** function to sort array while outputting beginning state,
** progress states, and finished state
*/
void showArraySorting(int *intArrToSort) {
//output initial array values
printf("Start: ");
printArrValues(intArrToSort, NUMVALS);

mergeSort(intArrToSort, 0, NUMVALS - 1);

//output sorted array values
printf("Finish: ");
printArrValues(intArrToSort, NUMVALS);
printf("-----------------\n");
}

/*
** function to output each value in the argument int array to the
** console in the current order via stdio in the format "[ a b c ... ]"
*/
void printArrValues(int *intArrToPrint, int intNumValues) {

//define iteration counter int for looping through the values array
int i;

//begin the line with bracket for aesthetics
printf("[ ");

//loop MAX times to print out the values
for (i = 0; i < intNumValues; i++) {

//print out each value with a space after it
printf("%d ", intArrToPrint[i]);
}

//end the line with closing bracket
printf("]\n");
}

//function which implements the merge sort algorithm
//by keeping track of nested index ranges in the array to be sorted.
//as sorting decisions are made, numbers are rearranged in the target array
void mergeSort(int *intArrToSort, int intLeftStartIndex, int intRightEndIndex) {
//if the current index range hasn't yet honed down to a single index
if (intLeftStartIndex < intRightEndIndex) {
//printf("\n");
//find the remaining two indices required to split the argument index
//range into two smaller ones
int intLeftEndIndex = (intLeftStartIndex + intRightEndIndex) / 2;
int intRightStartIndex = intLeftEndIndex + 1;

//printf("[%d, %d] and [%d, %d]\n",intLeftStartIndex,intLeftEndIndex, intRightStartIndex, intRightEndIndex);

//continue recursively breaking the array subsets down into smaller pieces
mergeSort(intArrToSort, intLeftStartIndex, intLeftEndIndex);
mergeSort(intArrToSort, intRightStartIndex, intRightEndIndex);

//all recursion below this level has finished, so merge the current two array subsets
merge(intArrToSort, intLeftStartIndex, intLeftEndIndex, intRightStartIndex, intRightEndIndex);
//show the status of the sort
printf(" sorting... ");
printArrValues(intArrToSort, NUMVALS);
}
}

/*
** Function to re-order the broken down components of the merge sort
** by comparing them to each other and swapping values in the parent array.
*/
void merge(int *intArrToSort, int intLeftStartIndex, int intLeftEndIndex, int intRightStartIndex, int intRightEndIndex) {

//calculate and store the number of values in each subset of the array.
int intLeftArrSize = intLeftEndIndex - intLeftStartIndex + 1;
int intRightArrSize = intRightEndIndex - intRightStartIndex + 1;

//keep track of the total number of ints being combined in this pass
int intTotalSize = intRightEndIndex - intLeftStartIndex + 1;

//create new arrays to stack the sorted values in
int intArrLeft[intLeftArrSize], intArrRight[intRightArrSize];
int i;

//copy values into new left array
for (i = 0; i < intLeftArrSize; i++) {
intArrLeft[i] = intArrToSort[intLeftStartIndex + i];
}
//copy values into new right array
for (i = 0; i < intRightArrSize; i++) {
intArrRight[i] = intArrToSort[intRightStartIndex + i];
}

//define the ints to hold the current index for both the left
//and right array subsets.
int intCurrentLeftIndex = 0;
int intCurrentRightIndex = 0;

//define the int to hold the "target" index, initialize it with the leftmost
//index of the left array subset. this holds which position in intArrToSort
//is about to be updated with a new, sorted value
int intTargetIndex = intLeftStartIndex;

//sentinel variable for while loop
int intDone = 0;

//loop until all numbers in the two array subsets have been sorted into intArrToSort
while (intDone == 0) {
//check if the lowest uncombined value in the left array is lower than the one in the right array
if (intArrLeft[intCurrentLeftIndex] <= intArrRight[intCurrentRightIndex]) {
//it is, so assign it to the current target position in the combined array
intArrToSort[intTargetIndex] = intArrLeft[intCurrentLeftIndex];

//increment the array's index counter to signal that another number has been combined
intCurrentLeftIndex++;

//check if the lowest uncombined value in the right array is lower than the one in the left array
} else {

//it is, so assign it to the current target position in the combined array
intArrToSort[intTargetIndex] = intArrRight[intCurrentRightIndex];

//increment the array's index counter to signal that another number has been combined
intCurrentRightIndex++;
}

//increment the target index to prevent overwriting the recently combined value
intTargetIndex++;

//if we've combined all but one item in the two array subsets
if (intCurrentLeftIndex + intCurrentRightIndex >= intTotalSize - 1) {

//don't iterate again through this while loop
intDone = 1;

//if the remaining item is in the left array
if (intLeftArrSize - intCurrentLeftIndex > 0) {

//copy its value to intArrToSort
intArrToSort[intTargetIndex] = intArrLeft[intCurrentLeftIndex];

//if the remaining item isn't in the left array
} else {

//assume it's in the right array and copy its value to intArrToSort
intArrToSort[intTargetIndex] = intArrRight[intCurrentRightIndex];
}
}
}
}

我也欢迎对我糟糕的代码提出任何相关或不相关的批评。

最佳答案

您的问题出在 merge 函数中:您的终止测试不正确,您假设您只需要检查最后一个元素。事实上,一旦发生这种情况,您需要检查是否完成了每一半以停止比较元素。例如,假设数组已经排序:左半部分将被完全复制,您的测试将无法检测到您无法将左半部分的下一个元素与右半部分的第一个元素进行比较。

这是一个更正的版本:

/*
** Function to re-order the broken down components of the merge sort
** by comparing them to each other and swapping values in the parent array.
*/
void merge(int *intArrToSort, int intLeftStartIndex, int intLeftEndIndex, int intRightStartIndex, int intRightEndIndex) {

//calculate and store the number of values in each subset of the array.
int intLeftArrSize = intLeftEndIndex - intLeftStartIndex + 1;
int intRightArrSize = intRightEndIndex - intRightStartIndex + 1;

//keep track of the total number of ints being combined in this pass
int intTotalSize = intRightEndIndex - intLeftStartIndex + 1;

//create new arrays to stack the sorted values in
int intArrLeft[intLeftArrSize], intArrRight[intRightArrSize];
int i;

//copy values into new left array
for (i = 0; i < intLeftArrSize; i++) {
intArrLeft[i] = intArrToSort[intLeftStartIndex + i];
}
//copy values into new right array
for (i = 0; i < intRightArrSize; i++) {
intArrRight[i] = intArrToSort[intRightStartIndex + i];
}

//define the ints to hold the current index for both the left
//and right array subsets.
int intCurrentLeftIndex = 0;
int intCurrentRightIndex = 0;

//using i to index into the destination array receiving the merged elements
//loop until while there elements left in both arrays
for (i = intLeftStartIndex; intCurrentLeftIndex < intLeftArrSize && intCurrentRightIndex < intRightArrSize; i++) {
//check if the lowest uncombined value in the left array is lower than the one in the right array
if (intArrLeft[intCurrentLeftIndex] <= intArrRight[intCurrentRightIndex]) {
//if so, assign it to the current target position in the combined array
intArrToSort[i] = intArrLeft[intCurrentLeftIndex];

//increment the array's index counter
intCurrentLeftIndex++;
} else {
//otherwise, assign the element from the right array to the current target position in the combined array
intArrToSort[intTargetIndex] = intArrRight[intCurrentRightIndex];

//and increment the array's index counter
intCurrentRightIndex++;
}
}

//we have exhausted either the left or the right half:

// try and copy left over elements from the left
for (; intCurrentLeftIndex < intLeftArrSize; i++) {
intArrToSort[i] = intArrLeft[intCurrentLeftIndex];
intCurrentLeftIndex++;
}

// and finally try and copy left over elements from the right
for (; intCurrentRightIndex < intRightArrSize; i++) {
intArrToSort[i] = intArrRight[intCurrentRightIndex];
intCurrentRightIndex++;
}
}

至于 build 性地批评您的代码:
  • 注释太多,代码被埋在无用​​的废话中,注释明显的语句。
  • 变量名太长了。选择有意义但简短的名称。在具有明显界限的简单 for 循环中使用的数组索引可以命名为 ijk
  • 数组边界应遵循 C 约定,首先包含,最后排除。这使得代码更简单,并允许一个空数组。
  • 前向函数声明的原型(prototype)应具有参数名称以便于阅读。

  • 这是一个简化版本:
    #include <stdio.h>
    #include <stdlib.h>

    #define NUMVALS 11

    //function prototypes
    void printArrValues(int *array, int length);
    void mergeSort(int *array, int start, int end);
    void merge(int *array, int start, int middle, int end);
    void showArraySorting(int *array);

    //define some data to sort
    static int intArrValsDesc[NUMVALS] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
    static int intArrValsAsc[NUMVALS] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
    static int intArrValsPreset1[NUMVALS] = { 6, 6, 2, 2, 1, 1, 6, 2, 1, 1, 4 };
    static int intArrValsPreset2[NUMVALS] = { 13, 99, 23, 1, 57, 29, 19, 456, 9, 9, 34 };

    int main(void) {
    //show a few different sorting scenarios
    showArraySorting(intArrValsAsc);
    showArraySorting(intArrValsDesc);
    showArraySorting(intArrValsPreset1);
    showArraySorting(intArrValsPreset2);
    return 0;
    }

    /*
    ** function to sort array while outputting beginning state,
    ** progress states, and finished state.
    */
    void showArraySorting(int *array) {
    printf("Start: ");
    printArrValues(array, NUMVALS);
    mergeSort(array, 0, NUMVALS);
    printf("Finish: ");
    printArrValues(array, NUMVALS);
    printf("-----------------\n");
    }

    /*
    ** function to output each value in the argument int array to the
    ** console in the current order via stdio in the format "[ a b c ... ]"
    */
    void printArrValues(int *array, int length) {
    printf("[ ");
    for (int i = 0; i < length; i++) {
    printf("%d ", array[i]);
    }
    printf("]\n");
    }

    /*
    ** function which implements the merge sort algorithm
    ** by keeping track of nested index ranges in the array to be sorted.
    ** as sorting decisions are made, numbers are rearranged in the target array
    */
    void mergeSort(int *array, int start, int end) {
    //if the current index range hasn't yet honed down to a single index
    if (end - start > 1) {
    int middle = (start + end) / 2;

    //continue recursively breaking the array subsets down into smaller pieces
    mergeSort(array, start, middle);
    mergeSort(array, middle, end);

    //all recursion below this level has finished, so merge the current two array subsets
    merge(array, start, middle, end);
    }
    }

    /*
    ** function to merge adjacent sorted array slices
    */
    void merge(int *array, int start, int middle, int end) {
    //calculate and store the number of values in each subset of the array.
    int leftSize = middle - start;
    int rightSize = end - middle;

    //define temporary arrays to hold values as the destination will be overwritten
    int leftArray[leftSize], rightArray[rightSize];
    int i;

    //copy values into new left array
    for (i = 0; i < leftSize; i++) {
    leftArray[i] = array[start + i];
    }
    //copy values into new right array
    for (i = 0; i < rightSize; i++) {
    rightArray[i] = array[middle + i];
    }

    int leftIndex = 0;
    int rightIndex = 0;

    //using i to index into the destination array receiving the merged elements
    //loop until while there elements left in both arrays
    for (i = start; leftIndex < leftSize && rightIndex < rightSize; i++) {
    if (leftArray[leftIndex] <= rightArray[rightIndex]) {
    array[i] = leftArray[leftIndex];
    leftIndex++;
    } else {
    array[i] = rightArray[rightIndex];
    rightIndex++;
    }
    }

    // try and copy left over elements from the left array
    for (; leftIndex < leftSize; i++) {
    array[i] = leftArray[leftIndex];
    leftIndex++;
    }

    // and finally try and copy left over elements from the right array
    for (; rightIndex < rightSize; i++) {
    array[i] = rightArray[rightIndex];
    rightIndex++;
    }
    }

    请注意,对于大量数据,不建议在自动存储(堆栈上)中分配临时数组。您可以改为在顶层使用 malloc 分配一个临时工作数组,并将其传递给递归函数和 merge 函数。实际上, merge 函数不需要是一个单独的函数。

    这是一个实现,其中 mergeSort 只获取数组及其长度:
    /*
    ** recursive function implement the merge sort algorithm.
    */
    static void mergeSortHelper(int *array, int *temp, int start, int end) {
    if (end - start > 1) {
    int i, middle = (start + end) / 2;

    mergeSortHelper(array, temp, start, middle);
    mergeSortHelper(array, temp, middle, end);

    /* copy both subarrays in a single loop */
    for (i = start; i < end; i++) {
    temp[i] = array[i];
    }
    /* merge subarrays */
    int left = start;
    int right = middle;
    for (i = start; left < middle && right < end; i++) {
    if (temp[left] <= temp[right])
    array[i] = temp[left++];
    else
    array[i] = temp[right++];
    }
    /* flush left subarray */
    while (left < middle) {
    array[i++] = temp[left++];
    }
    /* no need to flush right subarray, elements are already in place */
    }
    }

    /*
    ** function which implements the merge sort algorithm
    ** by keeping track of nested index ranges in the array to be sorted.
    ** as sorting decisions are made, numbers are rearranged in the target array
    */
    void mergeSort(int *array, int length) {
    if (length < 2) {
    return;
    } else
    if (length <= 1000) {
    int temp[1000];
    mergeSortHelper(array, temp, 0, length);
    } else {
    int *temp = malloc(length * sizeof(int));
    if (!temp) {
    printf("not enough memory for mergeSort\n");
    return;
    }
    mergeSortHelper(array, temp, 0, length);
    free(temp);
    }
    }

    关于c - 运行 printf 如何更改我的 int 变量中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35067260/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com