Converting int to string with to_string

I'm basically just practicing classes right now. I am trying to write a program that just holds some basic information in a .txt file then I'm going to open it and print it to console screen.

I fixed this problem by just turning the int's on the phoneNum declarations through the program to strings. I would still like to know how I could make this work with int's for the phoneNum areas: (I will then put in the dashes between numbers, like 123-456-7890)

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
     #include <iostream>
#include <string> 
#include <fstream>
#include <sstream>
using namespace std;
class Personal {
    public:
    void setName(string n) {
        name = n;
    }
    void setAddress(string  a) {
    address = a;
    }
    void setAge(int a) {
        age = a;
    }
    void setPhone(int p) {
        phoneNum = p;
    }
    string getName() {
        return name;
    }
    string getAddress() {
        return address;
    }
    int getAge() {
        return age;
    }
    int getPhone() {

        return phone;
    }
    private:
    string name;
    string address;
    int age;
    int phoneNum;

    };

int main() {
    Personal info;
    string userName;
    string userAddress;
    int userAge;
    int userPhone;
    cout << "Enter your name" << endl;
    getline (cin,userName);
    cout << "Enter your Address" << endl;
    getline (cin,userAddress);
        cout << "Enter your age" << endl;
    cin >> userAge;
        cout << "Enter your Phone #" << endl;
    getline (cin,userPhone);


    info.setName(userName);
    info.setAddress(userAddress);
    info.setAge(userAge);
    info.setPhone(userPhone);

    ofstream myFile;
    myFile.open("myInfo.txt");
    if (myFile.is_open())
    {
        myFile << info.getName() << endl;
        myFile << info.getAddress() << endl;
        myFile << info.getAge() << endl;
        //~ myFile << to_string(info.getPhone()) << endl;
    myFile << info.getPhone() << endl;
        myFile.close();
    }
    else cout << "Unable to open file";
    return 0;
}


I am also aware I probably need a to_string somewhere, but I have tried many places and maybe I am doing something wrong. I have tried to_string in set/getPhone member function, within the actual getline and tried a few things within the .txt file area.

Where do I put the to_string or maybe something else needs to be done? I'm getting a ton of errors.

Thanks!
One of your problems is that you have defined phoneNum as an int instead of a string. Just becase something has number in it's name doesn't mean it should be stored as a number.

Once you convert all your phone numbers to a string the program should compile.

Ok, thanks for the response. I have actually already done that, but I was wondering how I would do it with int's. There has to be a way to receive a number like 1234567890 convert it to a string and use getline to store it. Then I would add in the parenthesis later.

Is it just much better to use a string? Could you elaborate on why you should only use strings for something like a phone number?

Thanks!
IMO, yes. Normally users will try to either put spaces or the dashes into a phone number, because that is the way they "see" a phone number. Also remember you can't be sure a phone number will always fit in an int (don't forget about "international" prefixes).

There has to be a way to receive a number like 1234567890 convert it to a string and use getline to store it.

First remember that getline() requires a stream and a string. You seem to be trying to use getline() with a stream and an int which won't work. You can use things like to_string() to convert a number to a string however it is usually less error prone just to store this in a string in the first place.


PS. Do you realize that telephone numbers at one time had letters as well as numbers, and that a phone number is really a "code" for the particular "line" being dialed?

Last edited on
Tad bit off topic, but why are your getters and setters all void? It’s just going to do nothing if it’s void, since it’s not returning the variables, is there a reason for that?

1
2
3
4
5
6
7
8
9
10
// dosn’t affect anything, never escapes scope of setVar so var not n
void setVar(int n){
  var = n;
}

// affects out side scope by returning var so var now n.
int setVar(int n){
  var = n;
  return var;
}
Last edited on
But look closer at his setters, the variable that is being modified is the class member variable. The member variable is altered, it will hold that value until the function is called again.

Here is another definition for your class. Didn't spend that much time on it so there could be some stuff I left out:

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <string>
#include <string_view>
#include <cstdint> //uint, uint64_t

class Personal 
{
    public:
        Personal(std::string_view    name, 
                 std::string_view    address,
                 uint                age,
                 uint64_t            phone_number);
    
        std::string_view    get_name()    const   { return m_name;    }
        std::string_view    get_address() const   { return m_address; }
        uint                get_age()     const   { return m_age;     }
        uint64_t            get_number()  const   { return m_number;  }
    
    //setters omitted for brevity
   
