Using reverse function and removing whitespace for a set amount of information from a txt file

I need to find a way of reading in the last 6 lines of data from a file.

For example if I have 1 2 3 4 5 6 7 8 9 10

I need to read be able to get 10, 9, 8, 7, 6, 5.

This method outputs the last 6 numbers from the file however they are backwards and I need a way to reverse them and get rid of the whitespace it prints out.

I'm unsure on how to use reverse and which arguments are required from this - http://en.cppreference.com/w/cpp/algorithm/reverse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
    char x;
    ifstream f("test.txt", ios::ate);
    streampos size = f.tellg();
    for (int var = 1; var <= size; var++){
        f.seekg(-var, ios::end);
        f.get(x);
        reverse(x);
        cout << x; 
    }
    cin.get();
    return 0;
}

Alot of the information I can find on this kind of thing are reading in all the information in a vector from the bottom and reversing it which is not what I need.

Can anyone please advise?

Regards
closed account (SECMoG1T)
are your values arranged in a single line like you've shown?
why did you dislike using a vector and you could also apply reverse to it and make your work easier?
With the vector method I didn't know how to only get them 6 lines of data.
Sorry no the values are displayed in the text file like this:

60
50
45
43
43
23
10
6

Note the numbers can change. I'm also unsure how to get rid of whitespace.

closed account (SECMoG1T)
The vector method will still work , thing is right now i cant figure out another way your could achieve your results more efficiently without using containers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 ///variables
 ifstream read("file.txt");
 std::vector<int> record;

 int var;
  
 if(!read)
   { std::cout<<"File not found\n"; return (1);}

 while(read>>var)//no more whitespaces, your file must contain atleast 6 values
  {
      record.push_back(var);
   }

   std::reverse(record.begin(),record.end());
    std::vector<int> results(record.begin(),record.begin()+6);///you could do without these
         ///just to make things clear.
  for(const auto& reslt : results)
  {
     std::cout<<reslt<<std::endl;
   }
   
 


Won't that be enough.
Last edited on
You don't seem to want lines, but values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main() {
  std::vector<int> arr;

  // Read values from file with formatted input
  // and append them to arr

  // Print (at most) last 6 with backward iteration
  auto rit = arr.rbegin();
  size_t count = 0;
  while ( rit!= arr.rend() && count < 6 ) {
    if ( count ) std::cout << ',';
    std::cout << *rit;
    ++rit;
    ++count;
  }
  std::cout << '\n';

  return 0;
}

Andy1992 could I get this code to work with a timestamp in the line and decimal numbers? That is the goal ultimately. Thank you for explaining this clearly.
closed account (SECMoG1T)
timestamp in the line and decimal numbers?
if you've got some timestamps in your file you will need to ignore them if they aren't necessary BTW am not sure if you mean your file consists of timestamps as the values if so you can handle them with strings, if you want to handle value of floating point you could use a vector of type double instead.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ifstream read("file.txt");
 std::vector<double> record;

 int var;
  
 if(!read)
   { std::cout<<"File not found\n"; return (1);}

 while(read>>var)//no more whitespaces, your file must contain atleast 6 values
  {
      record.push_back(var);
   }

 
    std::vector<double> results(record.rbegin(),record.rbegin()+6);
   /// from @keskiverto idea this will save our time 

  for(const auto& reslt : results)
  {
     std::cout<<reslt<<std::endl;
   }


i hope that what you ment.
I have values such as:
50.67 Sat Jan 03 04:29:21 PM
12.67 Sat Jan 03 04:29:21 AM
607 Sat Jan 03 04:29:21 AM

Which I need to read into the program. Will there be a way to do this using strings?

I've tried the following but I don't know how to read it in #include <iostream>
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
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

int main()
{


	ifstream read("test.txt");
	std::vector<string> record;

	string var;

	if (!read)
	{
		std::cout << "File not found\n"; return (1);
	}

	while (read >> var)//no more whitespaces, your file must contain atleast 6 values
	{
		record.push_back(var);
	}

	std::reverse(record.begin(), record.end());
	std::vector<int> results(record.begin(), record.begin() + 6);///you could do without these
	///just to make things clear.
	for (const auto& reslt : results)
	{
		std::cout << reslt << std::endl;
	}

	cin.get();
}



However when I try to run the code it says iterator + offset out of range.

Can you advise or suggest a better way?
Last edited on
closed account (SECMoG1T)
Wll I guess you'll need to use getline to solve it.
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
ifstream read("test.txt");
 std::vector<std::string> record;
 std::vector<std::string> results;

  std::string var;
  
 if(!read)
   { std::cout<<"File not found\n"; return (1);}

 while(getline (read, var,'\n'))
  {
      record.push_back(var);
   }

 
    if (record.size ()>=6)
    {
        results.insert(result.begin (),record.rbegin(),record.rbegin()+6);
    }

    else
     {
        std::cout <<"Only :"<<record.size ()<<" values were found\n";
        results.insert(results.begin(),record.rbegin (), record.rend ());
     }
  

  for(const auto& reslt : results)
  {
     std::cout<<reslt<<std::endl;
   }

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
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

int main ()
{
	vector<string> vect;
	string s;
	
	ifstream read;
	read.open("file.txt");
	
	while(read.good()) {
		getline(read,s);
		vect.push_back(s);
	}
	
	//vector<string>::iterator iter = vect.end()-1;
		
	for(auto iter = vect.end()-1; iter>= vect.end()-3; iter--) {
		cout << *iter << endl;
	}
	
cin.ignore();
return 0;
}
That's ace can I ask you a question how the code actually works to make sure my understanding of it is correct?

push_back is used to add another line of data to the vector

and if the record size is greater than or equal 6 then the it will add 6 to this? I'm not really sure what the if statement does.

Thank you very much for your help :)
closed account (SECMoG1T)
push_back is used to add another line of data to the vector 
Exactly it just adds another value read from the file into the vector.

I'm not really sure what the if statement does. 
Ooh I added these because your code threw an out-of-range exemption if the number of values of were less thanu six , here record.begin() + 6)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (record.size ()>=6)///if our file had atleast six values it will be safe to use the iterators below
 {                              
   results.insert(result.begin (),record.rbegin(),record.rbegin()+6);
    /// from the last value in the vector record we will insert six value upto to last-6th value. 
  } 

else 
 {
    ///if our file held less than 6 records , an attempt to copy six values will just throw an out of range
    /// exemption,  instead we will copy all the values in reverse order but we will inform the user that
   /// the values retrieved from the file were less than 6.

   std::cout <<"Only :"<<record.size ()<<" values were found\n"; 
   results.insert(results.begin(),record.rbegin (), record.rend ()); 
 } 


Last edited on
There is a more compact way for that:
1
2
const auto count = std::min( 6, record.size() );
std::vector<std::string> results( record.rbegin(), record.rbegin() + count );



@PapaSmurf:
You should have shown the actual data format at start.

Now, would you like to go a step forward and separate the floating point value from the timestamp?


@anup30:
That ifstream::good() is redundant. Simply:
1
2
3
while ( std::getline( read, s ) ) {
  vect.push_back( s );
}

The thing is that the getline returns the stream and stream in the conditional returns the same as the stream.good().
Topic archived. No new replies allowed.