Ok, I have a small problem. I'm just trying to get my program to read a single line from a file at a time, and put the results in a vector.

The problem is at the end of each vector. It repeats the last element twice and also adds a 0. I'm not sure whats going on. I don't think the 0 is a newline, because my strstream never receives a '\n'. I also don't know why it repeats the last element. I posted my program plus my input and output at the end. Any help or ideas would be appreciated Thank you.

- Daniel

#include <iostream>
#include <fstream>
#include <strstream>
#include <string>
#include <vector>

void main() {
  // To determine if the the list is smaller or equal to 8, calculate how
  // many times youd have to cut the list to reach less than/equal to 8 BEFORE
  // you go into the mergesort loop.

  ifstream in("in.dat");
  vector<float>numbers;
  float myfloat;
  char ch[256];


  while (in) {
    in.getline(ch, 256, '\n');
    numbers.clear();
    strstream myss;
    myss << ch;

    while(myss) {
      myss >> myfloat;
      numbers.push_back(myfloat);

    }
    for (int a = 0; a <= numbers.size(); a++)
      cout << numbers[a] << ", ";
    cout << endl;
  }
}

My in.dat file looks like this:

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

My output looks like this:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 0,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, 0,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 0,
30, 22,
30, 22,

the loop is formatted wrong. Crevat: atof() does not detect errors in the string, but it doesn't really matter if you know the strings are all formatted ok.

while( in.getline(ch, 256, '\n'))
{
   numbers.push_back(atof(ch));
}

better yet, use a std::string instead of a char array

std::string line;

while( getline(in, line) )
{
   numbers.push_back(atof(line.c_str));
}

Your code shouldn't even compile. You're missing a using declaration (I assume) and main should return 'int'

Also, you should use std::stringstream instead of strstream (I believe the latter is deprecated)

for (int a = 0; a <= numbers.size(); a++)
   cout << numbers[a] << ", ";

I think you are in for a bit of surprise ;)

Thank all of you for your help,
I took all of your suggestions into account and made some changes in my code. Ancient Dragon, I took your advice on the string, which I think is more appropriate since I don't know how long the input may be. The thing is, I'm not trying to pushback the string. I use a string so I can work on one line at a time. Then, I had a thought. In the long run, I'm trying to use a mergesort to sort each line and output on its own line. I think what I'm going to try is something like this:

psuedocode:
  vector<vector<float>>inputlines
  vector<float>floatvector

  while (infile) {
     
       extract one line into a string
       put the string into a strstream
     while (mystrstream) { 
        mystrstream >> myfloat
        floatvector.pushback
     }
     inputlines.pushback(floatvector)
  }

Hopefully my psuedo code is psuedoreadable. I was thinking about creating a vector to hold each line of input, and gathering all the input at the beginning of the program. Then in the next procedure merge sort each input line and then output them.

Ok, so, with that unneccessary information, I did run into another problem even with my modified code. At the end of the run, each vector has one too many numbers still. The last number is always repeated. I also printed out the sizeof each vector, and it comes to 11, instead of the 10 inputs on each line. I'm not sure why the last number is being duplicated every time. Should I try a different kind of loop? Maybe a do-while and check the status of the stream at the end of the loop? My in.dat and my output are at the end of the post.

#include <iostream>
#include <fstream>
#include <strstream>
#include <string>
#include <vector>
using namespace std;

void main() {


  ifstream in("in.dat");
  vector<float>numbers;
  float myfloat;
  string input;


  while (in) {
    getline(in, input);
    numbers.clear();
    strstream myss;
    myss << input;

    while(myss) {
      myss >> myfloat;
      numbers.push_back(myfloat);
    }

    for (int a = 0; a < numbers.size(); a++)  // outputs one line
      cout << numbers[a] << ", ";
    cout << endl;
    cout << "sizeof numbers: " << numbers.size() << endl;
  }
}

OUTPUT:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10,
sizeof numbers: 11
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 20,
sizeof numbers: 11
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30,
sizeof numbers: 11
30,
sizeof numbers: 1

in.dat:
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

