代码(粘贴在下面)应该读取输入文件,然后将数据解析到结构中的适当位置。
如果正在读取的文件没有空格,则可以正确读取数据。但是一旦数据有空白行,那么文件就会陷入无限循环。
我一直在阅读有关跳过空白行/空行的信息。
我尝试使用"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 :(得分: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;
}
应该注意的是,如果你使用空格来标记你的行,你就不必再检查它们了(使用上面的方法)。
答案 1 :(得分:0)
不是你的问题的答案,这也不会导致你的代码行为不端(至少在你的测试用例中),但是你最后两次strncasecmp调用中的字节数参数是错误的。
答案 2 :(得分:0)
您看到无限循环的第一个原因是因为您没有读过文件中的第一行(双引号字符)。这是因为你这样做:
infile.getline (buffer,81);
while (!infile.eof ())
{
if (strncasecmp (buffer, "<student>",9)==0)
{
...
}
}
在第一个getline调用之后,双引号被读入缓冲区,然后你不会读取任何其他内容并保持无限循环,因为你希望在文件中的其他所有内容之前读取“”标记。在while循环中移动getline调用。这将允许您逐行读取您的文件。
即使经过此更正,此处还有其他问题,在将缓冲区内容保存到学生数据之前,您不会从“缓冲区”中删除标记/特殊字符。例如,您的一个学生记录的“最后”设置为“”。我假设你只想要“约翰逊”。当您阅读“”时出现问题,您的“record.mi”只是一个带有一个char的数组(为什么是数组?),但此条目的缓冲区为3个字符,此时您的strcpy失败。
为什么不使用C ++ xml解析库?有关建议,请参阅this。