Output comes out wrong - c++

I am teaching myself C/C++ at the moment, and I got the exercise (from the book I am reading) to write a program that could make an output like this:
Enter your first name: Flip
Enter your last name: Fleming
Here’s the information in a single string: Fleming, Flip
Using Structures. But my output comes out like this:
Enter your first name: Flip
Enter your last name: Fleming
Here’s the information in a single string: ,
Here is the code. It's fairly short and simple so it shouldn't be hard to read :)
#include <iostream>
#include <cstring>
using namespace std;
struct Person {
char* firstName;
char* lastName;
};
char* getName(void);
int main() {
Person* ps = new Person;
cout << "Enter your first name: ";
char* name;
name = getName();
ps->firstName = name;
cout << "Enter your last name: ";
char* lastname;
lastname = getName();
ps->lastName = lastname;
cout << "Here's the information in a single string: "
<< ps->lastName << ", " << ps->firstName;
delete ps;
delete name;
delete lastname;
return 0;
}
char* getName() {
char temp[100];
cin >> temp;
cin.getline(temp, 100);
char* pn = new char[strlen(temp) + 1];
strcpy(pn, temp);
return pn;
}

First, there's no such thing as C/C++. You're mixing them, which is wrong. Since you're using C++ headers/new/using, I'll assume you want C++, so here's how you fix your code:
replace all char* and char[] with std::string
get rid of dynamic allocation
So, some changes would be:
struct Person {
std::string firstName;
std::string lastName;
};
or
Person ps;

You are using:
cin >> temp;
cin.getline(temp, 100);
You probably overwrite what you already have with empty string at the end of a line.
Use just one of them.
If you'll stick with using cin >> you may consider setting width() to prevent buffer overflow.

First, the immediate problem is that you read twice from std::cin: first with operator>>, and then with getline. Pick one or the other.
But let's simplify your code a bit. There are simply too many sources of error. Pointers are tricky because they might point to the wrong thing, or you might forget to delete objects, or delete them twice. C-style char arrays as strings are bad because, well, they're not strings, and they don't behave like strings.
So let's use the standard library's string class:
#include <iostream>
#include <string>
struct Person {
std::string firstName;
std::string lastName;
};
std::string getName(void);
int main() {
Person ps;
cout << "Enter your first name: ";
std::string name = getName();
ps.firstName = name;
cout << "Enter your last name: ";
std::string lastname = getName();
ps.lastName = lastname;
cout << "Here's the information in a single string: "
<< ps.lastName << ", " << ps.firstName;
}
std::string getName() {
std::string temp;
std::getline(cin, temp);
return temp;
}
This is a fairly simple, almost mechanical substitution, basically just replacing char* by std::string, and removing the bits that are no longer necessary.
Of course, as pointed out in a comment, I've omitted all forms of error checking, which a real program should definitely do.

