input variable string or integer

i am struggling to create a program which takes multiple inputs and determines if they are a string or a number than outputting weather the input is valid or not (input is valid if input argument is a number that may contain decimals). eg. if
"yo man hi 13.9867" is entered program will output
invalid
invalid
invalid
13.9867

(not real code just idea)

if (input is number)
cout the number
else
cout invalid
You could use http://www.cplusplus.com/reference/string/stod/
but then you have to handle exceptions.

http://www.cplusplus.com/reference/cstdio/sscanf/
requires a bit different error handling.

Streams http://www.cplusplus.com/reference/sstream/istringstream/istringstream/
are yet another possibility.


The base logic is that you do have a word that might be a number. If you can get a number from the word and no characters are left unused, then the whole word is a number.

For example, 3.14A is not a number.
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
# include <iostream>
# include <string>
# include <sstream>
# include <cctype>
# include <algorithm>
# include <vector>
# include <utility>
# include <iterator>

void word_checker(const std::string& word)
{
    if(((word.find('.')) != std::string::npos)
            && (static_cast<std::string::size_type>(std::count_if(word.cbegin(), word.cend(), ::isdigit)) == (word.size() - 1)))
    {
        std::cout << "valid \n";
    }
    else
    {
        std::cout << "invalid \n";
    }
}

int main()
{
    std::string input = "yo man hi 13.9867";
    std::istringstream stream{input};
    std::vector<std::string> word_vec(std::istream_iterator<std::string>(stream), {});
    //https://stackoverflow.com/questions/455483/going-from-string-to-stringstream-to-vectorint
    for (const auto & elem : word_vec)word_checker(elem);
}

edit: also check the '.' is in the 'right' place of the number string
Last edited on
I use this all the time:

1
2
3
#include <sstream>
#include <stdexcept>
#include <string> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template <typename T>
bool string_to( const std::string& s, T& result )
{
  // Convert string argument to T
  std::istringstream ss( s );
  ss >> result >> std::ws;
 
  // Stream should be in good standing with nothing left over
  return ss.eof();
}

template <typename T>
T string_to( const std::string& s )
{
  T result;
  if (!string_to( s, result ))
    throw std::invalid_argument( "T string_to<T> ()" );
  return result;
}

Or this variation:
1
2
3
#include <optional>
#include <sstream>
#include <string> 
1
2
3
4
5
6
7
8
9
template <typename T>
boost::optional<T> string_to( const std::string& s )
{
  T result;
  std::istringstream ss( s );
  ss >> result >> std::ws;
  if (ss.eof()) return result;
  return boost::none;
}

You can then attempt to convert an input string to the desired type. If it succeeds then it is valid. If it fails it is not.

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
  std::string s;
  std::cout << "Enter numbers:\n";
  while (getline( std::cin, s ) and !s.empty())
  {
    double n;
    if (string_to<double>( s, n )) 
      std::cout << "You entered the number " << n << ".\n\n";
    else
      std::cout << "That was not a number.\n\n";
  }
}
or
1
2
3
4
5
6
7
8
9
10
11
int main()
{
  std::string s;
  std::cout << "Enter numbers:\n";
  while (getline( std::cin, s ) and !s.empty())
  {
    auto n = string_to<double>( s );
    if (n) std::cout << "You entered the number " << *n << ".\n\n";
    else   std::cout << "That was not a number.\n\n";
  }
}

Hope this helps.
Topic archived. No new replies allowed.