用get.line跳过空行

时间:2014-02-16 04:06:01

标签: c++

代码(粘贴在下面)应该读取输入文件,然后将数据解析到结构中的适当位置。

如果正在读取的文件没有空格,则可以正确读取数据。但是一旦数据有空白行,那么文件就会陷入无限循环。

我一直在阅读有关跳过空白行/空行的信息。

我尝试使用"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;
}
}

3 个答案:

答案 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