Hi everybody.

I'm interested in C++ programming, so I just started learning it. I already worked with structured programming, e.g. Pascal or Fortran, so I have no problems with while, for, pointers and so on. Above all I'm interested in object-oriented programming, but I'm an absolute beginner in that. I'd like to write a little programm for work in such way, but I'm very confused. I have a definite aim and I searched for tutorials or examples about it but there's a lot of different libraries and different codes (often a mix of C and C++). Can you help me with a simple and basic code, so I can learn through it?
This is the question. I want to read a text file and manipulate it to obtain a different one. The structure of the file is a matrix with 3 columns and an unknown amount of rows (cartesian coordinates). Rows are grouped and empty lines split them. I have to copy the text file into a matrix, add a fourth 'flag' column and delete the empty lines. The flag consists in a integer: it's 1 for rows following an empty line and 0 for the other rows. The flag is 9 for the last row. An example:

-8.25000 0.00000 5.00000
-8.25000 2.40000 5.00000
-8.25000 3.14041 5.02089
-8.25000 3.88838 5.09037
-8.25000 4.26046 5.14651
-8.25000 4.62873 5.21863
-8.25000 4.99130 5.30800
-8.25000 5.34627 5.41589
-8.25000 5.69174 5.54358
-8.25000 6.02580 5.69235
-8.25000 6.34657 5.86347
-8.25000 6.65214 6.05822
-8.25000 6.94062 6.27787
-8.25000 7.21010 6.52370
-8.25000 7.45869 6.79699
-8.25000 7.68448 7.09900
-8.25000 7.68448 13.00000

-6.91500 0.00000 4.86198
-6.91500 0.53300 4.86107
-6.91500 1.52750 4.84723
-6.91500 2.52103 4.85241
-6.91500 3.24041 4.90173
-6.91500 3.95730 5.00000
-6.91500 4.65508 5.14855
-6.91500 5.33864 5.35470
-6.91500 5.67153 5.48129
-6.91500 5.99659 5.62458
-6.91500 6.31240 5.78533
-6.91500 6.61753 5.96431
-6.91500 6.67352 6.00000
-6.91500 7.01575 6.23832
-6.91500 7.34042 6.50144
-6.91500 7.64348 6.78862
-6.91500 7.92086 7.09914
-6.91500 7.92086 9.00000
-6.91500 7.92086 13.00000

0.00000 0.00000 3.97457
0.00000 0.73587 3.97467
0.00000 1.77104 4.00000
0.00000 2.45523 4.02717
0.00000 3.13497 4.09151
0.00000 3.47509 4.15067
0.00000 3.81199 4.22868
0.00000 4.14536 4.32388
0.00000 4.47487 4.43462
0.00000 5.12109 4.69613
0.00000 5.74813 5.00000
0.00000 6.32759 5.31955
0.00000 6.88956 5.66551
0.00000 7.38561 6.00000
0.00000 8.12791 6.53821
0.00000 8.85263 7.09970
0.00000 8.85263 9.00000
0.00000 8.85263 13.00000

is transformed into:

