2013-11-21 22 views
2

我想從冒號分隔文件中提取信息到類對象中。文件的每一行都以相同的格式設置。下面是該文件的前幾行:從冒號分隔文件提取信息 - C++

s:Charles:Babbage:80:530213286:1133764834:mechanical engineering:3.8 
e:Marissa:Meyer:37:549114177:53321:ceo:4456000 
s:Alonzo:Church:92:586312110:1100539644:mathematics:4.0 
e:Dana:Ulery:74:573811211:23451:engineer:124569 

這是一個學校項目,目的是教給我們的類繼承。我們有一個基類Person和兩個子類Student和Employee。我們應該將學生的信息導入並存儲到Employee對象和Student對象中。我有一個每個類的對象數組;我將學生排序爲Student對象數組,同樣適用於員工,並將所有人添加到People對象數組中。

我不知道該怎麼做才能用分隔符來獲取每條信息。現在我正在嘗試使用.getline,但它似乎沒有工作。如何使用此函數(或其他函數)將分隔符之間的信息提取到char數組中?這裏是我到目前爲止的數據是針對僱員的情況:

ifstream fin; 
char* tempImport; 
tempImport = new char[50]; 
int* tempIntArray; 
tempIntArray = new int[10]; 
double tempDouble; 
int tempInt; 

    // get the specifier of student or employee 
    fin.getline(tempImport, ':'); 

    if(tempImport[0]=='e'){ 
    // get first name 
    fin.getline(tempImport, ':'); 
    employees[employeeIndex].setFirstName(tempImport); 
    allPeople[personIndex].setFirstName(tempImport); 
    // get last name 
    fin.getline(tempImport, ':'); 
    employees[employeeIndex].setFirstName(tempImport); 
    allPeople[personIndex].setFirstName(tempImport); 
    // get age 
    fin.getline(tempImport, ':'); 
    employees[employeeIndex].setAge(tempImport[0] - 0); 
    allPeople[personIndex].setAge(tempImport[0] - 0); 
    // get SSN 
    fin.getline(tempImport, ':'); 
    for(int i=0;i<9;i++){ 
     tempIntArray[i] = tempImport[i] - 0; 
     } 
    employees[employeeIndex].setSsn(tempIntArray); 
    allPeople[personIndex].setSsn(tempIntArray); 
    // get Employee ID 
    fin.getline(tempImport, ':'); 
    for(int i=0;i<5;i++){ 
     tempIntArray[i] = tempImport[i] - 0; 
     } 
    employees[employeeIndex].setEmpID(tempIntArray); 
    // get title 
    fin.getline(tempImport, ':'); 
    employees[employeeIndex].setTitle(tempImport); 
    // get salary 
    fin >> tempDouble; 
    employees[employeeIndex].setSalary(tempInt); 
    employeeIndex++; 
    personIndex++; 
    } 
+0

當您使用調試程序逐步完成程序時發生了什麼? –

+2

請使用''0''而不是48。許多人沒有意識到48是字符零的ASCII代碼的十進制值。 –

+0

爲什麼使用'new'運算符和動態內存?這是C++,而不是Java。絕對必要時只使用動態內存。研究「內存泄漏C++」以獲得關於雙面效應的更多信息。 –

回答

2

它看起來像你缺少一個參數當你調用ifstream::getline()。請參閱: http://www.cplusplus.com/reference/istream/istream/getline/

您需要方法的3參數版本才能指定分隔符。當您調用2參數版本時,它將':'解釋爲streamsize。 (基本上,':'只是解析爲一個冒號的ASCII碼,所以這個數字就被傳入了。你真正想要的streamsize是你的tempImport緩衝區的長度。)

但是,如果我可能會建議(和你的任務允許它),該功能的版本可能會更好。(它允許你使用std::string而不是char*,這是一種更加C++的方式,你也不必擔心輸入是否大於你的緩衝區。)下面是關於這個的文檔: http://www.cplusplus.com/reference/string/string/getline/

所以基本上你可以做這樣的事情:

std::string tempImport; 
std::getline(fin, tempImport, ':'); 

隨着調試的建議,你可以在每次打印後,您tempImport調用它函數getline()(不管你使用哪一種)。在提交之前將其取出,但這些打印語句可以幫助您在此期間調試解析。

std::stderr << "getline(): " << tempImport << std::endl; 

編輯:

對於下面的評論,我能得到這個編譯。 (它沒有做任何有用的事情,但顯示std::getline()確實存在並編譯。)它是否爲您編譯?

#include <fstream> 

int main (int argc, char** argv) 
{ 
     std::ifstream ifs; 
     std::string str; 
     std::getline(ifs, str, ':'); 
     return 0; 
} 
+0

當我嘗試這種方式時,它告訴我std :: getline沒有匹配的函數。我該如何解決? – Bobazonski

+1

我在上面的答案的末尾放了一段代碼片段。它使用'std :: getline()'併爲我編譯正確。看看它是否適合你...(我把它放在上面,因爲多行代碼片段在註釋中不起作用。):( –

+0

感謝您的幫助,Dave。編譯了代碼,我發現我的問題是tempImport是一個char *。是否有任何方法使用帶指針的getline函數? – Bobazonski

2

如果你會原諒我這麼說,你似乎已經被教導「面向對象編程的最糟糕的仿製品之一'(儘管如果它有任何的安慰,這也是一個相當普遍的)。

就我個人而言,我覺得我寫的東西有點不同。

我可能會開始消除所有的setSalary,setTitle等。它們是OOP應該做的一個可怕的變態,在可讀性上失去了很多,而在封裝中沒有獲得任何東西。

與其提供用於操作類的所有成員的成員函數,類應提供更高級別的成員以從流中重構其自身的實例。

當你得到的數據,你可能做而不是想要爲您的人員/員工/學生陣列創建單獨的對象。相反,每個項目將進入僱員或學生陣列。然後People將只是一個指向其他兩個數組中項目的指針數組。

至於讀取數據的細節:我個人可能會寫一個ctype類,將:分類爲空白,然後只讀取數據。對於你的班級,你可能想堅持使用getline

class Person { 
    virtual std::istream &read(std::istream &is); 

    friend std::istream &operator>>(std::istream &is, Person &p) { 
     return p.read(is); 
    } 
}; 

class Student : public Person { 
    std::string first_name; 
    std::string last_name; 
    std::string age; 
    std::string ssn; 
    std::string ID; 
    std::string title; 
    std::string salary; 

    virtual std::istream &read(std::istream &is) { 
     std::getline(is, first_name, ':'); 
     std::getline(is, last_name, ':'); 
     std::getline(is, age, ':'); 
     // ... 
     return is; 
    } 
}; 

通過這些適當的,從文件中讀取數據,通常會是非常簡單:

std::string t; 
Employee e; 
Student s; 

while (std::getline(infile, t, ':')) 
    if (t == "e") { 
     infile >> e; 
     Employees.push_back(e); 
    } 
    else if (t =="s") { 
     infile >> s; 
     Students.push_back(s); 
    }