>>I'm not trying to pushback the string. I
If you read my example carefully I didn't push_back the string either.

>>At the end of the run, each vector has one too many numbers still
re-read my previous post -- I already told you that your loop is incorrect and I showed you the correct loop

Sorry for misunderstanding it. I got the problems all worked out now. Thank you all. =)

Ok, for anyone interested, this is the entire mergesort program I was working on. It is finished and works(w/ g++). The stringstream issues I had were in the "GetInput" function. You will see how I finally decided to solve the problem.

/* mergesort.cpp | John Daniel Leon | johndleon@gmail.com | 10/01/06
 This program sorts numbers using a merge sort algorithm
 Merge sort: O(nlog(n)) - Divides unsorted list in half and sorts each sublist
 Recieves input from file in.dat - NOTE : End of file does not contain a new line. */

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

void GetInput(vector<float> &numbers, vector< vector<float> > &inputlines);
void mergesort(vector<float> &myvec);
void mergesort(vector<float> & a, vector<float> & tmp, int left, int right);
void merge(vector<float> & vec1, vector<float> & vec2, int leftpos, int rightpos, int rightend);

void main()
{
  vector<float>numbers;
  vector< vector<float> >inputlines;

  GetInput(numbers, inputlines);      // Uses "in.dat" - no new line at EOF
  
  for (int q = 0; q < inputlines.size(); q++)
    mergesort(inputlines[q]);

  for (int x = 0; x < inputlines.size(); x++){  
    for (int a = 0; a < inputlines[x].size(); a++)
     cout << inputlines[x][a]; if(a != inputlines[x].size() - 1) cout << ", ";
    cout << endl;
  }
}


void GetInput(vector<float> & numbers, vector< vector<float> > & inputlines)
 // This function reads "in.dat" file and stores each float number on a line into a float
 // vector. Then the float vectors are stored in a vector called inputlines.
 // This waay I can gather all the data in one procedure and then close the file
 // and move on with the rest of the program. 
 //  NOTE: End of "in.dat" should not contain a newline.
{
  ifstream in("in.dat");
  if(!in)
    cout << "Error reading file: in.dat" << endl;
  string input;
  float myfloat;

  while (getline(in, input)) {
    numbers.clear();
    stringstream myss;  
    myss << input;
    while(myss >> myfloat) {
      numbers.push_back( myfloat );
    }
  inputlines.push_back(numbers);
  }
  in.close();
}


void mergesort ( vector<float> &unsortedvec )
 // Calls mergesort on the unsorted vector and a temporary
 // vector the same size as unsortedvec.
{
  vector<float> temp(unsortedvec.size());
  mergesort(unsortedvec, temp, 0, unsortedvec.size() - 1);
}


void mergesort(vector<float> & a, vector<float> & tmp, int left, int right)
 // If the size of the vectors is not 1, then it recurses on itself and 
 // then calls merge.
{
  if (left < right)
  {
    int center = (left + right) / 2;
    mergesort(a, tmp, left, center);
    mergesort(a, tmp, (center + 1), right);
    merge(a, tmp, left, (center + 1), right);
  }
}


void merge(vector<float> & vec1, vector<float> & vec2, int leftpos, int rightpos, int rightend)
 // This is the merge routine. It compares the elements in each vector and manipulates the elements
 // so that vec1 ends up with the final merged(sorted) values.
{
  int leftend = rightpos - 1;
  int tmppos = leftpos;
  int numelements = (rightend - leftpos + 1);

  while(leftpos <= leftend && rightpos <= rightend)
    if (vec1[leftpos] <= vec1[rightpos])
      vec2[tmppos++] = vec1[leftpos++];
    else 
      vec2[tmppos++] = vec1[rightpos++];

  while(leftpos <= leftend)          // Copy rest of first half
    vec2[tmppos++] = vec1[leftpos++];

  while(rightpos <= rightend)        // Copy rest of right half
    vec2[tmppos++] = vec1[rightpos++];

  for(int i = 0; i < numelements; i++, rightend--)   //Copy vec2 back
    vec1[rightend] = vec2[rightend];
}
This article has been dead for over six months. Start a new discussion instead.