-8.25000 0.00000 5.00000 1
-8.25000 2.40000 5.00000 0
-8.25000 3.14041 5.02089 0
-8.25000 3.88838 5.09037 0
-8.25000 4.26046 5.14651 0
-8.25000 4.62873 5.21863 0
-8.25000 4.99130 5.30800 0
-8.25000 5.34627 5.41589 0
-8.25000 5.69174 5.54358 0
-8.25000 6.02580 5.69235 0
-8.25000 6.34657 5.86347 0
-8.25000 6.65214 6.05822 0
-8.25000 6.94062 6.27787 0
-8.25000 7.21010 6.52370 0
-8.25000 7.45869 6.79699 0
-8.25000 7.68448 7.09900 0
-8.25000 7.68448 13.00000 0
-6.91500 0.00000 4.86198 1
-6.91500 0.53300 4.86107 0
-6.91500 1.52750 4.84723 0
-6.91500 2.52103 4.85241 0
-6.91500 3.24041 4.90173 0
-6.91500 3.95730 5.00000 0
-6.91500 4.65508 5.14855 0
-6.91500 5.33864 5.35470 0
-6.91500 5.67153 5.48129 0
-6.91500 5.99659 5.62458 0
-6.91500 6.31240 5.78533 0
-6.91500 6.61753 5.96431 0
-6.91500 6.67352 6.00000 0
-6.91500 7.01575 6.23832 0
-6.91500 7.34042 6.50144 0
-6.91500 7.64348 6.78862 0
-6.91500 7.92086 7.09914 0
-6.91500 7.92086 9.00000 0
-6.91500 7.92086 13.00000 0
0.00000 0.00000 3.97457 1
0.00000 0.73587 3.97467 0
0.00000 1.77104 4.00000 0
0.00000 2.45523 4.02717 0
0.00000 3.13497 4.09151 0
0.00000 3.47509 4.15067 0
0.00000 3.81199 4.22868 0
0.00000 4.14536 4.32388 0
0.00000 4.47487 4.43462 0
0.00000 5.12109 4.69613 0
0.00000 5.74813 5.00000 0
0.00000 6.32759 5.31955 0
0.00000 6.88956 5.66551 0
0.00000 7.38561 6.00000 0
0.00000 8.12791 6.53821 0
0.00000 8.85263 7.09970 0
0.00000 8.85263 9.00000 0
0.00000 8.85263 13.00000 9

I started to write pieces of codes but, as I wrote above, I'm very confused with libraries, classes and so on. I rely on your patience and your help, I guess it's a very simple question for a C++ expert. I need this code as a tutorial. I can't understand anything about

std::vector<double> row;
    std::copy(std::istream_iterator<double>(ifs),
          std::istream_iterator<double>(),
          std::back_inserter(row))

or

std::istream &read(std::istream &stream) { 
    std::copy(std::istream_iterator<double>(stream), 
          std::istream_iterator<double>(), 
          std::back_inserter(xyz));

In the meantime I go on with studying C++. Thanks for your attention.

Recommended Answers

All 16 Replies

I know there are a lot of mistakes, but is it a good start? :-/

#include iostream.h
#include fstream.h
#include cstdlib.h

int main()
{

// open input file

    std::fstream ifs;
    ifs.open("file_name");

// create matrix as vector of vectors

    std::vector<std::vector<double>> matrix;
    int flag;

// read line

    std::string line;
    std::getline(ifs, line);

// if something went wrong (probably EOF), exit the loop

    if(!ifs) 
        break;

// if the line is empty, read row contents into vector and append flag 1

    if (line.empty())
        flag==1;
        continue;
        std::vector<double> row;
        std::copy(std::istream_iterator<double>(ifs),
                  std::istream_iterator<double>(),
                  std::back_inserter(row));
        row.push_back(flag)

// else read row contents into vector and append flag 0

    else
        flag==0;
        std::vector<double> row;
        std::copy(std::istream_iterator<double>(ifs),
                  std::istream_iterator<double>(),
                  std::back_inserter(row));
        row.push_back(flag)

    return matrix;
}

I edited the code in order to remove empty lines and squeeze whitespace in a single space. But I'm not sure this is the best (and correct) way. In the meantime I noticed that 'empty lines' are not empty: there is a single whitespace.

#include iostream.h
#include fstream.h
#include stream.h
#include cstdlib.h

int main()
{

// open input file

    std::ifstream ifs( "in_file.txt" );
    std::fstream ofs( "out_file.txt" );

// squeeze whitespace

   ifs >> word;
   out << word;

   while( in >> word )
   {
      ofs << " ";
      ofs << word;
   }

// read line

    std::string line;
    std::getline( ofs, line );

// append flag and remove 'empty lines'

    int flag = 1;

    while( getline( ofs, line ) )
    {
        if( line == "" )
        {
            flag = 1;
            continue;
        }
        cout << line << " " << flag << endl;
        flag = 0;
    }

ifs.close();
ofs.close();

}

have you compiled this to check for errors ?
also if you have just started learning C++ this is better than i did when i first started :D
good job ;)

I tried to compile test.cpp:

#include <iostream>
#include <fstream>
#include <stream>
#include <cstdlib>
using namespace std;