    private:
        std::string         m_name, 
                            m_address;
        uint                m_age;
        uint64_t            m_number; //Large enough to hold all sizes of numerical phone numbers

};

Personal::Personal(std::string_view    name, 
                   std::string_view    address, 
                   uint                age, 
                   uint64_t            number)

    : m_name(name.data()), 
      m_address(address), 
      m_age(age), 
      m_number(number)
    {}

int main()
{
   using namespace std;

    std::string userName;
    std::string userAddress;

    uint userAge;
    uint64_t userPhone;
    cout << "Enter your name" << endl;
    getline (cin, userName);
    cout << "Enter your Address" << endl;
    getline (cin, userAddress);
    cout << "Enter your age" << endl;
    cin >> userAge;
    cout << "Enter your Phone #" << endl;
    cin >> userPhone;
    
    Personal person1(userName, userAddress, userAge, userPhone);
    //...........

}


Use std::string_view instead of const std::string& and NEVER use "string" passed by value as a function parameter (deleted, courtesy of @Dutch) and only use std::string directly when you need pass by value mechanics. Most of the time, when you want read-only access to a string, you can use std::string_view instead of const std::string&. This is more efficient since std::string_view will not make copies of the string and it is very cheap itself to copy since it just holds a pointer to the data. For example, if you ever pass a const char* in a function that accepts const std::string&, the compiler will implicitly generate an std::string object using its constructor, which may not be efficient. I also created a constructer which initializes the data with your user information. This is better than creating 4 different function calls to do the same thing.

EDIT: Also, a quick tip. Try not to use "std::endl" especially not in file streams. std::endl not only enters a newline character, but also flushes the buffer. This can have a huge impact on performance if you are writing lets say hundreds of lines to a file in a while loop. Try to use '\n' instead.

Last edited on

Use std::string_view instead of const std::string& and NEVER use "string" passed by value as a function parameter. This is more efficient since std::string_view will not make copies of the string and it is very cheap itself to copy since it just holds a pointer to the data.

There are times when passing a std::string by value is acceptable, for instance you want to create a "duplicate" inside the function so that the passed string can be changed for the duration of the function but not change the original outside the function. Also there are places where passing a string_view() will not be acceptable.

@KishgoreG, maybe you should stick to asking questions since you obviously don't know what you're talking about.
You could keep sections of the phone number maybe?
1
2
3
4
5
6
7
#include <cstdio>

int telephone1,telephone2,telephone3;

Scanf("%3i",&telephone1); //only takes three of the inputted characters in the console 
Scanf("%3i",&telephone2);
scanf("%3i",&telephone3);



I might me messing up the subscript a bit but the link is here
http://www.cplusplus.com/reference/cstdio/scanf/?kw=scanf

Edit: I did mess it up! Fixed now.
Last edited on
Bad dutch. No biscuit. There are much politer ways to communicate that KishoreG is spreading bad advice (albeit born out of a decent guideline).

And mind you, it is born out of a decent guideline. In most cases, people passing std::string by value would be better served by passing it by const reference. In many cases, people passing std::strings around would be better served by passing std::string_views.

-Albatross
@Dutch Here's my advice to you, friend. You should treat others respectfully and not be an asshole. We are all here to learn. He made a simple comment that might not be true in all cases, and instead of correcting him you berate him for being new. That is extremely arrogant and demeaning.
Dutch, thank you for your kind advice. I have changed my original comment to elucidate. I intended to tell OP that using std::string_view is often better than const string& or passing std::string directly by value is often not the best option (in this case). I sincerely thank you for providing your technical expertise and expert opinion on this matter.

I apologize that my comment was not up to your standards in technical expertise and sincerely hope that you do not find my lack of experience on this forum contemptible. You have indeed mastered all there is to know about programming and that is evident by the fact that you have 800+ posts on this forum. Well done.
Last edited on
Hello frza45,

In everyone's attempt to find the most advanced answer to your problem I believe that they have missed the most fundamental part.

Each numerical variable type has a finite number it can store.

An example is an "int" which is generally four bytes can store a number between (-2,147,483,648 to 2,147,483,647) and the unsigned version is (0 to 4,294,967,295).

Compared to a phone number of (9995551234) or (9,995,551,234). You can see that the phone number is larger than an "int" can store.

Most often an "unsigned long long" is used to store a phone number. This can store a number up to (18,446,744,073,709,551,615) which is large enough to store a phone number as a numeric variable.

