6

I am coding this simple program which is supposed to create a user profile with given attributes. I am testing the method view_profile() which is supposed to just return a string with the values given from the constructor. When I run the program I get no errors, but the output is not expected. I am wondering why in the output the Name: Sam Drakillanouns is appearing, instead of Name: Sam Drakilla, also, age variable is not showing.

#include <iostream>
#include <vector>
using namespace std;

class Profile {
private:

  string name;
  int age;
  string city;
  string country;
  string pronouns;
  vector<string> hobbies;

public:
  
  //Constructor
  Profile(string name1, int age1, string city1, string country1, string pronouns1 = "they/them") {
    name = name1;
    age = age1;
    city = city1;
    country = country1;
    pronouns = pronouns1;
  }

  //View Profile method
  string view_profile() {
    string bio = "Name: " + name;
    bio += "\nAge: " + age;
    bio += "\nCity: " + city;
    bio += "\nCountry: " + country;
    bio += "\nPronouns: " + pronouns;
    bio += "\n";
    return bio;
  }

};

int main() {
  Profile sam("Sam Drakkila", 30 , "New York", "USA", "he/him");
  cout << sam.view_profile();
}

My output is:

Name: Sam Drakillanouns:
City: New York
Country: USA
Pronouns: he/him

when is should be:

Name: Sam Drakilla
Age: 30
City: New York
Country: USA
Pronouns: he/him

I tried to check the constructor and method view_profile() but everything seems to be correct. I may be overlooking something since I am new to the C++ language.

Chris
  • 26,361
  • 5
  • 21
  • 42
  • 4
    `bio += "\nAge: " + age;` -- Hint -- what is the data type of `age`? Is that type compatible with being concatenated onto a string? – PaulMcKenzie Dec 24 '22 at 20:36

2 Answers2

5

bio += "\nAge: " + age;

The issue is that age is an int, and there is no overload of + that converts an int into a type that can be concatenated onto a std::string.

To fix this, the age must be converted to a string. A simple way is to use std::to_string:

bio += "\nAge: " + std::to_string(age);


As to what is happening when you didn't convert the integer to a string:

Since (I am assuming ASCII) the value of 30 is the "record separator", one of the control characters. So you basically wound up concatenating a control character onto the string, and not the string "30".

The operator + and += for std::string will allow single characters to be concatenated, and unfortunately, the code compiled with no errors due to the integer being converted to a character value.


Edit:

After looking more closely at your original code, it seems with the code you did have, the actual behavior is to increment the string literal "\nAge: " by 30 bytes, pointing to who-knows-where. This will actually yield undefined behavior if std::string uses this value as one to concatenate with.

Regardless, the age is converted to an integer 30, and whether it was used to "add" to the string as mentioned before, or increment a literal by 30 bytes, it still yielded the undesired behavior.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • there is no overload of `+`, but the program compiles – apple apple Dec 24 '22 at 20:42
  • @appleapple -- Yes, unfortunately it does. – PaulMcKenzie Dec 24 '22 at 20:43
  • 2
    I think it's good to also explain what actually happens. – apple apple Dec 24 '22 at 20:44
  • Thank you this makes sense and fixed it. I am coming from java so I am learning the new rules of C++. – user15442068 Dec 24 '22 at 20:53
  • @user15442068 -- I know in Java, you can do things like adding a value to a string, and things will just work correctly. In C++, you have to be careful -- yes, the code compiled, but as you can even see from my answer and subsequent edits, it isn't straightforward as to what really happens when you make this mistake. If you want a more foolproof way of output mixed types, then using `std::ostringstream`, as one of the other answers given, can be used to stream the output to a string. – PaulMcKenzie Dec 24 '22 at 21:09
  • @PaulMcKenzie Thank you for the explanation, I will definitely be looking at learning the ostringstream for future programs. – user15442068 Dec 24 '22 at 21:14
1

Adding an int into a string is the source of your problem. I suggest you use a std::stringstream to build up your string, and view_profile can be marked const because it is safe to call on a constant Profile object.

  std::string view_profile() const {
    std::ostringstream ss;
    ss << "Name: "     << name     << std::endl
       << "Age: "      << age      << std::endl
       << "City: "     << city     << std::endl
       << "Country: "  << country  << std::endl
       << "Pronouns: " << pronouns << std::endl;

    return ss.str(); 
  }
Chris
  • 26,361
  • 5
  • 21
  • 42