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

C++统计文件行数并添加带当前序号新行时文件损坏报错的问题求助

问题分析与修复方案

首先,你遇到的"文件损坏"提示大概率是文件打开失败导致的,而非文件真的损坏。我们来一步步拆解代码里的问题并修复:

1. 核心问题:文件打开模式错误(导致行数统计失效+打开失败)

在DodajAso()函数中,你用ios::in|ios::out|ios::app打开文件:

  • ios::app会强制把文件指针放在末尾,所以后续的getline(plik, linia)根本读不到任何内容,numer始终为0,无法正确统计已有行数。
  • 如果文件不存在,ios::in会导致open()直接失败,触发你写的"文件损坏"提示,但实际是文件还没创建。

修复方式:把读取行数和写入新内容的操作分开:

  • 先以ios::in模式打开文件统计行数(如果文件不存在,numer就为0)。
  • 再以ios::app模式打开文件追加新内容(自动创建文件如果不存在)。

修改后的DodajAso()片段:

void DodajAso() {
    int n, numer = 0;
    // 第一步:统计已有行数
    ifstream countFile("Asortymenty.txt");
    if (countFile.good()) {
        string linia;
        while (getline(countFile, linia)) {
            numer++;
        }
        countFile.close();
    }
    // 第二步:写入新内容
    ofstream plik("Asortymenty.txt", ios::app);
    if (!plik.is_open()) {
        cout << "\tNie mozna otworzyc pliku do zapisu!!\n";
        system("pause");
        return;
    }
    cout << "Ile Asortymentow chcesz wprowadzic do bazy: ";
    cin >> n;
    // 替换非标准动态数组为vector(C++标准不支持变量长度数组)
    vector<DaneAso> tab_aso(n);
    for (int i = 0; i < n; i++) {
        cout << "\nWporwadz Kod Asortymentu " << i + 1 << ": ";
        cin >> tab_aso[i].kod;
        cout << "Wprowadz Nazwe Asortymentu " << i + 1 << ": ";
        cin >> tab_aso[i].nazwa;
        cout << "Wprowadz Jednostke miary " << i + 1 << ":";
        cin >> tab_aso[i].jm;
        plik << numer++ << ";" << tab_aso[i].kod << ";" << tab_aso[i].nazwa << ";" << tab_aso[i].jm << ";" << endl;
    }
    plik.close();
    system("pause");
}

2. 非标准语法:变量长度数组(VLA)

DaneAso tab_aso[n];是C语言的特性,不是标准C++的语法,不同编译器可能报错或行为异常。换成vector<DaneAso>来动态创建数组,如上面代码所示。

3. 读取文件的逻辑缺陷(导致显示异常+文件读取错误)

在WyswietlAso()、DodajStan()、WyswietlStan()中,你用逐个字符读取+手动处理分隔符的方式非常容易出错,比如otworz >> litera会自动跳过空格和换行,导致读取到的内容混乱,看起来像文件损坏。

修复方式:用getline()读取整行,再用stringstream分割字段,代码更简洁可靠:

修改后的WyswietlAso():

void WyswietlAso(const string& fileName) {
    ifstream otworz(fileName);
    if (!otworz.is_open()) {
        cout << "\tNie mozna otworzyc pliku!!\n";
        system("pause");
        return;
    }
    cout << left << setw(6) << "Numer" << setw(12) << "Kod" << setw(30) << "Nazwa" << "Jednostka Miary" << endl;
    cout << string(60, '-') << endl;
    string linia;
    while (getline(otworz, linia)) {
        stringstream ss(linia);
        string numer, kod, nazwa, jm;
        // 用分号分割字段
        getline(ss, numer, ';');
        getline(ss, kod, ';');
        getline(ss, nazwa, ';');
        getline(ss, jm, ';');
        // 格式化输出,对齐更美观
        cout << left << setw(6) << numer << setw(12) << kod << setw(30) << nazwa << jm << endl;
    }
    otworz.close();
    cout << endl << endl;
    system("pause");
}

注意:需要添加头文件#include <sstream>和#include <iomanip>来支持stringstream和setw格式化。

4. 其他小问题

  • DodajStan()函数目前是空实现,你可以参考上面的读取和写入逻辑来完成:先读取Asortymenty.txt的内容让用户选择,然后将选中的条目编号和数量写入stany.txt。
  • ZdejmijStan()同样需要补充实现,逻辑类似DodajStan,但要处理库存减少的逻辑。
  • 主函数中string wybor;改成int wybor;更合理,因为用户输入的是数字选项,避免字符串比较的问题。

完整修改后的代码框架

(整合以上修复点,补充必要头文件)

#include <iostream>
#include <fstream>
#include <windows.h>
#include <conio.h>
#include <vector>
#include <string>
#include <sstream>
#include <iomanip> // 用于格式化输出
using namespace std;

struct DaneAso {
    char kod[10];
    char nazwa[50];
    char jm[3];
};

struct Stany {
    char ilosc[10];
};

void menu() {
    cout<<"\t\t\tMENU GLOWNE\n\n\n";
    cout<<"\t\t1. Wprowadz Asortyment do systemu\n";
    cout<<"\t\t2. Wyswietl baze Asortymentow\n";
    cout<<"\t\t3. Wstaw Towar na magazyn\n";
    cout<<"\t\t4. Wydaj Towar z magazynu\n";
    cout<<"\t\t5. Obecne stany magazynowe\n";
    cout<<"\t\t6. Wyjdz\n";
}