int main()
{

// open input file

    std::ifstream ifs( "in_file.txt" );
    std::fstream ofs( "out_file.txt" );

// squeeze whitespace

   std::string word;
   ifs >> word;
   ofs << word;

   while( ifs >> word )
   {
      ofs << " ";
      ofs << word;
   }

// read line

    std::string line;
    std::getline( ofs, line );

// append flag and remove 'empty lines'

    int flag = 1;

    while( getline( ofs, line ) )
    {
        if( line == "" )
        {
            flag = 1;
            continue;
        }
        cout << line << " " << flag << endl;
        flag = 0;
    }

ifs.close();
ofs.close();

}

I had the error message:
test.cpp:3:18: error: stream:
What does it mean?

>> test.cpp:3:18: error: stream:

There isn't a header file named <stream> in standard C++. Looks like you'd rather want to;

#include <string>

You're right. What a stupid mistake... sorry. I edited the source file:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

int main()
{

// open input file

    std::ifstream ifs( "in_file.txt" );
    std::fstream ofs( "out_file.txt" );

// squeeze whitespace

   std::string word;
   ifs >> word;
   ofs << word;

   while( ifs >> word )
   {
      ofs << " ";
      ofs << word;
   }

// read line

    std::string line;
    std::getline( ofs, line );

// append flag and remove 'empty lines'

    int flag = 1;

    while( getline( ofs, line ) )
    {
        if( line == "" )
        {
            flag = 1;
            continue;
        }
        cout << line << " " << flag << endl;
        flag = 0;
    }

ifs.close();
ofs.close();

}

and the outoput is:

