2014-02-16 65 views
1

代碼(粘貼在下面)應該讀取輸入文件,然後將數據解析到結構中的適當位置。用get.line跳過空行

如果正在讀取的文件沒有空格,則正確讀取數據。但是一旦數據有空行,文件就會陷入無限循環。

我一直在閱讀關於跳空行/空行。

我試着用"if (buffer[0] == '\n')"然後再讀一行。但它根本不工作!

是否有人知道將允許的代碼(如果有多個空白行,我正在使用while循環。)我跳過空行並允許代碼解析所有數據。

的文件中讀取應該是這樣的

" 
<student> 
<first> 
1FRED 
</first> 
<mi> 
J 

</mi> 
<last> 
JOHNSON 

</last> 
<ssn>  
123456788 
</ssn>  

</student> 
<STUDENT> 

<FIRST> 
2SUSIE 
</FIRST> 
<MI> 
Q 
</MI> 
<LAST> 
WATSON 
</LAST> 
<SSN> 
234567899 
</SSN> 
</STUDENT> 
" 

下面的代碼:

#include <iostream> 
#include <cstdlib> 
#include <fstream> 
#include <stdio.h> 
#include <cstring> 
#include <strings.h> 

using namespace std; 

struct record 
{ 
char first [20]; 
char mi [1]; 
char last [20]; 
int ssn; 
}; 

void filename (char ifname [], struct record *student[]); 
void structfill (fstream & infile, struct record *student[]); 

int main() 
{ 

system ("clear"); 

fstream infile; 
char ifname [256]; 
struct record * student [50]; 
filename (ifname, student); 

return 0; 
} 
/*******************************************************************/ 
void filename (char ifname [],record *student []) 
{ 
fstream infile; 
cout << "Enter name of file to read from: "; 
cin.getline (ifname, 256); 
cout << endl; 
infile.open (ifname); 
    if (!infile.is_open()) 
    { 
    cerr << "FILELOOP!: Unable to open input file " << ifname 
     << endl; 
    exit (1); 
    } 
structfill (infile, student); 
} 
/*******************************************************************/ 
void structfill (fstream & infile, record *student []) 
{ 
char buffer [81]; 
int buffernumber [81]; 
int n=0; 
int f=0; 

infile.getline (buffer,81); 
while (!infile.eof()) 
{ 

if (strncasecmp (buffer, "<student>",9)==0) 
{ 

student[n] = new record; 
while ((strncasecmp (buffer, "</student>",10) != 0)) 
{ 
     infile.getline (buffer, 81); 
    if (strncasecmp (buffer, "<first>",7)==0) 
     { 
     infile.getline (buffer, 81); 
     if (buffer[0] == '\n') 
     { 
     infile.getline (buffer, 81); 
     cout << "-----"; 
     } 
     strcpy (student[n]->first, buffer); 
     } 
    if (strncasecmp (buffer, "<mi>",4)==0) 
     { 
     infile.getline (buffer,81); 
     if (buffer[0] == '\n') 
     infile.getline (buffer, 81); 
     strcpy (student[n]->mi, buffer); 
     } 
    if (strncasecmp (buffer, "<last>",4)==0) 
     { 
     infile.getline (buffer, 81); 
     if (buffer[0] == '\n') 
     infile.getline (buffer, 81); 
     strcpy (student[n]->last, buffer); 
     } 
    if (strncasecmp (buffer, "<ssn>",4)==0) 
     { 
     infile.getline (buffer, 81); 
     if (buffer[0] == '\n') 
     infile.getline (buffer, 81); 
     } 
} n++; 
infile.getline (buffer,81); 
} 
} 
for (int a =0; a < n; a++){ 
cout << student[a]->first << " " << student[a]->mi << " " << student[a]->last << a << endl; 
} 
} 
+0

嘗試檢查字符串是否爲空,即'strlen(s)== 0' – user1520427

+0

我試過了,它仍然會進入無限循環。 – user3304639

回答

0

不回答你的問題,這也不是造成你的代碼無法正常運作(至少你測試用例),但最近兩次strncasecmp調用中的參數字節數是錯誤的。

1

爲什麼不用std::getline代替?

如果您嘗試跳過空格,那麼您可以使用這些流來獲得您的好處,因爲默認情況下,流將跳過空格。

例子:

string filename = "students.txt"; 
ifstream ifile(filename.c_str()); 

string temp; 
//tokenize the file by newlines (getline reads up to newlines by default) 
//so this way, it'll read and store data up to a newline each time 
while(getline(ifile, temp)) { 
    //at this point you can use another stream (i.e. a stringstream) 
    //to perform other manipulations on the tokenized data. 
    //example: read a number of characters using the getline method 
    //of the stream: e.g.: `cin.getline()` 
    //In my example, I am tokenizing each line by whitespace and outputting 
    //the tokens: 
    istringstream iss(temp); 
    while(iss >> temp) { 
     cout << temp << " "; 
    } 
    if (!temp.empty()) 
     cout << endl; 
} 

應當注意的是,如果你用空白來標記你行,你不再需要檢查他們(使用上述方法)。

+0

我不太瞭解你的代碼。仍在學習。 – user3304639

+0

@ user3304639:你不明白?請你詳細說明一下嗎? – jrd1

+0

我沒有學過刺痛類。我一直使用strtok來標記過去的行。我沒有看到你的代碼的哪部分是標記行? – user3304639

0

爲什麼你看到一個無限循環的第一個原因是因爲你沒有越過你的文件的第一行(雙引號字符)。這是因爲你這樣做:

infile.getline (buffer,81); 
while (!infile.eof()) 
{ 

    if (strncasecmp (buffer, "<student>",9)==0) 
    { 
     ... 
    } 
} 

雙引號獲得的第一個函數getline調用後讀入緩衝區,然後你不看別的,並保持停留在一個無限循環,因爲你期待閱讀「」在文件中的其他所有內容之前標記。在while循環中移動getline調用。這將允許您逐行讀取您的文件。

即使在修正之後,這裏還有其他的錯誤,在將緩衝區的內容保存在學生數據中之前,您並沒有從「緩衝區」中去除標籤/特殊字符。例如,你的一個學生記錄的「最後」設置爲「」。我假設你只是想要「JOHNSON」。當你閱讀「」時,你的「record.mi」只是一個帶有一個char的數組(爲什麼是數組?),但是你的緩衝區是3個字符,你的strcpy在這個時候失敗了。

爲什麼不使用C++ xml解析庫?有關建議請參閱this