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

为何有效数据错误输出至switch分支?C++汽车程序问题排查

问题:有效汽车记录错误归类到无效分支

我的有效数据(Records.txt)持续被错误输出至无效case分支。当按下1时,仅显示1条有效记录,另外两条有效记录被放到InvalidRecords中。

Records.txt内容

AB12MP349 Fusion5 20 17000.00
33435KMOP324 BMW 40 25000.00
AB12MP349 Audi 100 4000.00
AB12MP349 Pagni 1 2000000.00

程序错误输出

./test

Welcome to  Car Database Lookup
----------------------------------------
Press 1 to display a table of valid car records: 
Press 2 to display a table full of InvalidRecords: 
Type here: 1
            Car ID               Model           Quantity           Price

            AB12MP349            Fusion5                20           17000              
Press 2 to display a table full of InvalidRecords: 
Type here: 2
Invalid car IDs:
33435KMOP324
BMW
40
25000.00
AB12MP349
Audi
100
4000.00
AB12MP349
Pagni
1
2000000.00

原始代码

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <vector>
#include <cctype>
using namespace std;

// Class to store information about cars
class CarData {
public:
    string CarID;
    string Model;
    int Quantity;
    double Price;

    // Constructor to initialize CarData class(Parameters)
    CarData(const string &carID, const string &model, int quantity, double price)
        : CarID(carID), Model(model), Quantity(quantity), Price(price) {}
};

// Function prototypes
bool dataValidation(char d);
bool IsValidCarID(const string &carID);
bool DataCarPrice(double price);
void TakeCarData(vector<CarData> &carInfo, vector<string> &invalidCarIDs);

int main() {
    // Menu for User
    enum uiforUser {
        DISPLAY_CARINFO = 1,
        DISPLAY_ERROR = 2,
    };

    int userInput;

    cout << "\nWelcome to Pierce Car Database Lookup\n";
    cout << setfill('-');
    cout << setw(40) << "-" << endl;
    cout << "Press " << DISPLAY_CARINFO << " to display a table of valid car records: ";
    cout << endl;
    cout << "Press " << DISPLAY_ERROR << " to display a table full of Invalid Records: ";
    cout << "\nType here: ";
    cin >> userInput;

    // Used a Vector because it can hold many values and etc(Sequence Container !)
    vector<string> invalidCarIDs;
    vector<CarData> carInfo;

    switch (userInput) {
        // Menu To display Valid Records
        case DISPLAY_CARINFO: {
            TakeCarData(carInfo, invalidCarIDs);  // Getting Parameters from Function(TakeCarData)

            // Output for valid Records
            cout << setfill(' ');
            cout << setw(27) << "Car ID";
            cout << setw(20) << "Model";
            cout << setw(19) << "Quantity";
            cout << setw(16) << "Price";
            cout << endl << endl;

            // for loop that uses a pointer(Record), this allows me to access the data from carInfo!
            for (const CarData &Record : carInfo) {
                cout << setw(29) << Record.CarID;
                cout << setw(19) << Record.Model;
                cout << setw(18) << Record.Quantity;
                cout << setw(16) << Record.Price;
                cout << endl;
            }
        }
        break;

        // Menu to display Record Errors
        case DISPLAY_ERROR: {
            TakeCarData(carInfo, invalidCarIDs);  // Grabbing Parameters from Function below
            cout << "Invalid car IDs:" << endl;

            // for loop that uses a pointer(invalidID), this is allows me to access to data Validation Function
            for (const string &invalidID : invalidCarIDs) {
                cout << invalidID << endl;
            }
        }
        break;
    }

    return 0;
}

// DataValidation Logic !
bool dataValidation(char d) {
    // Checks if a character's range from A-Z, also checks for "O"
    return (d >= 'A' && d <= 'Z' && d != 'O');
}

bool DataCarPrice(double &price) {
    if (price <= 5000) {
        cout << "test";
    }
    return false;
}

bool IsValidCarID(const string &carID) {
    // checks length of CarID(9 characters long)
    if (carID.length() != 9) {
        return false;
    }

    if (!dataValidation(carID[0]) || !dataValidation(carID[1])) {
        return false;
    }

    for (int i = 2; i < 6; ++i) {
        // isalnum is used because it can check if a value is alphanumeric
        if (!isalnum(carID[i]) || carID[i] == 'O') {
            return false;
        }
    }

    for (int i = 3; i < 6; ++i) {
        if (!isdigit(carID[i])) {
            return false;
        }
    }

    return true;
}

void TakeCarData(vector<CarData> &carInfo, vector<string> &invalidCarIDs) {
    ifstream RecordFile;
    RecordFile.open("Records.txt");

    if (!RecordFile) {
        cout << "File not found. Please check the file path." << endl;
        system("pause");
        exit(EXIT_FAILURE);
    }

    // Read data from the file and add it to the vector
    string carID, model;
    int quantity;
    double price;

    while (RecordFile >> carID >> model >> quantity >> price) {
        carInfo.emplace_back(carID, model, quantity, price);  // Add car data to the vector
    }
    while (RecordFile >> carID) {
        invalidCarIDs.emplace_back(carID);
    }

    RecordFile.close();

    // Open an output file (if needed)
    ofstream DataBase;
    DataBase.open("Output.txt");
    if (!DataBase) {
        cout << "Output file not found. Please check the file path." << endl;
        system("pause");
        exit(EXIT_FAILURE);
    }

    // Close files when done
    DataBase.close();
}

