C语言文件处理程序Bug求助:删除最大负数逻辑异常
C语言代码删除最大负数逻辑错误排查与修复
问题背景
需求:文件中每行最多含30个整数,需删除每行的最大负数;若该行所有负数相同或仅含一个负数,则不执行删除操作。
当前代码处理输入行:
1 2 -4 5 2 -4 6 -4 10 5 6 -7 -7 9 -8
时,未按预期删除最大负数(-4),反而删除了最后一个负数(-8),且该错误仅在存在重复负数时出现。
原代码
#include <stdio.h> #include <stdlib.h> #include <string.h> unsigned read_string(int*, FILE*); void print(int*, unsigned, FILE*); void remove_max_negative(int*, unsigned*); int main() { int values[30], s; unsigned size, n = 1; FILE* file = fopen("1.txt", "r"); if(!file){ printf("error"); return 1; } FILE* out = fopen("r.txt", "w"); if(!out){ printf("error"); return 1; } while (size = read_string(values, file)) { remove_max_negative(values, &size); print(values, size, out); } fclose(file); fclose(out); remove("1.txt"); rename("r.txt", "1.txt"); return EXIT_SUCCESS; } unsigned read_string(int* values, FILE* stream) { char value[1024]; unsigned result = 0; fscanf(stream, "%s", value); while (!feof(stream)) { values[result] = atoi(value); result++; if (getc(stream) == '\n') return result; fscanf(stream, "%s", value); } return result; } void print(int* values, unsigned size, FILE* output) { for (int i = 0; i < size; i++) { fprintf(output, "%d ", values[i]); } fprintf(output, "\n"); } void remove_max_negative(int* values, unsigned* size) { int max_value = -2147483648, flag = 0, index_max_value = -1; for (int i = 0; i < *size; i++) { if (values[i] < 0) { if (values[i] > max_value) { flag = 0; max_value = values[i]; index_max_value = i; } else if (values[i] == max_value) { flag = 1; index_max_value = i; } else if (flag) { index_max_value = i; } } }if (index_max_value != -1) { --* size; for (int i = index_max_value; i < *size; i++) { values[i] = values[i + 1]; } } }
错误原因分析
- 逻辑混乱的下标更新:在
remove_max_negative函数中,当遇到比当前max_value更小的负数时,若flag为1,错误地将index_max_value更新为当前下标,这直接导致遍历到最后一个负数时,下标被覆盖为最后一个负数的位置。 - 未处理需求中的跳过条件:原代码完全没有判断「所有负数相同」或「仅一个负数」的情况,只要存在负数就执行删除操作,违反需求。
修复方案
重写remove_max_negative函数,分三步实现逻辑:
- 遍历数组,统计负数总数、最大负数的值及其出现次数
- 判断是否满足删除条件:负数总数>1,且最大负数的出现次数≠负数总数(即不是所有负数都相同)
- 找到第一个最大负数的下标,执行删除操作
修复后的remove_max_negative函数:
void remove_max_negative(int* values, unsigned* size) { int max_neg = -2147483648; int neg_count = 0; int max_neg_count = 0; int target_index = -1; // 第一步:统计负数信息 for (int i = 0; i < *size; i++) { if (values[i] < 0) { neg_count++; if (values[i] > max_neg) { max_neg = values[i]; max_neg_count = 1; target_index = i; } else if (values[i] == max_neg) { max_neg_count++; } } } // 第二步:判断是否需要删除 if (neg_count <= 1 || max_neg_count == neg_count) { return; // 不满足删除条件,直接返回 } // 第三步:执行删除操作 if (target_index != -1 && target_index < *size) { --*size; for (int i = target_index; i < *size; i++) { values[i] = values[i + 1]; } } }
验证结果
用示例输入测试,修复后的代码会删除第一个出现的最大负数-4,输出结果为:
1 2 5 2 -4 6 -4 10 5 6 -7 -7 9 -8
符合需求预期。
内容的提问来源于stack exchange,提问作者citn
相关产品推荐
相关产品推荐

