Read two specific lines from text file and doing arithmetic process between them.

Pages: 12
I have a text file that I would like to read a specific lines in it. All lines have the same amount of characters (one 3 numbers on each like x y z ), and I would like to read from a specified lines , like read line1 and line3 and doing summation process like x1+x3 ,y1+y3 and z1+z3 and put the result in new txt file then move to line 4 and do the same with line 6 and so on for unknown numbers of lines . Is there a way to do this?

Thanks!
loop every three lines and read the second line into a dummy variable, however if the # lines not multiple of 3 then the loop will break down in the final iteration
Hello gunnerfunner

Thanks a lot for your reply, I really appreciate it, I am trying to write a program but I am stuck since i am very beginner in c++ , Any help would be really helpfull !
#include <fstream>
#include <string>

int main()
{
std::ifstream file("Read.txt");
std::string str;
std::getline(file, str); // read a line, as dummy read
while (std::getline(file, str)) // keep reading till end of the file
{
// Process str
}
}


share your input file?
Instead of doing:

while(std::getline(file, str)), do this:

while(file.eof() == false)
{
std::getline(file, str);

//Process str
}

Also, be sure to have the using namespace std; directive at the top of your file otherwise you'll be having to type std:: before every use of getline...

Joe
www.concordspark.com
sparkprogrammer@gmail.com
@Little Captain

Sorry I disagree with those comments.

It's best to loop on the read operation for a stream. eof is too late, the stream has already gone past it by that stage.

It's best in the long run to do exactly that: put std:: before every std thing. There is lots written as to why having using namespace std; is bad, the main problem it defeats the whole idea of namespaces - that is potentially causing name clashes.
my input file is like that :-

2.375 22.6 9
12.57 2.1 9
55.2 1.87 9
77.2 22.1 9
12.9 65.3 9
28.1 77.9 9
and so on

i need some examples code please ,
thanks
Last edited on
One way would be to use a struct to hold the data for each line and store all lines in a vector.
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
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>

using namespace std;

struct Data // maybe you find a more meaningful name
{
  double X;
  double Y;
  int Z;
};

Data Add(const Data& d1, const Data& d2)
{
  Data ret;

  ret.X = d1.X + d2.X;
  ret.Y = d1.Y + d2.Y;
  ret.Z = d1.Z + d2.Z;

  return ret;
}

int main()
{
  vector<Data> data;

  ifstream src("Data.txt");
  if (!src)
  {
    perror("File error: ");
    return -1;
  }

  Data tmp;
  while (src >> tmp.X >> tmp.Y >> tmp.Z)
    data.push_back(tmp);

  cout << data.size() << " lines read.\n\n";
  for (const Data& d: data)
    cout << "X = " << d.X << "\tY = " << d.Y << "\t\tZ = " << d.Z << "\n";

  cout << "\n\nAdding line 1 and line 3" << "\n";
  Data result = Add (data[0], data[2]);

  cout << "Result of addition\n";

  cout << "X = " << result.X << "\tY = " << result.Y << "\tZ = " << result.Z  << "\n\n";

  system("pause");
  return 0; 
}
Thank you so much Thomas I really appreciate it .

Last edited on

Hello
I am so grateful to you ,
please still 2 important things first i need the result to be in new txt file without x= , y= and z= finally the loop move to line 4 and do the same with line 6 and so on till the end of the lines .

so the output of the up data will be like this:-


57.575 24.47 18
105.3 100 18







To create an output file you use
1
2
3
4
5
6
  ofstream dest("Data.txt");
  if (!dest)
  {
    perror("File error: ");
    return -1;
  }

To write the data you can do like this.
1
2
3
  Data result = Add (data[0], data[2]);
  char sep = '\t'; // or whatever you need
  dest << result.X << sep << result.Y << sep << result.Z << "\n";


Try to implement this first. The loop I will show you then.
read line1 and line3 and doing summation process like x1+x3 ,y1+y3 and z1+z3 and put the result in new txt file then move to line 4

in below program no container is used, rather the summation results are sent to the output file directly while the input file is being read by overloading the stream insertion operator << for struct Data:
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
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>

struct Data
{
  double m_X;
  double m_Y;
  double m_Z;
  Data (){}
  Data (const double X, const double Y, const double Z)
    : m_X(X), m_Y(Y), m_Z(Z){}
  Data (const Data& lhs, const Data& rhs)
  : m_X(lhs.m_X + rhs.m_X), m_Y(lhs.m_Y + rhs.m_Y), m_Z(lhs.m_Z + rhs.m_Z){}
};

