简体   繁体   中英

Input String where Integer should be - C++

I'm a beginner and am stuck on such a simple problem whilst working through Stroustrup's Principles and Practices.

Using only basic elements

#include "std_lib_facilities.h"

int main()
{

double highest = 0;
double lowest = 100;
int i=0;
double sum = 0;
vector <double> inputlist;
double input;
string unit;

cout<<"Type in a number followed by it's unit \n";

while(cin>>input>>unit){

    inputlist.push_back(input);
    sum += inputlist[i];

    if (input >= lowest && input <= highest){
        cout<<input<<" \n";
        ++i;
    }

    else if (input < lowest){
        lowest = input;
        cout<<"\nLowest Number so far \n"<<lowest;
    ++i;
    }

    else if (input > highest){
        highest = input;
    cout<<"\nHighest number so far \n"<< highest;
    ++i;
    }

    else
        cout<<"Lowest is: \n"<<lowest<<"\n\n Highest is: \n"<<highest<<" \n\n and the total is: \n"<<sum;


    if (unit == "ft", "m", "in","cm")
        cout<<unit<<"\n";

    else
        cout<<"cannot recognize unit";
}

keep_window_open();
return 0;
}

I need the program to show the user the sum and highest and lowest value when the character "|" is entered. Problem is: i need this entered where the Integer value should be entered.

NOTE: I don't know much about conversions but tried a few and they didn't work.

If I understood you correctly, you want to read int from std::cin , but:

int i;
if (std::cin >> i) {
    ...

doesn't suite your needs since there might be '|' sign as a signal for termination of reading.

Here's what you could do: read input word by word ( std::string ) and parse these words separately using temporary std::istringstream :

std::string word;
if (std::cin >> word) {
    if (word == "|")
        ...
    // else:
    std::istringstream is(word);
    int i;
    if (is >> i) {
        // integer successfully retrieved from stream
    }
}

just #include <sstream>

Read the value with string. if it doesn't match | convert it to double using the following function:

double toDouble(string s)
{
   int sign = 1, i=0;
   if (s[0]=='-')
      sign = -1, i=1;

   double result = 0, result2 = 0;
   for (; i < s.size(); i++)
     if (s[i] == '.')
       break;
     else
       result = result * 10 + (s[i] - '0');

   for (i = s.size()-1 ; i>=0 ; i--)
     if (s[i] == '.')
        break;
     else
        result2 = result2 / 10 + (s[i] - '0');

   if (i>=0)
      result += result2/10;
   return result * sign;
}

Summing meters with inches does not make much sense. Therefore, you should consider to translate the units into scaling factors. You could use a map to get the scaling factors. Even if this is somewhat overshoot you might use regular expressions to parse the user input. If the regex does not match you can test for stuff like "|". In the new c++-standard ( http://en.wikipedia.org/wiki/C%2B%2B11 ) a regex library is defined for this purpose. Pityingly, the g++ regex library is buggy. But you can use boost ( http://www.boost.org/doc/libs/1_54_0/libs/regex/doc/html/boost_regex/ ). Here is an example:

#include <iostream>
#include <vector>
#include <map>
#include <boost/regex.hpp> //< Pittyingly std::regex is buggy.

using namespace std; ///< Avoid this in larger projects!
using namespace boost;

int main() {

const string strReFloat("([-+]?[[:digit:]]*\\.?[[:digit:]]+(?:[eE][-+]?[[:digit:]]+)?)");
const string strReUnit("([[:alpha:]]+)");
const string strReMaybeBlanks("[[:blank:]]*");
const string strReFloatWithUnit(strReMaybeBlanks+strReFloat+strReMaybeBlanks+strReUnit+strReMaybeBlanks);
const regex reFloatWithUnit(strReFloatWithUnit);

const map<const string,double> unitVal= {
    {"m", 1.0},
    {"in", 0.0254},
    {"ft", 0.3048},
    {"cm", 0.01}
};

double highest = 0;
double lowest = 100;
int i=0;
double sum = 0;
vector <double> inputlist;
double input;
double unitToMeter;
string unit;
string str;

while( (cout<<"\nType in a number followed by it's unit \n", getline(cin,str), str != "") ){

    smatch parts;

    if( regex_match(str,parts,reFloatWithUnit) ) {
        unit = parts[2].str();

        auto found = unitVal.find(unit);
        if( found != unitVal.end() ) {
            cout<<unit<<"\n";
            input = found->second * atof(parts[1].str().c_str());
        } else {
            cout << "Unit \"" << unit << "\" not recognized. Using meters.\n";
        }

        inputlist.push_back(input);
    sum += inputlist[i];

    if (input >= lowest && input <= highest){
        cout<<input<<" \n";
        ++i;
    }
    else if (input < lowest){
        lowest = input;
        cout<<"\nLowest Number so far \n"<<lowest;
    ++i;
    }

    else if (input > highest){
        highest = input;
                cout<<"\nHighest number so far \n"<< highest;
                ++i;
    }

    } else if( str == "|" ) {
        cout << "sum:" << sum << "\n";
    } else {
        cout << "Input not recognized.\n";
    }
}

return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM