C语言优化移除字符串数组冗余数据的技术问询
问题:提取连续相同传感器读数的首尾时间点
需求说明
现有CSV格式的字符串数组,第一列为时间点,第二列为传感器读数。需要保留每组连续相同读数的首尾行,直接生成符合要求的结果,无需先标记待删除行再二次清理的冗余操作。
输入输出示例
输入示例
1.00 -2000 1.99 -2000 48.00 35000 54.99 35000 55.00 35000 55.39 35000 58.99 35000 59.00 37000 59.39 37000
预期输出
1.00 -2000 1.99 -2000 48.00 35000 58.99 35000 59.00 37000 59.39 37000
现有代码的问题
当前代码分为标记待删除行、二次清理数组两步,不仅冗余复杂,还存在逻辑错误:
- 标记逻辑中嵌套循环处理连续相同值时,未正确跳过所有中间行,导致部分不该保留的行(如示例中的54.99)未被标记
- 二次清理时的数组移位操作效率低,且容易出现索引错误
现有代码如下:
// // PART 1: Tag elements to remove from array // int i; double timestep, value, previousValue; for (i = 0; i < numTestCases; ++i) { sscanf(BUFFER[i], "%lf %lf", ×tep, &value); // First element, set previous value if (i == 0) { previousValue = value; continue; } // Current value is equal to previous value, tag unnecessary elements if (value == previousValue) { while (i + 1 < numTestCases) { ++i; sscanf(BUFFER[i], "%lf %lf", ×tep, &value); if (value == previousValue) sprintf(BUFFER[i], "."); else { --i; break; } } } // Current value is different from previous value, update previous value... else previousValue = value; } // // PART 2: Remove tagged elements from array, trim the array // & count new number of elements // int newNumTestCases = 0; for (i = 0; i < numTestCases; ++i) { if (strcmp(BUFFER[i], ".") == 0) { int j; for (j = i; j < numTestCases - 1; ++j) { strcpy(BUFFER[j], BUFFER[j + 1]); strcpy(BUFFER[j + 1], ""); } --i; --newNumTestCases; } else ++newNumTestCases; }
当前错误输出
1.00 -2000 1.99 -2000 48.00 35000 54.99 35000 <-- 错误保留的中间行 59.00 37000 59.39 37000
优化实现:一步生成结果
可以通过一次遍历直接构建结果数组,彻底避免标记删除的冗余步骤,逻辑更清晰,效率更高。
实现思路
- 初始化结果数组的索引,记录当前连续值组的起始行索引和对应的值
- 遍历输入数组:
- 当遇到值与当前组不同时,将当前组的起始行和上一行(当前组的结束行)加入结果
- 更新当前组的起始行索引和对应的值
- 遍历结束后,将最后一组的首尾行加入结果
完整代码示例
#include <stdio.h> #include <string.h> #define MAX_LINES 1000 // 根据实际需求调整最大行数 int main() { // 示例输入,实际可替换为从CSV读取的BUFFER数组 char input[MAX_LINES][100] = { " 1.00 -2000", " 1.99 -2000", "48.00 35000", "54.99 35000", "55.00 35000", "55.39 35000", "58.99 35000", "59.00 37000", "59.39 37000" }; int numTestCases = 9; // 输入行数 char result[MAX_LINES][100]; int resultIdx = 0; if (numTestCases == 0) { // 空输入处理 return 0; } // 初始化第一组的起始行和值 double currentValue; sscanf(input[0], "%*lf %lf", ¤tValue); int startIdx = 0; for (int i = 1; i < numTestCases; ++i) { double value; sscanf(input[i], "%*lf %lf", &value); if (value != currentValue) { // 将当前组的首尾行加入结果 strcpy(result[resultIdx++], input[startIdx]); strcpy(result[resultIdx++], input[i-1]); // 更新当前组的起始行和值 currentValue = value; startIdx = i; } } // 处理最后一组 strcpy(result[resultIdx++], input[startIdx]); strcpy(result[resultIdx++], input[numTestCases - 1]); // 输出结果 printf("处理后结果:\n"); for (int i = 0; i < resultIdx; ++i) { puts(result[i]); } return 0; }
代码说明
- 只遍历输入数组一次,时间复杂度为O(n),比原代码的O(n²)(数组移位操作)效率更高
- 直接构建结果数组,无需修改原输入数组,避免了原代码中标记和移位的逻辑错误
- 逻辑清晰,注释明确,便于维护和扩展
内容的提问来源于stack exchange,提问作者Alex Spataru
相关产品推荐
相关产品推荐

