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

C语言字符串解析程序故障:仅重复输出最后一条输入数据问题排查

C语言数据存储与输出问题排查解决

需求说明

  • 接收用户输入的多条格式一致的字符串,示例:
    String 1 : Voltage 230,Current 3.14,PF 0.91,KW 1889.91
    String 2 : Voltage 240,Current 2.98,PF 0.84,KW 1889.92
  • 按逗号拆分字符串,再将子串按空格拆分,提取对应参数值并整理为表格形式
  • 过滤规则:若Voltage<230 且 PF<0.85,则不记录该条数据

问题描述

现有C语言代码运行后,仅重复输出最后一条输入的数据,无法正确展示所有符合条件的输入数据,需排查并解决该问题。

现有代码及输入输出情况

现有代码

#include <stdio.h>
#include <string.h>
void main() 
{
    char str[55];
    char *vol[5], *cur[5], *pf[5], *kw[5];
    int i, k = 0, m;
    char delim1[] = ",";
    for (i = 0; i < 5; i++) 
    {
        printf("Enter value : ");
        gets(str);
        char *tk1 = strtok(str, delim1);
        while (tk1 != NULL) {
            if (tk1[0] == 'v') {
                vol[k] = strchr(tk1, ' ') + 1;
            } 
            else if (tk1[0] == 'c') {
                cur[k] = strchr(tk1, ' ') + 1;
            } 
            else if (tk1[0] == 'p') {
                pf[k] = strchr(tk1, ' ') + 1;
            }
            else if (tk1[0] == 'k') {
                kw[k] = strchr(tk1, ' ') + 1;
            }
            tk1 = strtok(NULL, delim1);
        }
        k++;
    }
    printf("Voltage \tCurrent \t PF\t\t\t kW\n");
    for (m = 0; m < 5; m++) {
        printf("%s\t\t\t%s\t\t%s\t\t%s\n", vol[m], cur[m], pf[m], kw[m]);
    }
    return 0;
}

预期输出

Enter value : Voltage 230,Current 7.89,PF 0.91,KW 1289.33   (第1次输入)
Enter value : Voltage 230,Current 3.20,PF 0.84,KW 1100.32   (第2次输入)
Enter value : Voltage 240,Current 4.78,PF 0.91,KW 1278.87   (第3次输入)
Enter value : Voltage 230,Current 7.45,PF 0.91,KW 1945.34   (第4次输入)
Enter value : Voltage 210,Current 5.13,PF 0.81,KW 998.33    (第5次输入)

Voltage     Current      PF      kW
210     5.13        0.81        998.33      (最新输入的第5条数据)
230     7.45        0.91        1945.34
240     4.78        0.91        1278.87
230     3.20        0.84        1100.32
230     7.89        0.91        1289.33     (最早输入的第1条数据)

实际输出

Enter value : Voltage 230,Current 7.89,PF 0.91,KW 1289.33
Enter value : Voltage 230,Current 3.20,PF 0.84,KW 1289.32
Enter value : Voltage 240,Current 4.78,PF 0.91,KW 1278.87
Enter value : Voltage 230,Current 7.45,PF 0.91,KW 1945.34
Enter value : Voltage 210,Current 5.13,PF 0.81,KW 998.33
Voltage     Current      PF          kW
210         5.13        0.81        998.33
210         5.13        0.81        998.33
210         5.13        0.81        998.33
210         5.13        0.81        998.33
210         5.13        0.81        998.33

问题分析

  1. 指针指向复用内存:代码中vol、cur、pf、kw都是指针数组,存储的是指向局部数组str内部的地址。每次循环输入时,str的内容会被新输入覆盖,所有指针始终指向同一块内存空间,最终全部指向最后一次输入的内容。
  2. 函数安全性问题:使用已废弃的gets函数,存在缓冲区溢出风险。
  3. 未实现过滤规则:完全忽略了需求中“Voltage<230且PF<0.85时不记录”的要求。
  4. 输出顺序不符预期:当前代码按输入顺序输出,而预期是从最新到最旧逆序输出。

解决方法

  1. 存储数值而非指针:用结构体存储每条数据的数值,避免指针指向被覆盖的内存。
  2. 替换不安全函数:用fgets替代gets,并处理换行符。
  3. 实现过滤逻辑:提取数据后判断是否符合过滤条件,仅保留有效数据。
  4. 调整输出顺序:逆序遍历有效数据,实现从最新到最旧的输出。

修正后的代码

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

// 定义结构体存储每条电力数据
typedef struct {
    float voltage;
    float current;
    float pf;
    float kw;
} PowerData;

int main() 
{
    char str[55];
    PowerData data[5];
    int valid_count = 0; // 记录符合条件的数据条数
    char delim1[] = ",";
    
    for (int i = 0; i < 5; i++) 
    {
        printf("Enter value : ");
        // 使用fgets读取输入,处理异常情况
        if (fgets(str, sizeof(str), stdin) == NULL) {
            break;
        }
        // 去掉输入末尾的换行符
        str[strcspn(str, "\n")] = '\0';
        
        char *tk1 = strtok(str, delim1);
        PowerData temp_data = {0};
        
        while (tk1 != NULL) {
            // 忽略大小写匹配参数类型
            switch(tolower(tk1[0])) {
                case 'v':
                    temp_data.voltage = atof(strchr(tk1, ' ') + 1);
                    break;
                case 'c':
                    temp_data.current = atof(strchr(tk1, ' ') + 1);
                    break;
                case 'p':
                    temp_data.pf = atof(strchr(tk1, ' ') + 1);
                    break;
                case 'k':
                    temp_data.kw = atof(strchr(tk1, ' ') + 1);
                    break;
                default:
                    break;
            }
            tk1 = strtok(NULL, delim1);
        }
        
        // 应用过滤规则:仅保留不符合Voltage<230且PF<0.85的数据
        if (!(temp_data.voltage < 230 && temp_data.pf < 0.85)) {
            data[valid_count++] = temp_data;
        }
    }
    
    // 逆序输出有效数据(最新输入在前)
    printf("\nVoltage\t\tCurrent\t\tPF\t\tkW\n");
    for (int m = valid_count - 1; m >= 0; m--) {
        printf("%.2f\t\t%.2f\t\t%.2f\t\t%.2f\n", 
               data[m].voltage, data[m].current, data[m].pf, data[m].kw);
    }
    
    return 0;
}

代码说明

  • 用结构体PowerData存储每条数据的数值,彻底解决指针指向复用内存的问题。
  • 替换gets为fgets,并通过strcspn去除换行符,提升输入安全性。
  • 实现过滤规则,自动跳过不符合条件的数据。
  • 逆序遍历有效数据,满足从最新到最旧的输出要求。
  • 使用atof将字符串转为浮点型,便于数值判断和格式化输出。

内容的提问来源于stack exchange,提问作者Yatharth Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:47:21