0

My task is to create a program that converts one unit of measurement to another. So if the user enters 5 kg, it converts this to the equivalent in pounds. The requirements state that the user input must be read all on one line and any number of spaces anywhere in the input must not eliminate functionality. My problem is this: if a user enters their input with a bunch of spaces between the actual double 'mass' value and then in between different words in the unit of measurement such as 'short tonnes', how can I eliminate the spacing so that it reads as just "shorttonnes"? So far my code is:

double mass;  string unit;
    cout << "Enter mass: ";
    cin >> mass;
    cin.ignore();
    cin >> unit;

    if (unit == "short tonnes" || unit == "sh tn")
    {
        //convert to long tonnes
    }

My code works to ignore white space before the double mass value is entered, as well as to ignore white space up until the first part of the string is entered. But I can not figure out how to make my program read "short tonnes" as just "shorttonnes" (regardless of the number of spaces between the words), so that I can do the string comparison and convert the mass value as necessary. Thank you in advance for your help and please do not hate on me, I am in my first week of learning C++.

2 Answers2

3

My apologies again. Post edit, I think my initial comment was correct-ish. Get the line with getline as recommended by others. Then put the line in a std::istringstream. Read the words from the stringstream with >> and concatenate them with the + operator until you have assembled one of the tokens you are looking for. >>'s default behaviour is to discard all whitespace for you.

So...

std::string line;
while (std::getline(cin, line)) // reads in a line
{
    std::istringstream stream(line);
    std::string spaceless;
    std::string word;
    while (stream >> word) // get words on the line without any whitespace
    {
        spaceless += word; // assemble without spaces
        if (spaceless ==  "shorttonnes")
        {
            //do something with spaceless
        }
        else if (spaceless ==  "Someothertoken")
        {
            // do something else with spaceless
        }
        else if ( ... ) 
        {
            // rinse, repeat
        }
    }
}

Here is a simple, stripped down example of just the concatenation: https://ideone.com/hGLr6f

There are other techniques you can use in place of the if/else if chain. A std::map of strings and function pointers for one, but that is another question.

user4581301
  • 33,082
  • 7
  • 33
  • 54
1

std::copy_if() is another way to do what you want. It's well worth learning how it works, since it can find uses in many other places, other than this particular problem.

If you write this space removal routine, it'll become a component you can re-use if you ever have to solve this problem again in a different situation.

void StripSpaces(std::string &str)
{
    std::vector<char> temp;
    temp.resize(str.length());
    auto pred = [] (char &c)
    {
        return c != ' ';
    };
    auto temp_end = std::copy_if(str.begin(), str.end(), temp.begin(), pred);
    str = std::string(temp.begin(), temp_end);
}

That does an inplace removal of spaces from your string.

The vector<char> is there to hold the resulting value. It's first resized to be the length of the input string, knowing that the result can be no longer than the input.

pred is a lambda that just takes a single character as it's parameter and returns a bool that is true if and only if the character is not a space.

std::copy_if does the heavy lifting. It'll copy characters from your source string to temp, but only if pred returns true for that character. It returns an iterator that refers to the element one past the last character we copied. This is, very conveniently usable as a synonym for temp.end() if you want to consider temp as holding the resulting string.

The last thing is to reconstruct the parameter string from the data in temp.

dgnuff
  • 3,195
  • 2
  • 18
  • 32
  • This is awesome! I will definitely keep this in mind later on as I gain a better understanding of C++. Right now i'm sad to say but a lot of what you wrote doesn't make much sense to me but as I continue to learn, I will come back to your post. Thank you for your help – Sabrina Tessier May 16 '18 at 03:14