Hi again everyone. I'm having a problem with some code I am writing. I need to take an input file change what is on it, then print out to the screen. What I want to change in the file is re-formatting it so that there is Last name First name then 10 scores, if there are less than ten scores replace the empty ones with 0's. here is what I got so far...

#include <iostream>
#include <cctype>
#include <cstdlib>
#include <string>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;


string getLast(string line);
bool moreToRead(istream& ins);

int main() 
{
  string line;
  ifstream in;

  { in.open("in.text");
  if (in.fail()) {
    cerr << "Failed to open in.text.\n";
    exit(1);
  }
  }
  
  while(moreToRead(in)) {
    getline(in, line);
    getLast(line);
    cout << line << endl;
  }
  in.close();
  
  return (0);
}  


// Function writen by William Austad
bool moreToRead(istream& ins) {
  char ch;
  ins.get(ch);
  while(!ins.eof()) {
    if (!isspace(ch)) {
      ins.putback(ch);
      return (true);
    } else {
      ins.get(ch);
    }
  }
  return (false);
  
}

string getLast(string line) {
  
  string temp = line;
  stringstream tempStream;
  string token;
  if (tempStream >> token) {
    return (token);
  } else {
    temp = "Error";
  }
  return (temp);
}

this is just a start, but could someone advise me where to go with this, I am kind of at a standstill.

Recommended Answers

All 10 Replies

you don't need function moreToRead() Change lines 27-31 to be something like this:

while( getline(in,line) )
{
   // blabla
}

What format is the file? FirstName LastName <scores> ?

The format is Last name First name scores. And the more to read function gets rid of bad whitespaces.

Wow -- it seems like you're way over-complicating the whole procedure. Just make a loop like AD mentioned, and then use a stringstream to split up the words:

// loop...
   std::istringstream iss(line);
   iss >> lastName;
   iss >> firstName;
   // another loop to extract 10 scores, but you get the idea...

The stringstream will automatically ignore the whitespace in your file.

ok, using those methods I got all the last names. Now I do a variation of that to get the first name, then the numbers. Then finally use member functions of the string class to concatinate them all together?

ok, using those methods I got all the last names. Now I do a variation of that to get the first name, then the numbers.

What was wrong with my previous example? This is how I understand your file to be:
FirstName LastName s1 s2 s3 ... getline reads the entire line, and stores it in a string. Then it's put into a stringstream. The first >> will spit out the first name. The second time you use >> , it will spit out the last name. And after that it spits out the scores, until there's nothing left in the stringstream, in which case you're finished with the line, and you carry on to the next line.

Then finally use member functions of the string class to concatinate them all together?

If that's how you want your output on the screen to look, yes.

Ok, so does this code look a lot better?

#include <iostream>
#include <cctype>
#include <cstdlib>
#include <string>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;


string process_line(string, string, string, string);
bool moreToRead(istream& ins);

int main() 
{
  string line;
  ifstream in;

  { in.open("in.text");
  if (in.fail()) {
    cerr << "Failed to open in.text.\n";
    exit(1);
  }
  }
  
  string last;
  string first;
  string scores;
  while(getline(in, line)) {
     cout << process_line(line, last, first, scores) << endl;
    
  }
  
  
  in.close();
  
  return (0);
} 


// Function writen by William Austad
bool moreToRead(istream& ins) {
  char ch;
  ins.get(ch);
  while(!ins.eof()) {
    if (!isspace(ch)) {
      ins.putback(ch);
      return (true);
    } else {
      ins.get(ch);
    }
  }
  return (false);
  
}

string process_line(string line, string last, string first, string scores) {
  string name;
  istringstream lineStream(line);
  lineStream >> last;
  lineStream >> first;
  lineStream >> scores;
  
  name = last + " " + first + " " + scores;
  return (name);
}

That code only gets the first code tho. So I tired to do a loop for scores and got weird answers. Why doesn't this work?

for (int i = 0 ; i < 10 ; i++) {
scores = lineStream << scores;
}
cout << last << " " << first << " " << scores << endl;

>process_line(string line, string last, string first, string scores) {
Why do you pass last , first , and scores , when you just use them to fill up data from the stringstream?

>Why doesn't this work?
Because you're doing something weird. Just do it something like this:

// loop of course
lineStream >> tempScore;
name += " " + tempScore;

Lol i was doing something weird. Ok that worked thank you. Now I just have to figure out how to deal with lines without 10 scores and replaces the missing scores with zero. thanks for you help

Now I just have to figure out how to deal with lines without 10 scores and replaces the missing scores with zero.

The stringstream will return false when there's nothing left in it. So, check if the score extraction was successful each time you do it:

if (iss >> score) { /* successful */ }

I'll let you figure out the rest.

Thanks for your `help I understand this stuff a lot better now :)

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.