Reading a file in segments

Hi Everybody,

I wish if somebody could help me in reading a file part by part.
I am enclosing a sample file below. Actually my file contains some 7000 lines and each part is separated by a comment line. I wanted to know how to process each segment separately but add the calculation obtained from each segment into one.

For example,

Input file:

!Comment
U 2.0 4.5 4.0
O 3.4 4.5 -1.9
U 5.6 4.5 2.9
Y 8.0 4.5 4.3
K -11.0 4.5 5.7
!Comment
I 6.0 4.5 7.9
U 2.8 4.5 -12.3
G 2.8 4.5 6.1
U -22.0 9.4 8.9

In the first segment between two comment line I wanted to calculate difference between column 2, 3 and 4 where first column is U. Similarly in next segment. The difference obtained from each segment has to be added for further calculation.

Looking forward for help...

Are you interested only in lines where the first column is 'U' ?
Are the other lines to be ignored, or also processed in some way.
Is it important to keep each block of lines separated?
It isn't clear exactly what calculation you want to do with columns 2, 3 and 4.
An example would be useful. Which value or set of values do you want to derive from each block?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    ifstream fin("data.txt");  
    string line; 
    
    while (getline(fin, line) && line.size() )
    {
        if (line[0] == '!')
        {
                            // Add end-of-block processing here
            continue;       // ignore comment line
        }
        
        istringstream ss(line);
        char id;
        double a, b, c;
        
        if ( ss >> id >> a >> b >> c)
        {
            
            if (id == 'U')  // process line type U
            {
                // do something with a, b and c
                cout << setw(3) << id << setw(6) << a << setw(6) << b << setw(6) << c << '\n';
            }            
        }        
        
    }
    
    return 0;
}


Output:
  U     2   4.5     4
  U   5.6   4.5   2.9
  U   2.8   4.5 -12.3
  U   -22   9.4   8.9
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <vector>
#include <sstream>
#include <iomanip>

struct line
{
    double col_1 ;
    double col_2 ;
    double col_3 ;
};

using segment = std::vector<line> ;

bool is_comment( std::string str ) { return !str.empty() && str.front() == '!' ; }

bool get_segment( std::istream& stm, segment& s, char prefix )
{
    s.clear() ;
    std::string line ;
    while( std::getline( stm, line ) && !is_comment(line) )
    {
        std::istringstream str_stm(line) ;
        char first_char ;
        double a, b, c ;
        if( str_stm >> first_char >> a >> b >> c && first_char == prefix ) s.push_back( { a, b, c } ) ;
    }

    return !s.empty() ;
}

std::vector<segment> get_segments( std::istream& stm, char prefix = 'U' )
{
   std::vector<segment> result ;
   stm.ignore( 10000, '\n' ) ; // throw the first comment line away

   segment s{} ;
   while( get_segment( stm, s, prefix ) ) result.push_back(s) ;
   return result ;
}

int main()
{
    std::istringstream file(    "!Comment\n"
                                "U 2.0 4.5 4.0\n"
                                "O 3.4 4.5 -1.9\n"
                                "U 5.6 4.5 2.9\n"
                                "Y 8.0 4.5 4.3\n"
                                "K -11.0 4.5 5.7\n"
                                "U 11.22 -33.44 55.66\n"
                                "!Comment\n"
                                "I 6.0 4.5 7.9\n"
                                "U 2.8 4.5 -12.3\n"
                                "G 2.8 4.5 6.1\n"
                                "U -22.0 9.4 8.9\n"
                                "!This too is a comment\n"
                                "U 7.8 9.0 1.2\n"
                                "U -3.4 -5.6 -7.8\n"
                                "G 1 2 3\n"
                                "U 9.0 10.11 12.13\n" ) ;

    int segment_number = 0 ;
    for( const segment& seg : get_segments( file, 'U' ) )
    {
        std::cout << "\nsegment #" << ++segment_number << "\n-----------\n" << std::fixed << std::setprecision(2) ;
        for( const line& ln : seg )
            std::cout << '\t' << std::setw(7) << ln.col_1 << std::setw(7) << ln.col_2 << std::setw(7) << ln.col_3 << '\n' ;
    }
}

segment #1
-----------
	   2.00   4.50   4.00
	   5.60   4.50   2.90
	  11.22 -33.44  55.66

segment #2
-----------
	   2.80   4.50 -12.30
	 -22.00   9.40   8.90

segment #3
-----------
	   7.80   9.00   1.20
	  -3.40  -5.60  -7.80
	   9.00  10.11  12.13

http://coliru.stacked-crooked.com/a/6ed8f72eb3116145
Thank you guys. With your suggestions I tried to write a crude way of writing my program and it works! :)

int main()
{
string line;
string str,at;
int a=0;
double x,y,z,dx,dy,dz;
vector <double> xyz;
vector <vector <double> > acoor;
vector <vector <double> > bcoor;

//Opening file and storing the data into variables
ifstream infile;
infile.open("water.xyz");
while(getline(infile,line))
{
if(line.size()<20)
{
a=a+1;
continue;
}
istringstream str(line);
str >> at >> x >> y >> z;
if(at=="OH2")
{
xyz.clear();
xyz.push_back(a/2);
xyz.push_back(x);
xyz.push_back(y);
xyz.push_back(z);
acoor.push_back(xyz);
bcoor.push_back(xyz);
}
}

//Calculating the distances between atoms
for(int i=0;i<acoor.size();i++)
{
for(int k=0;k<bcoor.size();k++)
{
if((acoor[i][0]==bcoor[k][0]) && (i!=k))
{
dx=acoor[i][1]-(bcoor[k][1]);

dy=acoor[i][2]-(bcoor[k][2]);

dz=acoor[i][3]-(bcoor[k][3]);

distsq=dx*dx+dy*dy+dz*dz;
dist=sqrt(distsq);
}
}
}}
Last edited on
Topic archived. No new replies allowed.