No no no, wayyyy too complicated. Use real C++ idioms. The program could be as simple as this:
#include <string>
#include <iostream>
int main()
{
std::string firstName, lastName;
if (!(std::cout << "Your first name: " &&
std::getline(std::cin, firstName) &&
std::cout << "Your last name: " &&
std::getline(std::cin, lastName) ))
{
std::cerr << "Error: unexpected end of input!\n";
return 0;
}
std::cout << "You are " << firstName << " " << lastName << ".\n";
}
As a variation on the theme, you could put each getline in a loop until the user inputs a non-empty line:
std::cout >> "Your first name: ";
for ( ; ; )
{
if (!(std::getline(std::cin, firstName))
{
std::cerr << "Error: unexpected end of input.\n";
return 0;
}
if (!firstName.empty())
{
break;
}
std::cout << "Sorry, please repeat - your first name: ";
}

Related

How do i make different responses to different user inputs?

I'm a beginner, so please excuse my silly mistakes.
I'm trying to get a specific output when I input a specific name using strings, but I keep getting an error that my name wasn't declared in the scope. I also want to be able to add different responses for different inputs.
I tried looking up how to use strings, and I tried all sorts of combinations, but I'm still confused as to what I did wrong.
I'm sorry if this doesn't make sense, I'm just really bad at explaining things.
#include <iostream>
#include <cmath>
#include <string>
int main() {
std::string firstname;
std::cout << "please state your name. \n";
std::cout << firstname;
std::cin >> firstname;
if (firstname == leo) {
std::cout << "oh, you.";
}
return 0;
}
First, std::cout << firstname; is a no-op since firstname is empty at that point.
Second, there is no name in your code. Is the error referring to leo? That should be wrapped in double-quotes since you meant it to be a string literal, not a variable.
Try something more like this:
#include <iostream>
#include <string>
int main() {
std::string firstname;
std::cout << "please state your name. \n";
std::cin >> firstname;
if (firstname == "leo") {
std::cout << "oh, you.";
}
else {
std::cout << "hello, " << firstname;
}
return 0;
}

C_string arrays, assigning first and last names to fullName (C++ Beginner)

I'm in my first CS class and I am having trouble getting this to compile. I have looked over my professor's notes, lectures, and examples but it doesn't seem to matter what I type, its an error. I'm getting 38 errors and there's only 25 lines of code! A lot of the errors don't make any sense, for example, "expected a ;" even though there is already a ';', Or "expected a {" after main even though it is clearly there. As far as I can see, visual studio should at least compile my code. Any help at all is much appreciated!
Step by Step Instructions/Correct Output:
Write a program that produces the following output:
/* OUTPUT
Enter your age: 21
Enter the last name: Lee
Hello Tom Lee. You are 21 years old.
Press any key */
1.) Declare an array named: firstName
The array is a c_string, i.e., it is a null-terminated character array.
The size of the array is 10.
Assign a first name to it when it is declared.
2.) Declare an array named: lastName
The array is a c_string,
The size of the array is 10.
Don’t assign a name to it.
3.) Declare an array named: fullName
The array is a c_string,
The size of the array is 20.
Don’t assign a name to it.
4.) In main():
First ask the user for the age.
Read the age and assign it to a variable.
Then ask the user for the last name.
Read the last name and assign it to lastName.
Assign the first and last names to fullName.
Make sure to include a space between the names.
5.) Call a function named: displayInfo().
The function should output the full name and age. (see output)
My code:
#include <iostream>
#include <string>
using namespace std;
void displayInfo(char fullName, int age)
int main
{
char firstName[10] = "Bob";
char lastName[10] = { 0 };
char fullName[20] = { 0 };
int age;
cout << "Enter your age: ";
cin >> age;
cout << "\nEnter the last name: ";
cin.getline(lastName, 10);
displayInfo(fullName, age)
strcpy_s(fullName, firstName);
strcat_s(fullName, " ");
strcat_s(fullName, lastName);
strcat_s(fullName, ".");
return 0;
}
displayInfo(char fullName, int age)
{
cout << "Hello " << fullName << "You are " << age << "years old.";
}
You have a few bugs with your code, here are some corrections (in comments):
#include <iostream>
#include <fstream>
#include <cstring> // include this for strcpy() and strcat()
using namespace std;
// You need to have char* fullname as you are passing a cstring not a character
void displayInfo(char* fullName, int age); // You forgot the semi colon here
int main(void) // You need to have input parameters to main() it can be void
{
char firstName[10] = "Bob";
char lastName[10] = "0"; // Not an error but you should initialize like this
char fullName[20] = "0"; // same here
int age;
cout << "Enter your age: ";
cin >> age;
cout << "\nEnter the last name: ";
cin.getline(lastName, 10);
strcpy(fullName, firstName); // Just use strcpy
strcat(fullName, " "); // Just use strcat
strcat(fullName, lastName); // Just use strcat
strcat(fullName, "."); // Just use strcat
// Move the display after you do string manipulation
displayInfo(fullName, age); // You forgot semi colon here
return 0;
}
// You need to have char* fullname as you are passing a cstring not a character
void displayInfo(char* fullName, int age) // You forgot the return type of this function
{
cout << "Hello " << fullName << "You are " << age << "years old.";
}

Code outputs nonsense to output file instead of string?

