How to double numeric value from a string read from console

Here is the code in question: it can read from the console and parse the string, but I want it to parse the string with initial numeric value doubled. For example....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>

int main()
{
	std::string str;
	getline(std::cin, str);
	std::cout << "You entered: '" << str << " ' " << std::endl;

	std::istringstream buf(str);
	std::istream_iterator<std::string> beg(buf), end;

	std::vector<std::string> tokens(beg, end);

	for (auto& s : tokens)
		std::cout << '"' << s << '"' << '\n';
	system("PAUSE");
}



::DESIRED OUTPUT::

Parse this string 10
You entered: 'Parse this string 10 '
"Parse"
"this"
"string"
"20"
::DESIRED OUTPUT::


Currently it just says

Parse this string 10
You entered: 'Parse this string 10 '
"Parse"
"this"
"string"
"10"

That's not what I'm looking for. Any help would be greatly appreciated!
Last edited on
Use std::transform:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main() {
    std::vector<std::string> tokens; 
    
    using it = std::istream_iterator<std::string>;
    std::transform(it{std::cin}, it{}, std::back_inserter(tokens),
                   [](std::string const& s) {
                     int i; std::stringstream str{s};
                     if(str >> i)
                        return std::to_string(i * 2); 
                     else return s;
                   });

    for (auto const& s: tokens) 
        std::cout << std::quoted(s) << '\n'; 
}

Demo:
http://coliru.stacked-crooked.com/a/3155b633ffcbb1b6

An appropriate library would make this particular task nicer. Boost.Range or Eric Niebler's library ( https://github.com/ericniebler/range-v3 ) could help, for example.

(Or not - it's relatively clean already.)
Last edited on
Put
s = filter( s );
between lines 18 and 19 of your code, with filter() as below.

1
2
3
4
5
6
7
8
9
10
11
12
13
std::string filter( std::string s )
{
   try
   {
      int d = std::stoi( s );                // use for ints only
//    double d = std::stod( s );             // use for doubles, but little control over formatting
      return std::to_string( 2 * d );
   }
   catch( ... )
   {
      return s;
   }
}
Last edited on
1. Using std::regex to handle negative and decimal numbers
2. cut down a line of code by initializing the std::vector<std::string> directly with the std::istringstream object's initialization:
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
31
32
33
34
35
36
37
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
#include <regex>

int main()
{
	std::string str;
	getline(std::cin, str);
	std::cout << "You entered: '" << str << " ' " << std::endl;

	std::istringstream buf(str);
	//std::istream_iterator<std::string> beg(buf), end;

	std::vector<std::string> tokens(std::istream_iterator<std::string>(buf), {});//C++11
	std::regex number("(-)?[0-9]+(\\.[0-9]+)?");

	for (auto& s : tokens)
    {
       if(std::regex_match(s, number))
       {
           std::istringstream stream{s};
           double num{};
           stream >> num;
           num *= 2;
           std::ostringstream stream_double;
           stream_double << num;
           s = stream_double.str();
           //wrap code within this loop into a function
       }

		std::cout << '"' << s << '"' << '\n';
    }
	//system("PAUSE");
}

regex is a big beast to explain off-hand but if you wish to explore this solution try below for a C++ specific starter and then further search:
http://www.cplusplus.com/reference/regex/ECMAScript/

Avoid using a custom regular expression to parse floating point numbers. There are too many edge cases to handle; a correctly written regular expression would be horrendously complex.
For instance all these are all valid representations of numbers: 1.23e-99, inf, 0xab.cdP-23
On most implementations, this is not (it is out the range of values that can be represented): 1.0e56789

Let either a string stream or std::stold do the heavy lifting; in both cases incorporate checks for failure.

Something like this, perhaps:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

// if the string contains the representation of a number
// place the value of the number in var and return true
bool parse_number( const std::string& str, long double& var )
{
    try
    {
        // http://en.cppreference.com/w/cpp/string/basic_string/stof
        std::size_t parsed_till ;
        const auto num = std::stold( str, std::addressof(parsed_till) ) ;
        if( parsed_till == str.size() ) // if fully parsed
        {
            var = num ;
            return true ;
        }
    }

    catch( const std::exception& ) {}

    // if we get here, either str does not contain the representation of a number
    // or the value it represents is out side the range of numbers that we can handle
    var = 0 ;
    return false ;
}

int main()
{
    std::string str;
    std::getline( std::cin, str );
    std::cout << "You entered: " << std::quoted(str) << '\n' ;

    std::istringstream stm(str);
    std::string token ;
    while( stm >> token )
    {
        long double number ;
        if( parse_number( token, number ) ) std::cout << number*2 << '\n' ;
        else std::cout << std::quoted(token) << '\n' ;
    }
}
Topic archived. No new replies allowed.