0

Total newb here, so go easy :) I've googled and can't really seem to find an elegant solution to this. I'm doing some coding to learn a few concepts.

I have a class - called 'sally' which has a constructor which is overloaded twice i.e. my sally.cpp is:

#include "sally.h"
#include <iostream>
#include <string>
using namespace std;


sally::sally()
{
}
sally::sally(int x)
{
    inputvarint = x;
    cout << "you have an int of value: " << inputvarint << endl;
}

sally::sally(string y)
{
    inputstring = y;
    cout << "you have a string that is: " << inputstring << endl;
}

in my main.cpp if I create the object sally myobj; and then call the function via the object, i.e. sally.myobj(55) I get the correct constructor firing off and telling me I have an INT of value whatever, or if I go sally.myobj("johhny") I get the other constructor going and telling me I have a string that says "johnny", so that part I get fine.

What I would like to know is, is there an elegant way I can use CIN to take input from a user, and either pass it straight to the object - without using a variable ( i've tried and can't get it to work ).

Basically, I'd like the user to be able to enter either a string, or an int and use that in the sally.myobj(); call, and let the constructor(s) do the work of figuring out what type of data it is.

things like: auto x = 0; and then cin >> x don't work as the initial declaration was an int, so it stays like that.

Is there a way to declare a variable without a type and assign it a type based on the input from CIN?

Apologies if the answer to this is blindingly obvious, but i'm at the very beginning of my journey ( I'm up to about tutorial 40 of this guy: http://www.youtube.com/watch?v=tvC1WCdV1XU ) and also reading C++ Primer by Stanley Lippman ( 5th edition ) and The Object-Oriented Thought Process by Matt Weisfield. They are my only resources at present ( that and google ).

Thanks in advance

Seb

EDIT:

After seeing some of the responses below, it helped me figure out what can/can't be done and I've tackled it this way using a parsing function which utilises some Regex, and if string content is deemed to be INT then converts it and places it into a new variable and off to the constructor:

Sally.cpp:

#include "sally.h"
#include <iostream>
#include <string>
#include <regex>
using namespace std;

sally::sally()
{
}
sally::sally(int x)
{
    inputvarint = x;
    cout << "Constructor output: you have an int of value: " << inputvarint << endl;
}

sally::sally(string y)
{
    inputstring = y;
    cout << "Constructor Output: you have a string that is: " << inputstring << endl;
}
void sally::StringParser(string x){

regex e("^[0-9]+$"); //test if the string starts with ends with and has a whole lot of numbers in between, i.e. and INT of any length

bool match = regex_match(x, e);

if(match){
    cout << "you have an int" << endl;
    int newvar = atoi(x.c_str());
    sally::sally(newvar);
}
else {sally::sally(x);}


}

then I simply sally myobj; and myobj.StringParser(x); whereby x is the input from CIN and the Parsing function takes care of the rest and passes it to the constructors.

I'm sure I could build this out a bit with a SWITCH statement with different REGEX's to handle floats etc and then create additional constructors. But For now, I seem to have found a solution.

Keen to see if there are any issues with my approach.

  • 3
    C++ is statically typed. You cannot enter "either an integer or a string". You *always* enter a string. *Sometimes* it may make sense to parse that string as an integer. But that has to be decided at runtime. – Kerrek SB Apr 05 '13 at 08:20
  • In other words, what you're looking for is a *parser* (or a "lexer" perhaps). – Kerrek SB Apr 05 '13 at 08:21
  • @Kerrek SB - your comments about parsing gave me a lightbulb moment. Thanks :) – Sebastiaan Stoffels Apr 06 '13 at 01:50

3 Answers3

1

Unfortunately there is really no way to do that.

What you can do is read the input as a string, and then try to convert it to an integer with e.g. std::stoi and if it succeeds you have an integer.


An alternative which does not throw exceptions is to use std::strtol instead.

Some programmer dude
  • 363,249
  • 31
  • 351
  • 550
1

I think c++ variables must always have a type. IN this case is better to save it as a string and then evaluate it. If its a number, convert to int and pass to the constructor: If its not a number pass the string to the constructor You can check if its a number using something like this:

bool is_number(const std::string& s)
{
  std::string::const_iterator it = s.begin();
  while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

from How to determine if a string is a number with C++?

For converting the string to an int, there a various ways, but you can try this one:

string str = "123";
int numb;
istringstream ( str ) >> numb;

So the final idea would be something like:

get input as a string
if(input is a number)
{
  convert to number;
  call constructor;
}
else
  call constructor with the string

Hope helped you out.

Community
  • 1
  • 1
MRodrigues
  • 1,657
  • 16
  • 19
  • Unfortunately even this approach still leaves the ambiguity between an 2 and "2". Using the suggested method there's no way to construct **sally("7")** as it will always turn into **sally(7)** instead. – mikyra Apr 05 '13 at 08:38
  • Yes, you're right. I just assumed that if the input was 7 or any other digit, then it goes as sally(7). – MRodrigues Apr 05 '13 at 08:43
  • This was very useful. @mikyra you are right about that, but then, only the user would know if they intended their (7) to be an int or string. I guess I could program in some kind of escape character in case a user wanted to enter a number as a string, and handle it that way. – Sebastiaan Stoffels Apr 06 '13 at 02:00
0

The problem you are encountering is not one specific to C++,. but a general problem regarding input encoding.

Without adding some additional information to your input it is impossible to achieve the desired operation.

As you are reading character input if given the input '2' there is no chance to make difference between to following two usage scenarios:

  • you want to call sally (2)

  • you want to call sally ("2")

You will have to supply some additional (type) information in the input to distinguish between this two cases ("i:2" and "s:2" for example) and try to parse the indicated value.

mikyra
  • 9,041
  • 38
  • 41