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

C语言停车场终端代码bug:带空格名称的停车场创建异常

终端停车场管理程序Bug排查与优化

异常现象

  • 首次创建带空格名称的停车场(如"park name")时,会抛出Error: invalid capacity错误;
  • 先创建单单词名称的停车场后,再创建带空格名称的停车场则能成功执行;
  • 单独输入p可正常列出已有停车场。

复现示例

p "park name" 20 1 2 3
Error: invalid capacity.

p park 20 1 2 3
Parking lot park successfully created!

p "park name" 20 1 2 3
Parking lot park name successfully created!

p
Existing parking lots:
park 20 20
park name 20 20

程序代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100

// 停车场结构体定义
typedef struct {
    char name[50];
    int capacity;
    float cost15;
    float cost15_after1hour;
    float max_daily_cost;

    int available_spaces;
} ParkingLot;

// 存储已创建停车场的全局变量
ParkingLot parkingLots[10];
int num_parkingLots = 0;

// 创建新停车场函数
void createParkingLot(char name[], int capacity, float cost15, float cost15_after1hour, float max_daily_cost) {
    if (num_parkingLots >= 10) {
        printf("Error: too many parking lots.\n");
        return;
    }

    // 检查停车场名称是否已存在
    for (int i = 0; i < num_parkingLots; i++) {
        if (strcmp(parkingLots[i].name, name) == 0) {
            printf("Error: %s already exists.\n", name);
            return;
        }
    }

    // 检查容量是否合法
    if (capacity <= 0) {
        printf("Error: invalid capacity.\n");
        return;
    }

    // 检查费用规则是否合法
    if (cost15 <= 0 || cost15_after1hour <= cost15 || max_daily_cost <= cost15_after1hour) {
        printf("Error: invalid cost.\n");
        return;
    }

    // 创建新停车场
    strcpy(parkingLots[num_parkingLots].name, name);
    parkingLots[num_parkingLots].capacity = capacity;
    parkingLots[num_parkingLots].cost15 = cost15;
    parkingLots[num_parkingLots].cost15_after1hour = cost15_after1hour;
    parkingLots[num_parkingLots].max_daily_cost = max_daily_cost;
    parkingLots[num_parkingLots].available_spaces = capacity;
    num_parkingLots++;

    printf("Parking lot %s successfully created!\n", name);
}

// 列出已有停车场函数
void listParkingLots() {
    printf("Existing parking lots:\n");
    for (int i = 0; i < num_parkingLots; i++) {
        printf("%s %d %d\n", parkingLots[i].name, parkingLots[i].capacity, parkingLots[i].available_spaces);
    }
}

int main() {
    char command[20];
    char name[50];
    int capacity;
    float cost15, cost15_after1hour, max_daily_cost;

    printf("p [ <park-name> <capacity> <cost-15> <cost-15-after-1hour> <max-daily-cost> ] - Create parking lot\n");

    while (1) {
        scanf("%s", command);

        if (strcmp(command, "p") == 0) {
            char nextChar = getchar(); // 读取"p"后的下一个字符
            if (nextChar == '\n') {
                listParkingLots();
            } else {
                ungetc(nextChar, stdin); // 将未读取的字符放回缓冲区
                char str[MAXSIZE];
                fgets(str, MAXSIZE, stdin);
                char *p = strchr(str, '\"');

                if (p){
                    char str_between_quotes[MAXSIZE];
                    int i = 0;
                    p++; // 指针移动到第一个引号后的字符
                    while (*p != '\"' && *p != '\n' && *p != '\0') {
                        str_between_quotes[i] = *p;
                        i++;
                        p++;
                    }
                    str_between_quotes[i] = '\0'; // 字符串结尾
                    strcpy(name,str_between_quotes);
                } else {
                    sscanf(str, "%s %d %f %f %f", name, &capacity, &cost15, &cost15_after1hour, &max_daily_cost);
                }
                createParkingLot(name,capacity,cost15,cost15_after1hour,max_daily_cost);
            }
        } else if (strcmp(command, "q") == 0) {
            break;
        } else {
            printf("Invalid command.\n");
        }
    }

    return 0;
}

Bug原因分析

问题根源是未初始化的数值变量:

  • 处理带引号名称的分支时,代码仅提取了name变量,但capacity、cost15等数值变量未被赋值,此时这些变量的值是栈内存中的随机垃圾值;
  • 首次运行时,capacity的随机值大概率≤0,触发"invalid capacity"错误;
  • 创建过单单词名称的停车场后,sscanf已给这些变量赋值,后续处理带引号名称时,变量保留了之前的有效值,因此能通过校验。

修复方案

修改main函数中带引号名称的处理逻辑,提取名称后继续读取后续参数:

if (p){
    char str_between_quotes[MAXSIZE];
    int i = 0;
    p++; // 指针移动到第一个引号后的字符
    while (*p != '\"' && *p != '\n' && *p != '\0') {
        str_between_quotes[i] = *p;
        i++;
        p++;
    }
    str_between_quotes[i] = '\0'; // 字符串结尾
    strcpy(name,str_between_quotes);
    
    // 跳过引号后的空白字符,读取剩余参数
    while (*p == ' ' || *p == '\t') p++;
    // 校验参数读取是否成功
    if (sscanf(p, "%d %f %f %f", &capacity, &cost15, &cost15_after1hour, &max_daily_cost) != 4) {
        printf("Error: missing or invalid parameters.\n");
        continue;
    }
} else {
    // 校验单名称场景的参数读取
    if (sscanf(str, "%s %d %f %f %f", name, &capacity, &cost15, &cost15_after1hour, &max_daily_cost) != 5) {
        printf("Error: missing or invalid parameters.\n");
        continue;
    }
}

同时在main函数开头初始化所有数值变量,避免垃圾值干扰:

int capacity = 0;
float cost15 = 0.0f, cost15_after1hour = 0.0f, max_daily_cost = 0.0f;

代码优化建议

  1. 移除全局变量:将parkingLots和num_parkingLots改为main局部变量,通过指针传递给函数,提升代码模块化程度;
  2. 增强参数校验:通过sscanf返回值判断是否成功读取足够参数,避免非法输入;
  3. 提升输入健壮性:使用strtok_r(线程安全分割函数)或逐字符解析替代现有逻辑,处理更复杂的输入场景;
  4. 防止缓冲区溢出:用strncpy替代strcpy,限制复制长度(如strncpy(name, str_between_quotes, sizeof(name)-1); name[sizeof(name)-1] = '\0';);
  5. 标准化错误提示:定义统一的错误信息格式,帮助用户快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:55:55