Rachel Kim
Rachel Kim

Reputation: 95

Rid of white space in file print

i am trying to get my file to remove the leading and trailing space but it does not work. this is the txt file contents:

        392402  wench

I have tried printing out my code, and this is what is displayed.

first:        392402    wench second: 

I want it to display this instead

first: 392402 second: wench 

this is my code

void readFile(const string &fileName) {
  int limit;
  ifstream ifs(fileName);
  string::size_type position;
  key_type item;
  mapped_type count;
  string line;
  if (ifs.is_open()) {
    ifs >> limit;
    for (int i = 0; i < limit; i++) {
      getline(ifs, line);
      position = line.find(" ", 0);
      auto c = line.substr(position + 1);
      item = line.substr(0, position);
      cout << "first: " << c << " second: " << item << endl;
      value_type value(item, count); 
      values.push_back(value);
    }
  } else {
    cout << "Can't open file.";
  }

what am i doing wrong? Thank you

Upvotes: 0

Views: 93

Answers (1)

WhozCraig
WhozCraig

Reputation: 66234

The two biggest mistakes you're making are (a) not checking your values for expected output as you go, and (b) not running your code in a debugger to see what is really happening. If you had, the values of position, c, and item would have been blatantly wrong, and you could then surmise where to go from there.

Belaying the highly-likely possibility that the loop iteration is broken from inception because you never consumed the remainder of the entry line containing input, let's look at the actual data and what you're asking of it with your code.

We read this entire line:

        392402  wench

You then ask "find the first single-space string in this line" via this code:

position = line.find(" ", 0);

Well, that would be here:

        392402  wench
^here

So position is zero (0). You then ask for the sub-string, starting a that position + 1, through the end of the string with this code:

auto c = line.substr(position + 1);

Therefore c now contains (leading space removed via the +1):

       392402  wench

Now we build item, which is done with this line:

item = line.substr(0, position);

Remember, position is zero, so you're asking for the string, starting at location 0, length 0. As you can imagine, that isn't going to amount to anything. So now item is an empty string.

Finally, the output statement:

cout << "first: " << c << " second: " << item << endl;

will produce:

first:        392402  wench second:  

I.e. exactly what you're seeing. And that's it. Clearly this is wrong.

Alternative

Use better error checking, value checking, and a string stream for per-line extraction. The following code doesn't give two cents about your type aliases (mainly because you didn't include them anyway and I'd rather not loft any guesses as to their origin).

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

// Expects a file with the following format:
//  count
//  name1 value1
//  name2 value2
//  ...
void readFile(const std::string &fileName)
{
    std::ifstream ifs(fileName);
    if (ifs.is_open())
    {
        int limit;
        if (ifs >> limit && limit > 0)
        {
            // consume through end of line.
            ifs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

            // repeat until `limit` iterations or stream error/eof
            std::string line;
            for (int i = 0; i < limit && std::getline(ifs, line); i++)
            {
                std::istringstream iss(line);

                // extract line values. Note these *can* be formatted 
                //  extraction for things besides just strings
                std::string first, second;            
                if (iss >> first >> second)
                {
                    std::cout << "first: " << first << " second: " << second << '\n';

                    // TODO: whatever you want to do with first/second
                }
            }
        }

        ifs.close();
    }
    else
    {
        std::cerr << "Can't open file: " << fileName << '\n';
    }
}

Note: The above code will NOT work for remaining-line-content as the expected second value. E.g. It will not process something like this as you may first expect:

10000  this is a multi-word description

will produce this:

first: 10000 second: this

which is considerably different than what you may be expecting:

first: 10000 second: this is a multi-word description

There was no suggestion in the original post such support was mandatory, though adding it wouldn't be terribly difficult to add. If it is a requirement, I leave that task to you.

Upvotes: 1

Related Questions