问题原因

  1. 未执行验证逻辑:TakeCarData函数完全没有调用IsValidCarID判断CarID合法性,仅通过是否能读取四个字段来区分有效/无效记录,逻辑完全错误。
  2. IsValidCarID规则错误:对CarID的格式验证逻辑矛盾,导致合法的CarID会被误判为无效。
  3. 无效记录收集错误:将读取失败后的所有剩余token单独加入无效列表,而非将整条无效记录的字段作为一组收集。
  4. 重复读取文件:在不同case分支中重复调用TakeCarData,导致文件读取状态异常。

修复方案

1. 修正IsValidCarID验证逻辑

根据示例中合法CarID(AB12MP349)的格式,调整验证规则为:

  • 总长度9位
  • 前两位:大写字母(不含O)
  • 第3-4位:数字
  • 第5-6位:大写字母(不含O)
  • 最后三位:数字
bool IsValidCarID(const string &carID) {
    if (carID.length() != 9) {
        return false;
    }

    // 验证前两位:大写字母,不含O
    if (!dataValidation(carID[0]) || !dataValidation(carID[1])) {
        return false;
    }

    // 验证第3-4位:数字
    for (int i = 2; i < 4; ++i) {
        if (!isdigit(carID[i])) {
            return false;
        }
    }

    // 验证第5-6位:大写字母,不含O
    for (int i = 4; i < 6; ++i) {
        if (!dataValidation(carID[i])) {
            return false;
        }
    }

    // 验证最后三位:数字
    for (int i = 6; i < 9; ++i) {
        if (!isdigit(carID[i])) {
            return false;
        }
    }

    return true;
}

2. 重构TakeCarData函数

读取每条记录后先验证CarID,合法则加入有效列表,否则将整条记录的所有字段加入无效列表:

void TakeCarData(vector<CarData> &carInfo, vector<string> &invalidCarIDs) {
    ifstream RecordFile("Records.txt");
    if (!RecordFile) {
        cerr << "文件未找到,请检查路径。" << endl;
        system("pause");
        exit(EXIT_FAILURE);
    }

    string carID, model;
    int quantity;
    double price;

    // 逐行处理每条记录
    while (RecordFile >> carID >> model >> quantity >> price) {
        if (IsValidCarID(carID)) {
            carInfo.emplace_back(carID, model, quantity, price);
        } else {
            // 将整条无效记录的所有字段加入无效列表
            invalidCarIDs.push_back(carID);
            invalidCarIDs.push_back(model);
            invalidCarIDs.push_back(to_string(quantity));
            invalidCarIDs.push_back(to_string(price));
        }
    }

    RecordFile.close();
}

3. 修正函数参数不匹配问题

将DataCarPrice的定义与声明统一:

bool DataCarPrice(double price) {
    if (price <= 5000) {
        cout << "test";
    }
    return false;
}

4. 调整main函数流程

提前读取所有数据,避免重复打开文件:

int main() {
    enum uiforUser {
        DISPLAY_CARINFO = 1,
        DISPLAY_ERROR = 2,
    };

    int userInput;

    cout << "\nWelcome to Pierce Car Database Lookup\n";
    cout << setfill('-');
    cout << setw(40) << "-" << endl;
    cout << "Press " << DISPLAY_CARINFO << " to display a table of valid car records: " << endl;
    cout << "Press " << DISPLAY_ERROR << " to display a table full of Invalid Records: " << endl;
    cout << "\nType here: ";
    cin >> userInput;

    vector<string> invalidCarIDs;
    vector<CarData> carInfo;

    // 提前读取并处理所有数据
    TakeCarData(carInfo, invalidCarIDs);

    switch (userInput) {
        case DISPLAY_CARINFO: {
            cout << setfill(' ');
            cout << setw(27) << "Car ID";
            cout << setw(20) << "Model";
            cout << setw(19) << "Quantity";
            cout << setw(16) << "Price";
            cout << endl << endl;

            for (const CarData &Record : carInfo) {
                cout << setw(29) << Record.CarID;
                cout << setw(19) << Record.Model;
                cout << setw(18) << Record.Quantity;
                cout << setw(16) << Record.Price;
                cout << endl;
            }
        }
        break;

        case DISPLAY_ERROR: {
            cout << "Invalid car IDs:" << endl;
            for (const string &invalidID : invalidCarIDs) {
                cout << invalidID << endl;
            }
        }
        break;

        default:
            cout << "无效输入,请输入1或2。" << endl;
    }

    return 0;
}

修复后效果

  • 按下1时,显示所有CarID合法的3条记录
  • 按下2时,仅显示无效的那条记录的所有字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:42:03