gcc -o test test.cpp
/tmp/cc10PaH8.o: In function `main':
test.cpp:(.text+0x38): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(char const*, std::_Ios_Openmode)'
test.cpp:(.text+0x64): undefined reference to `std::basic_fstream<char, std::char_traits<char> >::basic_fstream(char const*, std::_Ios_Openmode)'
test.cpp:(.text+0x70): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()'
test.cpp:(.text+0x87): undefined reference to `std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
test.cpp:(.text+0x9e): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
test.cpp:(.text+0xb7): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
test.cpp:(.text+0xce): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
test.cpp:(.text+0xe5): undefined reference to `std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
test.cpp:(.text+0xf9): undefined reference to `std::basic_ios<char, std::char_traits<char> >::operator void*() const'
test.cpp:(.text+0x10e): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()'
test.cpp:(.text+0x122): undefined reference to `std::basic_istream<char, std::char_traits<char> >& std::getline<char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
test.cpp:(.text+0x15d): undefined reference to `std::cout'
test.cpp:(.text+0x162): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
test.cpp:(.text+0x172): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
test.cpp:(.text+0x182): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(int)'
test.cpp:(.text+0x18a): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
test.cpp:(.text+0x192): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
test.cpp:(.text+0x1ae): undefined reference to `std::basic_istream<char, std::char_traits<char> >& std::getline<char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
test.cpp:(.text+0x1c2): undefined reference to `std::basic_ios<char, std::char_traits<char> >::operator void*() const'
test.cpp:(.text+0x1de): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::close()'
test.cpp:(.text+0x1ea): undefined reference to `std::basic_fstream<char, std::char_traits<char> >::close()'
test.cpp:(.text+0x1f6): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
test.cpp:(.text+0x208): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
test.cpp:(.text+0x21a): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
test.cpp:(.text+0x22c): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
test.cpp:(.text+0x23e): undefined reference to `std::basic_fstream<char, std::char_traits<char> >::~basic_fstream()'
test.cpp:(.text+0x250): undefined reference to `std::basic_fstream<char, std::char_traits<char> >::~basic_fstream()'
test.cpp:(.text+0x265): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()'
test.cpp:(.text+0x28f): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()'
/tmp/cc10PaH8.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cpp:(.text+0x2cd): undefined reference to `std::ios_base::Init::Init()'
test.cpp:(.text+0x2d2): undefined reference to `std::ios_base::Init::~Init()'
/tmp/cc10PaH8.o: In function `bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)':
test.cpp:(.text._ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_[bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)]+0x14): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare(char const*) const'
/tmp/cc10PaH8.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
/tmp/cc10PaH8.o:(.eh_frame+0x4b): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status

What's the problem, pleas? Have I to copy the called libraries in the same folder as test.cpp and in_file.txt?

>> gcc -o test test.cpp

You are using gcc as the compiler. Since the code is C++ (i.e. not C), you have to compile with g++ instead.

If you are compiling from the command line, just replace gcc with g++, otherwise you have to change your IDE's/project's settings.

Also, please explicitly return a value from main.

I'm not sure if g++ will presume anything and allow that to compile, but you've declared main as an int (which is good! :D), however, you've not returned a value from the method.

To indicate success back to the kernel, you should return 0, or non-zero if there has been some kind of catastrophic failure ^^

Explicitly returning a value from main() should not be necessary, the standard says:

If control reaches the end of main without encountering a return statement, the effect is that of executing

return 0;

>> To indicate success back to the kernel, you should return 0, or non-zero if there has been some kind of catastrophic failure ^^

The two pre-defined macros EXIT_SUCCESS and EXIT_FAILURE (from <cstdlib>) can also be used.

commented: Narue just shed a (happy) tear somewhere... :) +4

Still good practise to explicitly return in my opinion.
Not all compilers are fully standards compliant and it also lets everyone who reads your code know you intended to return 0 and didn't just forget.

Thanks for your help, I didn't know there was a g++ compiler (and thanks for the return hint). Obviously it doesn't work, becouse the source code is not correct. Please, can you help me? Thanks for your patience.

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

int main()
{

// open input file

    std::ifstream ifs( "in_file.txt" );
    std::ofstream ofs( "out_file.txt" );

// squeeze whitespace

   std::string word;
   ifs >> word;
   ofs << word;

   while( ifs >> word )
   {
      ofs << " ";
      ofs << word;
   }

// read line

    std::string line;
    std::getline( ofs, line );

// append flag and remove 'empty lines'

    int flag = 1;

    while( getline( ofs, line ) )
    {
        if( line == " " )
        {
            flag = 1;
            continue;
        }
        cout << line << " " << flag << endl;
        flag = 0;
    }

ifs.close();
ofs.close();

return(0);

}

>> ... Obviously it doesn't work ...

Please see Narue's Read This Before Posting, mostly the "Describe your problem clearly and fully!" section.

OK, you're right. I think I was exhaustive in the earlier posts but, in a few words: I have to edit an input file (see attachment), in order to obtain an output file, structured as described in the first post:

x y z flag

The flag is "1" if the row follows an empty line, otherwise is "0". I want to remove empty lines (they are not really empty, they seem to consist in " \n"). Possibly I'd like to squeeze whitespaces in each line and have just one single space between x y z flag. Possibly I'd like to have a '9' flag in the last row.

The code I wrote doesn't work becouse it doesn't recognize the 'empty' lines, so there is just one "1" flag in the first line (and 'empty' lines aren't removed). There is another strange thing: the flag is not at the righ place, I obtain something like x y z \n flag \n.

Here I am again. This is my current code: I can delete 'empty lines' (they really consist in one whitespace and the f.....g 'hidden' "\n" character) and append the integer flag at the end of the row. Next goals: squeeze whitespaces in order to have a structure like:

_x_y_z_flag

and change the last "0" flag into "9". Any suggestions, please? Thanks for your attention.

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

int main()
{

// open input file

    std::ifstream ifs( "in_file.txt" );
    std::ofstream ofs( "out_file.txt" );

// read line

    std::string line;
    std::getline( ifs, line );

// append flag

    std::string flag = " 1";
    int l;

    while( getline( ifs, line ) )
    {

         l = line.length();
         if( l == 2)
         {
             flag = " 1";
          continue;
          }
          line.erase(l-1);
          ofs << line << flag << endl;
          flag = " 0";
     }

ifs.close();
ofs.close();

}

I think you are unnecessarily concentrating on the whitespace.

You might read each line into a std::string, just like you already do, and use a std::stringstream for extracting 3 doubles. If the extraction succeeds, you've got a valid line to output, otherwise treat it as a blank line (maybe with some error checking added, i.e. is it really just spaces plus a newline or perhaps something else).

I think, managing all that would be a good start. Perhaps search DaniWeb for some stringstream examples.

OK, I learned how to read a line word by word with stringstream. Thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.