The following code is for a project I have to do where I recieve a text file that has a students first and last name followed by his grades. I then have to convert that into an output file that contains his name followed by his average score. The file I recieve has multiple students in it spereated line by line. The output should look relativly like
Rzam, Look = 0.00
Bambi, Lambi = 40.47
Coop, Jason = 27.31
but mine is merely printing garbage such as
0x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.000x7fffb08e8698= 0.00
Here is what I have so far:
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
struct Student
{
string fname;
string lname;
double average;
};
int read(ifstream &fin, Student s[]);
void print(ofstream &fout, Student s[], int amount);
int main()
{
const int size = 10;
ifstream fin;
ofstream fout;
string inputFile;
string outputFile;
Student s[size];
cout << "Enter input filename: ";
cin >> inputFile;
cout << "Enter output filename: ";
cin >> outputFile;
cout << endl;
fin.open(inputFile.c_str());
fout.open(outputFile.c_str());
read(fin , s);
print(fout, s, size);
fin.close();
fout.close();
}
int read(ifstream &fin, Student s[])
{
string line;
string firstName;
string lastName;
double score;
double total;
int i=0;
int totalStudents=0;
Student stu;
while(getline(fin, line)){
istringstream sin;
sin.str(line);
while(sin >> firstName >> lastName){
stu.fname = firstName;
stu.lname = lastName;
while(sin >> score){
total *= score;
i++;
}
stu.average = (total/i);
}
s[totalStudents]=stu;
totalStudents++;
}
return totalStudents;
}
void print(ofstream &fout, Student s[], int amount)
{
ostringstream sout;
for(int i = 0; i<amount; i++)
{
sout << left << setw(20) << s[i].lname << ", " << s[i].fname;
fout << sout << setprecision(2) << fixed << "= " << s[i].average;
}
}
You have a few bugs, which have added up to your issue:
in your print function, you write to a ostringstream and then try to write that to the file stream. Which is fine, but it is printing the address of the ostringstream buffer. So making this change will cause it to print the contents:
fout << sout.str() << setprecision(2) << fixed << "= " << s[i].average;
Note the usage of .str(). Though you don't really need a temporary stream here at all...
You don't place a newline in the output, so it all ends up one line making it hard to read:
so make another change making it look like this:
fout << sout.str() << setprecision(2) << fixed << "= " << s[i].average << '\n';
You need to place the ostringstream sout; inside the loop, so it is reset each time too. Otherwise you will get weirdly compounding output.
You don't use the count of students calculated by your read function! so it always tries to print 10! Do something like this:
int count = read(fin , s);
print(fout, s, count);
If no score is read, I think you'll have a divide by zero. So you should add a check.
You should ensure that no more than size Students are read. Or better yet, just place them in a std::vector and return that from the function. It's simpler and less error prone.
You need to reset i each time you start reading a student, or the later students will get divided by way too much. Each needs to have an independent count.
I don't know if these are the only issues, but certainly it should get you started on the right track :-)

C++ Populating a vector of objects with user input

I am new to vectors and new to classes.That being said, I have found some posts about how to create a vector of objects. I want to know how would one go about creating a vector of objects from user input? Say the program asks the user to give the number of employees(class) he/she wants to create. The user wants to add 5 employees. So user must input the employee's last name and first name. I have a for loop in mind but I am not sure how to go about grabbing the user input (Maybe using getline and push_back?) and storing it in the vector.
//Lets say class.h looks like this
class Employee
{
private:
string lastName;
string firstName;
public:
void setLastname(string);
void setFirstname(string);
string getLastname() const;
string getFirstname() const;
}
Your Employee class should have a constructor. When gathering input, you need all the constructor arguments. Then, to add an Employee to a vector<Employee>, call employees.emplace_back( ctor-arguments ).
std::vector has a nice method called emplace_back, which
Appends a new element to the end of the container. The element is constructed through std::allocator_traits::construct, which typically uses placement-new to construct the element in-place at the location provided by the container.
So the only thing you are missing to be able to use it is an appropriate constructor.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Employee
{
private:
string firstName;
string lastName;
public:
void setLastname(string);
void setFirstname(string);
string getLastname() const{return lastName;}
string getFirstname() const{return firstName;}
//create a constructor
Employee(string firstName, string lastName)
: firstName(firstName), lastName(lastName)
{}
};
int main()
{
vector<Employee> emp;
int count = 0;
cout << "Enter the amount of employees to add:" << endl;
cin >> count;
string firstName, lastName;
for(int i = 0; i < count; ++i)
{
cout << "Please enter the first and last names" << endl;
cin >> firstName;
cin >> lastName;
emp.emplace_back(firstName, lastName);
}
for(const Employee & e : emp)
{
cout << "Employee:" << endl;
cout << e.getFirstname() << " " << e.getLastname() << endl;
}
}
Other users have provided a good examples explaining how to use emplace_back in modern C++.
If you work with pre-C++11 versions, there is no emplace_back method. In this case, you can collect data in your vector manually using old-style push_back. You can simply define a vector:
vector<Employee> employees;
Then, you can read your data line by line, create new objects, fill them according to your business logics and append to your vector:
int n;
int main()
{
cout << "Enter number of employyes: "; cin >> n;
for (int i = 0; i < n; i++)
{
std::string s;
Employee employee; // Create object
cout << "Employee " << i << ". First name: "; cin >> s;
employee.setFirstname(s); // Fill object
cout << "Employee " << i << ". Last name: "; cin >> s;
employee.setLastname(s); // Keep filling it
cout << "Welcome, " << employee.getFirstname() << " " << employee.getLastname() << endl;
employees.push_back(employee); // Add to vector
}
}
You can also define a constructor taking both firstname and lastname as arguments to make it easier to work with.
class Employee
{
private:
string lastName;
string firstName;
public:
Employee(string paramLastName, string paramFirstName) : lastName(move(paramLastName)), firstName(move(paramFirstName)) {}
void setLastname(string);
void setFirstname(string);
string getLastname() const;
string getFirstname() const;
}
You need a constructor that takes two strings as input. Obviously you could do without this but this reduces verbosity.
Employee(string paramLastName, string paramFirstName) :
lastName(move(paramLastName)), firstName(move(paramFirstName)) {}
You will need to call it in this way.
vector<Employee> inp;
string tmp1, tmp2;
while(std::cin>>tmp1 >> tmp2) {
inp.emplace_back(tmp1, tmp2);
}
(This is assuming that you will compile with c++11 support)

