What is causing this output typo? [duplicate] - c++

This question already has answers here:
How do you append an int to a string in C++? [duplicate]
(20 answers)
How to concatenate a std::string and an int
(25 answers)
Why can you add an integer to a string literal?
(1 answer)
Adding strings and literals (C++)
(3 answers)
Closed last month.
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.

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.

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();
}

Related

Stringing together multiples of the same string (an asterisk) determined by an input file. C++

Essentially, the objective is to read an input file (hence inFile and inFileName) and output a population growth with asterisks representing each 1000 people using an ID (ex. 1375892), going from the year 1900 to 2020 in 20-year increments.
So, 1 asterisk for 1000 people, 3 asterisks for 3000 people, etc. The input file has numbers like 5000 and 7000 that I need to use to calculate the number of asterisks I need (by dividing by 1000). Even with that, I'm trying to figure out the final step in converting asteriskNum (the number of asterisks I need to use) and have it output the string of asterisks, not an integer of how many asterisks I need.
I definitely know I'm missing SOMETHING, but even after asking my teacher and scouring through my textbook and notes, I can't figure out how to solve this specific issue.
#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
using namespace std;
int main(){
string asterisk = "*";
string firstName;
int PopNum{0};
int year{1900};
int asteriskNum{};
const string INTROLINE{"POPULATION GROWTH \n(each * represents 1000 people)"};
cout << INTROLINE << "\n";
string inFileName="DL8_L5_Morrison.txt";
ifstream inFile{inFileName};
if (inFile){
cout << inFileName << " opened for reading. \n";
inFile >> firstName;
while (not inFile.eof()){
inFile >> PopNum;
asteriskNum = PopNum/1000;
cout << year << " " << asteriskNum << " " << << "\n";
year+=20;
inFile.close();
}
else {
cout << inFileName << " did not open for reading. \n";}
cout<<"Goodbye!\n";
return EXIT_SUCCESS;
}
}
You can use a std::string object and use the constructor that takes a count and character as arguments (constructor version #2 here). This will work with an int for the count argument, but it is better to cast it to a size_t type (or just have the calculated value as a size_t in the first place):
//...
asteriskNum = PopNum/1000;
cout << year << " " << std::string(static_cast<size_t>(asteriskNum), '*') << std::endl;
//...

Simple one line class method returning wrong value

I am having a weird issue and I don't know what's wrong.
I have a class publication composed of the class members string headline and string text.
I also have a class called publication_and_date which inherits from publication, but also has an additional field called string date which represents the date a certain article was published.
I also have a class news that inherits from publication_and_date, and has the additional field of string sources
The problem is this: I have an object of type news, and when i use the method get_date of that object, I get the value M.
Here is my void main:
void main()
{
news MyNews;
MyNews.set_date(3,12,2016);
MyNews.set_sources("IGN");
MyNews.set_headline("MGS V wins GOTY award");
MyNews.set_text("Metal Gear Solid V won the prestigious game of the year award!");
cout << MyNews.ToString();
getch();
}
This is the implementation of the class publication_and_date:
publication_and_date::publication_and_date() : publication()
{
date="1/9/2015";
}
void publication_and_date::set_date(const int NewDay,const int NewMonth,const int NewYear)
{
if((NewDay > 31)||(NewDay < 1)||(NewMonth > 12)||(NewMonth < 1)||(NewYear<2015)) //input check
{
cout << "\nDate is invalid\n";
return;
}
date=NewDay + '/' + NewMonth + '/' + NewYear;
}
string publication_and_date::get_date()
{
return date;
}
As you can see, the method get_date() is very simple. It's just one line.
I don't know why the value I'm getting is M.
The output of the void main I gave you is:
Headline: MGS V wins GOTY award
Text: Metal Gear Solid V won the prestigious game of the year award!
Date: M
Sources: IGN
I'm completely baffled as to why this happens. Would appreciate help.
Edit1: This is the code for ToString
string news::ToString()
{
string ToReturn;
ToReturn="\nHeadline: " + get_headline() + '\n' + "Text: " + get_text() + '\n'+"Date: " + get_date()+'\n'+"Sources: " + get_sources();
return ToReturn;
}
Edit2:
I think I know what the problem is. NewDay, NewMonth,NewYear are integers. So the + operator is not the same as with strings. I need to somehow make them chars.
You are getting an M or something else random because you add up the numbers rather than concatenate strings. A char '/' is actually a small integer with the value of 47.
One way to convert everything into a string is to use a stringstream (located in sstream header):
std::stringstream ss;
ss << NewDay << '/' << NewMonth << '/' << NewYear;
date = ss.str();
A string stream is just like your regular iostream, but it works on strings. It will do the right thing with regards of type conversions.

How do you extract a string that is in between a char/string in C++?

Let's say I have a simple string:
string example = "phone number: XXXXXXX,"
where X are random values given to me, so they are always different.
How do I extract only the X's?
"phone number: " doesn't change.
what I have now (using Thomas Matthews technique below)
const char search_text[] = "phone number: ";
std::string::size_type start_posn = example.find(search_text);
std::string::size_type end_posn = example.find(",", start_posn);
const unsigned int length = end_posn - start_posn - sizeof(search_text) - 1;
cout << "length: " << length << endl;
std::string data = example.substr(start_posn, length);
cout << data << endl;
what if I had string example = "phone number: XXXXXXX, Date: XXXXXXXX,"?
Hmmm, looks like you would search for "phone number: " and then determine the index or position after the phrase. Your requirements infer that there is a "," after the data you want.
So, you want the substring between the ": " and before the ",". In the olden days, we would search for the "," and get its position. The number of characters to extract is obtained by subtracting the two indices:
Edit 1
const char search_text[] = "phone number: ";
std::string::size_type start_posn = example.find(search_text);
if (start_posn != std::string::npos)
{
start_posn += sizeof(search_text) - 1;
}
std::string::size_type end_posn = example.find(",", start_posn);
const unsigned int length = end_posn - start_posn;
std::string data = example.substr(start_posn, length);
Note: the above code does not handle error cases where the find method returns std::string::npos.
Using the above technique, how would you extract the data after "Date: "?

Output shows no zero

FYI I'm a beginner in C++. This is just a part of the complete code, the problem is the 'student.id', if the input starts with '0' e.g.'06042010', the output shows no zero(in this case would be '6042010'! And the point is, I want that first zero to be shown. Thanks.
#include<iostream>
using namespace std;
struct students
{
char name[15];
char surname[10];
int id;
};
int main()
{
students student;
cout<<"Name: ";
cin>>student.name;
cout<<"Surname: ";
cin>>student.surname;
cout<<"ID: ";
cin>>student.id;
cout<<"\nStudent: "<<student.name<<" "<<student.surname<<" ID "<<student.id<<endl;
return 0;
}
If you need to preserve leading zeros, you should store id as a string and not an int.
If your IDs will always be a particular length, you can use C's printf function instead of streams, which gives you more power;
printf( "Student: %s %s ID %08d\n", student.name, student.surname, student.id );
That will always print 8 digits of ID, and will prefix with 0s as needed (if it was just %8d it would prefix with spaces).
But as already pointed out, you're likely better off storing it as a string, because then you will be able to increase the length of the IDs in the future without needing to adjust all the old IDs.
If you need or want to keep the student id a number for some reason you can also us the following:
#include <iomanip>
const int width = 8; //The length of your student ID numbers
cout << "\nStudent: " << student.name << " " <<student.surname
<< " ID " << setfill('0') << setw(width) << student.id << setfill(' ') << endl;
If your ID numbers are not all the same length you will have to detect how long they are and use the appropriate width in each setw() call.

How to combine strings and ints to a single string (C++) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ concatenate string and int
I am tryinging to make use many strings and ints to make a single string but I am getting the message: "error C2110: '+' : cannot add two pointers"
This is my code:
transactions[0] = "New Account Made, Customer ID: " + ID + ", Customer Name : " + firstName + " " + secondName + endl + ", Account ID: " + setID + ", Account Name: " + setName;
(note that ID and setID is an int)
Use a stringstream:
#include <sstream>
...
std::stringstream stm;
stm<<"New Account Made, Customer ID: "<<ID<<", Customer Name : "<<firstName<<" "<<secondName<<std::endl<<", Account ID: "<<setID<<", Account Name: "<<setName;
You can then access the resulting string with stm.str().
You should use a string stream: write the string into it; then write the int. Finally, harvest the result through the str() method of the stream:
stringstream ss;
string hello("hello");
int world = 1234;
ss << hello << world << endl;
string res = ss.str();
cout << res << endl;
Here is a link to a demo on ideone.