2012-12-06 97 views
0

爲什麼此文件始終包含一個額外的Fraction結構?如果用戶在程序剛啓動時輸入選項3以查看所有分數(文件應爲空),則打印出0/0。如果用戶選擇選項1並輸入分數1/1,然後選擇選項3,則打印出兩個分數1/1 1/1讀取和寫入.dat文件

注意:要運行這個你需要創建一個空.dat文件名爲"fractions.dat"

我真的很感謝你的幫助!

#include <iostream> 
#include <fstream> 

using namespace std; 

struct Fraction 
{ 
    int num, den; 
}; 

int search(fstream& file, Fraction* f); 
int menu(); 
void proccessChoice(int i); 
Fraction* readFrac(); 

Fraction* fracs[100]; 
int index; 
string fileName = "fractions.dat"; 
fstream file(fileName, ios::in | ios::out | ios::binary | ios::trunc); 

//structure called Fraction with num and den as its only integer members 
int main() 
{ 
    if (!file) 
    { 
     cout << "Error opening file. Program aborting.\n"; 
     system("pause"); 
     exit(1); 
    } 
    int choice; 
    do 
    { 
     choice = menu(); 
     proccessChoice(choice); 
    } while(choice != 4); 


    system("pause"); 
    return 0; 
} 



int menu() 
{ 
    int c; 
    cout << "1.Enter new fraction" << endl; 
    cout << "2.Display/update a fraction" << endl; 
    cout << "3.Display all fractions" << endl; 
    cout << "4.Quit" << endl; 
    cin >> c; 
    return c; 
} 

void proccessChoice(int i) 
{ 
    switch(i) 
    { 
    case 1: 
     { 
      cout << "Enter a fraction to add: "; 
      fracs[index] = readFrac(); 
      file.seekp(0, ios::end); 
      file.write(reinterpret_cast<char*>(fracs[index]), sizeof(Fraction)); 
      /*cout << fracs[index]->num << "/" << fracs[index]->den ;*/ 
      index++; 
     } 
      break; 
    case 2: 
     { 
      cout << "Enter fraction to view/update: "; 
      Fraction* fToFind = readFrac(); 
      int i = search(file, fToFind); 
      if (i == -1) 
      { 
       cout << "Fraction not found." << endl; 
      } 
      else 
      { 
       char r; 
       cout << fToFind->num << "/" << fToFind->den << " found at index " << i << ". Update? [y/n]"; 
       cin >> r; 
       if(r == 'y' || r == 'Y') 
       { 
        cout << "Enter a new fraction: "; 
        Fraction* fToWrite = readFrac(); 
        file.seekp(sizeof(Fraction) * (i)); 
        file.write(reinterpret_cast<char*>(fToWrite), sizeof(Fraction)); 
       } 
      } 
      cout << i << endl; 
      cout << "Case 2" << endl; 
     } 
      break; 
    case 3: 
     { 
      Fraction* cur = new Fraction(); 
      //int pos = -1; 
      if (!file) 
      { 
       cout << "Error opening file. Program aborting.\n"; 
       system("pause"); 
       exit(1); 
      } 
      file.seekg(0, ios::beg); 
      while(!file.eof()) 
      { 
       file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)); 
       cout << cur->num << "/" << cur->den << endl; 
      } 
        cout << "Case 3" << endl; 
     } 
      break; 
    } 
} 

int search(fstream& file, Fraction* f) 
{ 
    Fraction* cur = new Fraction(); 
    int pos = -1; 
    if (!file) 
    { 
     cout << "Error opening file. Program aborting.\n"; 
     system("pause"); 
     exit(1); 
    } 
    file.seekg(0, ios::beg); 
    while(!file.eof()) 
    { 
     file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)); 
     if((cur->num == f->num) && (cur->den == f->den)) 
     { 
      cout << "\nFrac found!" << cur->num << "/" << cur->den<<endl; 
      pos = file.tellg()/sizeof(Fraction) - 1; 
      return pos; 
     } 
    } 
    return pos; 
} 

Fraction* readFrac() 
{ 
    Fraction* f = new Fraction(); 
    char slash; 
    cin >> f->num >> slash >> f->den; 
    return f; 
} 

嘗試的解決方案1:適用於該用戶的第一次嘗試,以查看所有級分,但在第二次嘗試中沒有找到該文件。

case 3: 
     { 
      Fraction* cur = new Fraction(); 
      //int pos = -1; 
      if (!file) 
      { 
       cout << "Error opening file. Program aborting.\n"; 
       system("pause"); 
       exit(1); 
      } 
      file.seekg(0, ios::beg); 
      while(!file.eof()) 
      { 
       if(file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)).gcount()== sizeof(Fraction)) 
       { 
        cout << cur->num << "/" << cur->den << endl; 
       } 
      } 
        cout << "Case 3" << endl; 
     } 
      break; 
    } 

回答

1

因爲你還沒有達到文件的末尾!

while(!file.eof()) 

您打開了空文件,但請注意,讀取光標當前位置爲0。只要你沒有試圖讀取數據file.eof()將是錯誤的,因爲文件的末尾還沒有被光標達到。

你需要檢查是否實際上能夠提取分數:

if(
    file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)).gcount() 
    == sizeof(Fraction) 
){ 
    // Fraction has been extracted 
} 
else 
    // either eof() or some other error. 

注意,這變得更簡單,如果你提供了這樣的運營商定製:

std::istream& operator>>(std:istream& in, Fraction& f){ 
    return in.read(reinterpret_cast<char *>(&f), sizeof(Fraction)); 
} 

// .... 
while(file >> *cur){ 
    // ... your code. 
} 
+0

我嘗試你的第一個建議。它適用於選項3的第一次執行,但如果用戶再次選擇選項3,則找不到文件(請參閱問題更新)。 – Zzz

+0

第二個解決方案給出了以下錯誤:錯誤錯誤C2678:二進制'>>':找不到操作符找到類型'std :: fstream'的左側操作數(或沒有可接受的轉換) – Zzz

+0

@阿齊:呃,這個文件已經找到了。但是,它處於不良狀態,這會將'!file'評估爲true。如果你想知道文件是否打開,你應該使用'.is_open()'。請記住,您需要使用'.clear()'來清除舊的錯誤狀態。 – Zeta