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
相关产品推荐
相关产品推荐