For what you want to do it would be simpler to store the phone number as a string to begin with. Then you can manipulate it any way you like.

These are some links I found that will in some way help you understand the size limits of different variable types. Not exactly what I was looking for, but useful:
https://www.geeksforgeeks.org/c-data-types/
http://www.cplusplus.com/reference/limits/numeric_limits/
http://www.cplusplus.com/doc/tutorial/variables/
All information is good some just not easy to understand at first.


To answer your question. Start with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// in the class.
unsigned long long  phoneNum;

// Or as KishoreG has shown.
unsigned long long m_phoneNum;

// Change your "get" and "set" functions to return an "unsigned long long" and set the same.

// In "main".
unsigned long long userPhone;
std::string sUserPhone;  // <--- Added.

// On line 54 change the "getline" to:
std::cin >> userPhone;  // <--- Changed.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

// Once the phone number is in a numeric variable you can use:
sUserPhone = std::to_string(userPhone);

// Or
sUserPhone = std::to_string(info.getPhone());

When mixing the unformatted input of "getline" and formatted input of "stdcin >> userPhone;". The formatted input will leave the new line in the input buffer. The "std::cin.ignore()" will clear the input buffer before the next use of "getline". Otherwise the next "getline" will take the new line from the input buffer and move on never giving you the chance to enter anything. Two things about "std::getline". As mentioned earlier "getline" only works with a "std::string" as the second parameter and "getline" will eat the new line and discard it leaving an empty input buffer.

The "ignore" statement shown is the more portable version that any operating system and set of header files can use as some setups are different in the sizes. If it is possible, follow the last formatted input with the "ignore" function.

As the bits of code show there are two ways to use "std::to_string" to convert the numeric variable into a string. Exactly where to use it will depend on what you want to do where. The variable "sUserPhone" was a quick way to use the same basic variable name where the "s" reminds me that it is defined as a string. You are free to choose another name if you like.

For KishoreG's code there are many parts that are worth taking note of.

The way he/she, sorry not sure which, defined the "classs" is good. I like the use of the overloaded ctor and breaking up the class definition and function definitions into separate parts. This is a good practice to get use to because some day you will be putting the "class" definition in a header file and the functions in a ".cpp" file.

I have read several tutorials that suggest using the "m_" as a prefix to the "private" variable names. When using the overloaded ctor or a set function the parameter can use std::string name and inside the function you would use m_name = name;. Just a concept to keep in mind.

In "main" a few blank lines would be helpful, but answer all the questions then create an object of the class using the overloaded ctor. This has potential when you put most of "main" in a loop.

A suggestion. You may find this of more use than what you have:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{
	Personal info;
	string userName, userAddress;
	int userAge;
	unsigned long long userPhone;

	cout << "\n Enter your name (First last): ";  // Or "\n Enter your name (Last,  First): ".
	getline(cin, userName);

	cout << "\n Enter your Address (Number street, City, State, Zipcode): ";
	getline(cin, userAddress);

	cout << "\n Enter your age: ";
	cin >> userAge;

	cout << "\n Enter your Phone # (2025551234): ";
	cin >> userPhone;

	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>. 

Combining more than one variable on a single line is acceptable, but you can define each variable on its own line if you want. Different types require their own line.

Beginning each "cout" with the "\n ", and this may be just a personal thing with me, I find that one line off the top edge and one character in makes it easier to read.

I find that the parts in ()s help the user to know what to enter or how you want the information entered.

For the name (Last, First) can be useful in the future if you need to break up the full name into two parts. The comma can be used as a separator should either name have a space in it.

I have also found that ending the prompt with ": " and no "endl" will put the input on the same line. Most of the time this works unless the prompt is long and the input is long. Then you might want to break it into two lines.

After that a few blank lines makes the code easier to read and that is an important point both for you and others.

Hope that helps,

Andy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <string>
#include <sstream> // to use std::ostringstream

using namespace std;

// Let's implement our simple converter function
string to_string( int n )
{
    ostringstream oss;
    oss << n;
    return oss.str();
}

int main()
{
    int n = 5;
    string s = to_string( n );
}


general function that converts anything to a string
1
2
3
4
5
6
7
template< class Type >
string to_string( Type t )
{
    ostringstream oss;
    oss << t;
    return oss.str();
}
Last edited on
Let's implement our simple converter function

If you want to, fine, but you really should rename your function so that it doesn't possibly clash with std::to_string(), especially since you seem to be using that using statement.

Registered users can post here. Sign in or register to post.