void DodajAso() {
    int n, numer = 0;
    // 统计已有行数
    ifstream countFile("Asortymenty.txt");
    if (countFile.good()) {
        string linia;
        while (getline(countFile, linia)) {
            numer++;
        }
        countFile.close();
    }
    // 写入新内容
    ofstream plik("Asortymenty.txt", ios::app);
    if (!plik.is_open()) {
        cout << "\tNie mozna otworzyc pliku do zapisu!!\n";
        system("pause");
        return;
    }
    cout << "Ile Asortymentow chcesz wprowadzic do bazy: ";
    cin >> n;
    vector<DaneAso> tab_aso(n);
    for (int i = 0; i < n; i++) {
        cout << "\nWporwadz Kod Asortymentu " << i + 1 << ": ";
        cin >> tab_aso[i].kod;
        cout << "Wprowadz Nazwe Asortymentu " << i + 1 << ": ";
        cin >> tab_aso[i].nazwa;
        cout << "Wprowadz Jednostke miary " << i + 1 << ":";
        cin >> tab_aso[i].jm;
        plik << numer++ << ";" << tab_aso[i].kod << ";" << tab_aso[i].nazwa << ";" << tab_aso[i].jm << ";" << endl;
    }
    plik.close();
    system("pause");
}

void WyswietlAso(const string& fileName) {
    ifstream otworz(fileName);
    if (!otworz.is_open()) {
        cout << "\tNie mozna otworzyc pliku!!\n";
        system("pause");
        return;
    }
    cout << left << setw(6) << "Numer" << setw(12) << "Kod" << setw(30) << "Nazwa" << "Jednostka Miary" << endl;
    cout << string(60, '-') << endl;
    string linia;
    while (getline(otworz, linia)) {
        stringstream ss(linia);
        string numer, kod, nazwa, jm;
        getline(ss, numer, ';');
        getline(ss, kod, ';');
        getline(ss, nazwa, ';');
        getline(ss, jm, ';');
        cout << left << setw(6) << numer << setw(12) << kod << setw(30) << nazwa << jm << endl;
    }
    otworz.close();
    cout << endl << endl;
    system("pause");
}

void DodajStan(const string& asortymentFile, const string& stanyFile) {
    // 先显示现有库存
    WyswietlAso(asortymentFile);
    cout << "\nWybierz numer asortymentu do dodania na magazyn: ";
    int selectedNum;
    cin >> selectedNum;
    // 读取选中的条目信息(可选,也可以直接写入编号和数量)
    ifstream asortFile(asortymentFile);
    string linia;
    bool found = false;
    while (getline(asortFile, linia)) {
        stringstream ss(linia);
        string numer;
        getline(ss, numer, ';');
        if (stoi(numer) == selectedNum) {
            found = true;
            break;
        }
    }
    asortFile.close();
    if (!found) {
        cout << "\tNie znaleziono takiego asortymentu!!\n";
        system("pause");
        return;
    }
    // 写入数量到stany.txt
    string ilosc;
    cout << "Wprowadz ilosc do dodania: ";
    cin >> ilosc;
    ofstream stanyPlik(stanyFile, ios::app);
    if (!stanyPlik.is_open()) {
        cout << "\tNie mozna otworzyc pliku stanow!!\n";
        system("pause");
        return;
    }
    stanyPlik << selectedNum << ";" << ilosc << ";" << endl;
    stanyPlik.close();
    cout << "\tIlosc dodana pomyslnie!!\n";
    system("pause");
}

void ZdejmijStan() {
    // 类似DodajStan的逻辑,处理库存减少
    cout << "\tFunkcja w budowie!!\n";
    system("pause");
}

void WyswietlStan(const string& fileName) {
    ifstream otworz(fileName);
    if (!otworz.is_open()) {
        cout << "\tNie mozna otworzyc pliku stanow!!\n";
        system("pause");
        return;
    }
    cout << left << setw(6) << "Numer" << "Ilosc" << endl;
    cout << string(15, '-') << endl;
    string linia;
    while (getline(otworz, linia)) {
        stringstream ss(linia);
        string numer, ilosc;
        getline(ss, numer, ';');
        getline(ss, ilosc, ';');
        cout << left << setw(6) << numer << ilosc << endl;
    }
    otworz.close();
    cout << endl << endl;
    system("pause");
}

int main() {
    SetConsoleTitleA("Ksiega Inwentarzowa");
    int wybor; // 改成int更合理
    bool running = true;
    while(running) {
        cout<<"Program wspomagajacy zarzadzanie ksiega inwentarzowa\n\n\n";
        menu();
        cout<<"\n\n\tWybierz co chcesz zrobic: ";
        cin>>wybor;
        if(wybor == 6) {
            cout<<"\n\n\tDziekuje za korzystanie z programu\n\n";
            system("pause");
            return 0;
        } else if(wybor == 1) {
            DodajAso();
        } else if(wybor == 2) {
            WyswietlAso("Asortymenty.txt");
        } else if(wybor == 3) {
            DodajStan("Asortymenty.txt", "stany.txt");
        } else if(wybor == 4) {
            ZdejmijStan();
        } else if(wybor == 5) {
            WyswietlStan("stany.txt");
        } else {
            cout<<"\tWybrales zla opcje, wcisnij poprawny przycisk\n\n";
            system("pause");
        }
        system("cls");
    }
    return 0;
}

这些修改应该能解决你遇到的文件损坏提示问题,同时让代码更符合C++标准,逻辑更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 12:32:38