You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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", &timestep, &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", &timestep, &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

优化实现:一步生成结果

可以通过一次遍历直接构建结果数组,彻底避免标记删除的冗余步骤,逻辑更清晰,效率更高。

实现思路

  1. 初始化结果数组的索引,记录当前连续值组的起始行索引和对应的值
  2. 遍历输入数组:
    • 当遇到值与当前组不同时,将当前组的起始行和上一行(当前组的结束行)加入结果
    • 更新当前组的起始行索引和对应的值
  3. 遍历结束后,将最后一组的首尾行加入结果

完整代码示例

#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", &currentValue);
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:20:27