C++ beginner, need guidance

I am a c++ beginner and I am curious to why this does not work:
#include <iostream>
using namespace std;
int main ()
{
int firstname;
int lastname;
cout << "My name is " << firstname << lastname;
cin >> firstname >> lastname;
cout << endl;
return 0;
}
I want the output to simply be where the user inputs their first name and the last name and it turns out to be as follows:
Example:
My name is John Doe.
#include <string>
...
string firstname;
string lastname;
int values hold numbers. To store names, use strings.
cin >> firstname >> lastname;
cout << "My name is " << firstname << " " << lastname;
Then make sure to read the names before you print them. The cin and cout should be swapped. I've also added a space (" ") in the printout between the two variables.
#include <iostream>
#include <string> // so you can use string
using namespace std;
int main() {
string first;
string last;
cin >> first;
cin >> last; // getting input from using and storing it in last
cout << "My name is " << first << last << endl; // printing out "My name is and " and what you wrote for first and last
return 0;
}
cout << "My name is ";
cin >> firstname >> lastname;
cout << firstname << " " << lastname;
This should output a single line of:
My name is John Doe
Plus, strings of characters are stored in string types, not int types
So you'd have to include <string>, and change the ints to string
Name can be of int type change it to std::string
Here is the modified code will produce output as you want.
#include <iostream>
int main ()
{
std::string firstname;
std::string lastname;
std::cin >> firstname >> lastname;
std::cout << "My name is " << firstname<<" " << lastname<<"\n";
return 0;
}
Note that the you will have to add " " while printing if you want a white space between your first name and last name.
Try to take input using 'getline(cin,str); if your string contain white space too.
I would suggest you to not to use standard namespace i.e. using namespace std; while writing the code. For more detail please have a look of link provided below
Why is "using namespace std" considered bad practice?
First I would try to prompt the user to enter their first and last name. Or else how would they know what to enter? And using int type does not help at all because the user would be entering a string and not an integer. Try this ...
#include <iostream>
using namespace std;
int main() {
cout << "Pleas enter your first and last name." << endl;
string name;
cin >> name;
cout << "Hello " << name << endl;
return 0;
}
Make sure that the user knows what to input (first and last name) otherwise they will not know what to input. This is the output code you can use:
cout << "Please enter your first and last name." << endl;
So the full code should look something like this:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string firstname;
string lastname;
cout << "Please enter your first and last name: " << endl;
cin >> firstname >> lastname;
cout << "My name is " << firstname << " " << lastname;
cout << endl;
return 0;
}
You are doing
int firstname;
int lastname;
meaning that you want to get an integer value, however you want a string. So, replace the int with std::string or string in your case. Also, remember to #include <string> to get the string functionality. After doing this, you should be able to input and return letters. :D
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string firstname;
string lastname;
cout << "My name is " << firstname << lastname;
cin >> firstname >> lastname;
cout << endl;
return 0;
}
Might I add that you generally should not use using namespace std; as it is considered bad practice, it also is not really necessary, you could just type std::.... using namespace std is used if you do not want to type the namespace name every time, but it's generally better to distinguish between which type of functions you want to use with the same names but in different namspaces. and using '\n' for a new line as well instead of endl. This is because endl takes more time to complete than \n.
I recommend to also include the namespace in your code if you are a beginner. In simple cases like printing strings its readable but a better practice if you're learning to include std::string, std::cin, and std::cout. In this case the :: just means to grab the keyword(right value) from its namespace(left value).