C(VS)中static关键字失效 删除数组次大元素后n值未更新问题
需求说明
- 接收用户输入的数值N,再输入N个整数存入数组
- 编写C语言函数删除数组中所有第二大(次大)元素,删除后重排数组
- 最终输出处理后的新数组,以及更新后的数组长度N
- 样例:输入N=7,数组为
7 11 13 11 8 7 4时,预期输出N=5,数组为7 13 8 7 4
问题复现
原实现代码
#include<stdio.h> int secondLargest(int arr[], int n); int indexOfSecondLargest(int arr[], int n, int max2); void deleteElement(int arr[], int n, int index); void deleteSecondLargest(int arr[], int n); void printArray(int arr[], int n); int main() { static int n; printf("Enter value of n \n"); scanf("%d", &n); int arr[100]; printf("Enter n numbers \n"); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } deleteSecondLargest(arr, n); printf("New value of n = %d and the array is \n", n); printArray(arr, n); return 0; } int secondLargest(int arr[], int n) { int max1 = arr[0], max2 = arr[0]; for (int i = 0; i < n; i++) { if (arr[i] > max1) { max2 = max1; max1 = arr[i]; } if (arr[i] > max2 && arr[i] < max1) { max2 = arr[i]; } } return max2; } int indexOfSecondLargest(int arr[], int n, int max2) { for (int i = 0; i < n; i++) { if (arr[i] == max2) { return i; } } return -1; } void deleteElement(int arr[], int n, int index) { for (int i = index; i < n - 1; i++) { arr[i] = arr[i+1]; } n = n - 1; } void deleteSecondLargest(int arr[], int n) { int max2 = secondLargest(arr, n); int index = indexOfSecondLargest(arr, n, max2); while (index != -1) { deleteElement(arr, n, index); index = indexOfSecondLargest(arr, n, max2); } } void printArray(int arr[], int n) { for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } }
错误运行结果
Enter value of n 7 Enter n numbers 7 11 13 11 8 7 4 New value of n = 7 and the array is 7 13 8 7 4 4 4
问题现象
开发者在Visual Studio环境中调试时,尝试用static关键字修饰main函数中的长度变量n,甚至将n定义为全局变量,但调用删除次大元素的函数后,main函数中的n值始终没有更新为预期的5,数组输出末尾存在冗余元素,无法得到正确结果。
问题根因
- C语言函数默认采用值传递机制,函数形参是实参的独立副本,函数内部对形参的修改不会同步到外层实参。原代码中
deleteElement、deleteSecondLargest函数都以值的方式接收长度参数n,函数内部执行n = n -1时,修改的只是函数栈上的局部副本,main函数中的原始n完全不受影响。 - 即使将main函数中的
n用static修饰、或者定义为全局变量,只要两个删除函数的形参列表中仍定义了同名的int n,函数内部访问的n就会是形参局部变量,自动遮蔽外层的static变量或全局变量,修改操作依然不会生效。 - 由于长度值始终没有更新,删除元素后遍历数组仍用原始长度7计数,就会输出数组尾部未被覆盖的冗余旧值,也就是样例中末尾多打印的两个4。
修复方案
- 调整需要修改长度的函数形参,将长度参数改为指针类型,传入main函数中
n的内存地址,让函数可以直接修改原始n的值,无需依赖static修饰或全局变量。 - 所有涉及数组长度判断、遍历的逻辑,都使用指针解引用获取实时更新的长度值,保证删除元素后长度计数同步变化。
修复后完整代码
#include<stdio.h> int secondLargest(int arr[], int n); int indexOfSecondLargest(int arr[], int n, int max2); void deleteElement(int arr[], int *n, int index); void deleteSecondLargest(int arr[], int *n); void printArray(int arr[], int n); int main() { int n; printf("Enter value of n \n"); scanf("%d", &n); int arr[100]; printf("Enter n numbers \n"); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } deleteSecondLargest(arr, &n); printf("New value of n = %d and the array is \n", n); printArray(arr, n); return 0; } int secondLargest(int arr[], int n) { int max1 = arr[0], max2 = arr[0]; for (int i = 0; i < n; i++) { if (arr[i] > max1) { max2 = max1; max1 = arr[i]; } if (arr[i] > max2 && arr[i] < max1) { max2 = arr[i]; } } return max2; } int indexOfSecondLargest(int arr[], int n, int max2) { for (int i = 0; i < n; i++) { if (arr[i] == max2) { return i; } } return -1; } void deleteElement(int arr[], int *n, int index) { for (int i = index; i < *n - 1; i++) { arr[i] = arr[i+1]; } *n = *n - 1; } void deleteSecondLargest(int arr[], int *n) { int max2 = secondLargest(arr, *n); int index = indexOfSecondLargest(arr, *n, max2); while (index != -1) { deleteElement(arr, n, index); index = indexOfSecondLargest(arr, *n, max2); } } void printArray(int arr[], int n) { for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } }
验证结果
修复后运行代码,输入样例数据可得到正确输出:
Enter value of n 7 Enter n numbers 7 11 13 11 8 7 4 New value of n = 5 and the array is 7 13 8 7 4
内容的提问来源于stack exchange,提问作者MOHAMMAD SHOAIB ANSARI
相关产品推荐
相关产品推荐