std::ostream& operator << (std::ostream& os, const Data& d)
{
    os << std::setprecision(4) << std::setw(8) << std::left << d.m_X << std::setprecision(4) << std::setw(8)
         <<  std::left << d.m_Y << std::setprecision(4) << std::setw(8) << std::left << d.m_Z << "\n";
    return os;
}

int main()
{
    std::ifstream inFile {"D:\\input.txt"};
    std::ofstream outFile {"D:\\output.txt"};

    while(inFile)//to check file opening this can be put inside if(inFile) loop
    {
        std::string stringOne{};
        getline(inFile, stringOne);
        std::istringstream streamOne{stringOne};
        double X_One{}, Y_One{}, Z_One{};
        if(streamOne) streamOne >> X_One >> Y_One >> Z_One;

        std::string dummy{};
        getline(inFile, dummy);

        std::string stringThree{};
        getline(inFile, stringThree);
        std::istringstream streamThree{stringThree};
        double X_Three{}, Y_Three{}, Z_Three{};
        if(streamThree) streamThree >> X_Three >> Y_Three >> Z_Three;

        if(inFile)outFile << Data(Data(X_One, Y_One, Z_One), Data(X_Three, Y_Three, Z_Three));
    }
}
Thank you very much gunnerfunner & thomas You really help me .
The last c++ code worked perfectly , it is very useful for me , finally what i should implement in the code if i would like to read line 2 also and doing summation process like x1+x2 ,y1+y2 and z1+z2 as well .
Right now the 2nd, 5th, … lines are being read into the std::string dummy (line 39). If you want to use the information in these lines then you can construct a std::istringstream object with this std::string just as was done for std::string stringOne and std::string stringThree
the main point is for you to understand thoroughly what each line of the program is doing; once you've achieved that you should be able to update/change it as per your needs yourself. So i'd rather you clarified if something was not clear in the program instead of asking about every little change because that'll help you to venture out on your own eventually
You are right , thanks
Last edited on
Just to clarify that it is fine having a using namespace std; in a source file (it IS bad practice to have it in a header file), if you're source file has only one namespace - such as a practice program - it is fine.

Many universities and post-secondary schools teach that and I'm not far off on that as well. If you know you won't have any name clashes, then yes, it is fine. Having it in a header file is a no no of course and many people get confused on that.

For reference:
Item 59 in Sutter and Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" He states to not place using directives for header files or before #includes, but does NOT mention it for .cpp files.

Second, I sometimes find eof() is easier for beginners to understand and it's easy to work around the logic. If Stack Overflow says otherwise, yes, they have a good point, but it doesn't mean it won't work. Again, it's sometimes easier for a beginner to understand "code" that works closer to an English sentence as: "while not end of file", do this... Some will argue this, but it is a viable option. Too often I find that students use the return value of getline() but don't really understand what it is they're doing, so I give out the eof() option - again, one can argue with this, and it's just my opinion. I've seen professional code use eof() as well, so I think understanding as many ways possible to achieve the same solution is a good thing to know.

Anyway, I do appreciate all your input :)
Thanks!
Little Captain wrote:
Just to clarify that it is fine having a using namespace std; in a source file (it IS bad practice to have it in a header file)If you know you won't have any name clashes, then yes, it is fine.


The trouble is that how is to one know they are not going to have a name clash? It is too much of a burden to work that out, people usually discover the hard way, and aren't aware of the reason until someone points it out to them.

Little Captain wrote:
Too often I find that students use the return value of getline() but don't really understand what it is they're doing, so I give out the eof() option - again, one can argue with this, and it's just my opinion.


I think it is a bit disingenuous to teach something that is simpler but wrong. Why not teach them properly form the start? People can have personal preferences, but should they promote them if they are wrong?

Little Captain wrote:
I've seen professional code use eof() as well, so I think understanding as many ways possible to achieve the same solution is a good thing to know.


Perhaps not as professional as you might think they are, and it doesn't achieve the same solution.
@TheIdeasMan,
normally the compiler will tell you about the name clashes, see this demo;
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
#include <iostream>

using namespace std;

namespace A
{
  void f()
  {
    cout << "A::f()" << "\n\n";
  }
}

namespace B
{
  void f()
  {
    cout << "B::f()" << "\n\n";
  }
}

using namespace A;
using namespace B;

int main()
{
  f(); // error C2668 ambiguous call to overloaded function in main.cpp line 33

  return 0; 
}


Can you show me an example where the compiler isn't able to warn you?
Pages: 12