Print a list in c++ - c++

I have the following structure:
struct People{
string name;
string surname;
string number;
};
How can i print all people in list? I created a few people in main and tried to print them, but i get error.
int main(int argn, char** args) {
list<People> test_list;
People first;
first.name= "Name1";
first.surname= "Surname1";
first.number= "E1234567";
test_list.push_back(first);
People second;
second.name= "Name2";
second.surname= "Surname2";
second.number= "E2345678";
test_list.push_back(second);
People third;
third.name= "Name3";
third.surname= "Surname3";
third.number= "E3456789";
test_list.push_back(third);
list<People>::iterator i;
for( i = test_list.begin(); i != test_list.end(); ++i)
cout << *i << " ";
cout << endl;
return 0;
}
Does anybody know the propper way to print a list?

You should define std::ostream& operator<<(std::ostream&,const People&), which should simply print the data inside your People instance.

Try this to print the details:
cout << i->name << " "<< i->surname << " "<< i->number << " ";

I assume that, you are trying to print the variable of structure.Inside the for loop, you have specified the pointer, which is pointing to each element of list. But you haven't specified the element inside the structure. So, for that,
count<<(*i).name<<endl; // for printing name
Alternatively, you can also use -> like this
count<<i->name; // for printing name.
This should solve your problem.

Related

char* Input function Causes Seg Fault

Working on an assignment about Abstract Base classes, I'm running into a segment fault when I execute the getInput function I created in the addRecord function. I've tried a variety of methods for getting the user input for the name of the Employee/Student, however I keep running into issues with it.
getInput:
char* getInput(std::string message)
{
char* name;
std::cout << message << std::endl;
std::cin.ignore(INT_MAX, '\n');
std::cin.getline(name, INT_MAX);
return name;
}
addRecord:
/*
* addRecord(vecotr<base*>& v)
*
* Ask the user which type of record they want to add, an employee or student. Once
* they have made their selection, dynamically create a new pointer of the selected
* type of record and have them fill out the record's members via its set methods,
* then add it to the vector using the vector method .push_back().
*/
void addRecord(std::vector<Base*>& v)
{
std::cout << "--Records to Create--" << std::endl;
std::cout << "1.) Student Record" << std::endl;
std::cout << "2.) Employee Record" << std::endl;
std::cout << "Please select from the above options: ";
int sel = intInputLoop(1, 2);
clearConsole();
if (sel == 1)
{
char* name;
/*
std::cout << "Record Type: Student" << std::endl;
std::cin.ignore(INT_MAX, '\n');
std::cin.getline(name, INT_MAX);
*/
name = getInput("What is the Student's name? ");
float gradePointAverage = (float)intInputLoop(0, 4);
Student student = Student();
student.setName(name);
student.setGradePointAverage(gradePointAverage);
Base* bp = &student;
v.push_back(bp);
std::cout << "Added Student record for " << name << " with a grade point average of " << gradePointAverage << std::endl;
delete name;
}
else
{
char* name;
std::cout << "Record Type: Employee" << std::endl;
name = getInput("What is the Employee's name? ");
std::cout << "What is the Employee's salary? ";
int salary = intInputLoop(0, 0);
Employee employee = Employee();
employee.setName(name);
employee.setSalary(salary);
Base* bp = &employee;
v.push_back(bp);
std::cout << "Added Employee record for " << name << " with a salary of " << salary << std::endl;
delete name;
}
}
Any input is much appreciated. Thank you in advance.
char* name;
This declares a pointer, to an indeterminate number of char values. Who knows how many of them there are. It could be just one, very lonely char, sitting there, all by itself with nobody to play with. It could be a million, an entire city of chars. It's completely unspecified, nobody knows; that's because the pointer is completely uninitialized. Nothing in C++ happens automatically. If you intend to use a pointer, it must, well, point somewhere valid before you can use that pointer.
std::cin.getline(name, INT_MAX);
This call to getline reads input into a pointer. The pointer must point to valid memory. Since the pointer is uninitialized, this is undefined behavior, and is the reason for your crash.
Since your intent here is to use C++, the simplest solution is to use a C++ class that just happens to handle all the memory management for you: std::string:
std::string name;
std::getline(std::cin, name);
You'll need to replace all old-fashioned char * pointers, which is what you would use if you were writing C code, with std::string. After all: this is C++, not C.

(C++) Vector elements seem to disappear after for loop ends

I'm extremely new to C++ (even newer to OOP) and I'm doing my first project that doesn't take place within one .cpp file. I've run into a seemingly simple issue where my vector data seems to be disappearing.
Code chunk inside main.cpp's main function:
vector<Horse> HorseStable(horseAmount); // creating an vector of horse objects based on user input horseAmount
for (int i = 0; i < horseAmount; i++) // sets name for each horse and rider
{
string nameString = "";
string riderString = "";
cout << "Enter name for horse #" << (i + 1) << ": ";
cin >> nameString;
HorseStable[i].setName(nameString);
cout << "Enter name for rider of " << nameString << ": ";
cin >> riderString;
HorseStable[i].setRider(riderString);
system("cls");
}
HorseStable[0].printName(); // a test to see if the horse name stayed inside the vector (it did not)
Entire Horse.h file:
#pragma once
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
class Horse
{
private:
std::string name;
std::string rider;
public:
// these three ints were supposed to be private, but I couldn't access
// maxRunningDistPerSecond as a displayHorse() function parameter from main
// maybe figuring out my first issue will help with this, as I was attempting
// HorseStable[0].displayHorse(maxRunningDistPerSecond)
int maxRunningDistPerSecond;
int distanceTraveled;
int racesWon;
Horse() // default constructor
{
std::string name = " ";
std::string rider = " ";
int maxRunningDistPerSecond = 100;
int distanceTraveled = 0;
int racesWon = 0;
};
int runASecond(int, int);
int sendToGate(int);
void displayHorse(int);
std::string setName(std::string); // sets the horse name based on user input from main.cpp variable
std::string printName(); // simply prints the horse name, I don't believe my issue is here
std::string setRider(std::string);
std::string printRider();
};
Code chunk inside Horse.cpp:
std::string Horse::setName(std::string nameString) // takes user input for horse name
{
Horse::name = nameString;
return std::string(nameString);
}
std::string Horse::printName() // prints the horse's name
{
return std::string(name);
}
setName() and getName() work perfectly within my for loop inside main.cpp, but all data seems to disappear when I attempt them after the loop ends. I've looked for hours for solutions, but had to revert to this stable build after nothing worked. I'm not very good with pointers and passing by reference, but these seem to be the only things that will work. Is it possible that I was using pointers wrong? Should I be creating a vector of Horse pointers, rather than a vector of actual Horse objects?
My other issue:
If you've noticed my public members that are supposed to be private in Horse.h, I cannot access them when private as parameters from functions called in main. This makes some sense, as my function call in main looked like this:
HorseStable[0].displayHorse(distanceTraveled)
I'm not sure how I could refer to each element of the vector within the Horse class, which seems like the only way distanceTraveled would be reachable as private. My professor wants the variables in question to be private, which makes this an issue. The user defines the amount of Horse objects, which means I can't just declare a few named Horses and simply displayHorse(distanceTraveled) them.
Function declaration from Horse.cpp:
void Horse::displayHorse(int distanceTraveled) // attempts to show a graphic of the race progress
{
if (distanceTraveled >= 50)
{
std::cout << "|-> |" << " " << name << ", ridden by " << rider;
}
else if (distanceTraveled >= 100)
{
std::cout << "|--> |" << " " << name << ", ridden by " << rider;
}
else if (distanceTraveled >= 150)
{
std::cout << "|---> |" << " " << name << ", ridden by " << rider;
} // this goes on up to 1000, but this is all that's necessary for posting
I apologize if my formatting isn't up to par, but this assignment has really been stressing me out. I've been understanding all the new material, but it always seems like pointers and referencing are the things that render my assignments unusable.

C++ beginners question how to access variables

So basicly my questions include when to use parameters and when I dont need them.
I try to learn from examples and this one I can't fully understand:
I will add the questions to the part where I dont understand something after "//" on the right side of the line.
Maybe someone can give me a good explanation, what I need to do in which scenario or good sources where I can look this up on my own.
class Student with public attributes:
#include <iostream>
class Student
{
public:
int stud_ID;
char stud_Name[22];
int stud_Age;
};
function which I want included in int main():
void studentinformation(Student); //#1Why do I must include (Student) in this fuction? ->
// If I dont add this parameter in here, there is no connection ->
//to the function studentinformation(s) in int main.
//Why exactly is that the case ?
main function to get information:
int main(){
Student s;
std::cout<<"Type in ID:";
std::cin >> s.stud_ID;
std::cout<<"Type in youre Name:";
std::cin.ignore(); //
std::cin.getline(s.stud_Name, 22); //#2 Why is std::getline(std::cin, s.stud_Name) not working ?->
std::cout<<"Type in age:"; //#3 Or is there a better alternative ?
std::cin >> s.stud_Age;
studentinformation(s); //#4 Why do I must include the parameter s ?
return 0;
}
function to print information:
void studentinformation(Student s) // #5 Why do I must include the Parameters ?
{ std::cout<<" Student information:"<< std::endl;
std::cout<<" Student ID:" << s.stud_ID << std::endl;
std::cout<<" Name:" << s.stud_Name<< std::endl;
std::cout<<" Age:" << s.stud_Age<< std::endl;
}
studentinformation() is a free function with no connection to any instance of Student which is why you need to supply one as an argument.
std::getline() works on std::strings ...
... and you'd be doing yourself a favour if you changed char stud_Name[22]; to std::string stud_Name;.
For the same reason as in 1.
For the same reason as in 1. 1, 4 and 5 are questioning the same thing.
An alternative would be to make studentinformation() a Student member function instead. You could then call s.studentinformation(); to print info about that particular student.
class Student {
public:
int stud_ID;
std::string stud_Name; // suggested change
int stud_Age;
void studentinformation() const { // const since the object (this) won't be altered
std::cout << " Student information:" << '\n';
std::cout << " Student ID:" << stud_ID << '\n';
std::cout << " Name:" << stud_Name << '\n';
std::cout << " Age:" << stud_Age << '\n';
}
};

Dynamic array of structs

I have such piece of code:
typedef struct reader
{
char name[50];
char card_num[50];
char title[100];
}reader_t;
int main()
{
vector<reader> vec;
ifstream input_file("D:\\lab.txt", ios::binary);
reader_t master[1];
input_file.read((char*)&master, sizeof(master));
for (size_t idx = 0; idx < 1; idx++)
{
reader temp;
strcpy(temp.name, master[idx].name);
strcpy(temp.card_num, master[idx].card_num);
strcpy(temp.title, master[idx].title);
vec.push_back(temp);
cout << "Name: " << master[idx].name << endl;
cout << "Card num: " << master[idx].card_num << endl;
cout << "Title: " << master[idx].title<<endl;
}
cout << vec.size();
getchar();
}
What is does: it reads structures from binary file into an array of structures,copies them into vector and displays structure.And yes, I do need to do like this - I need to store structures from file in vector and this is the only working way to do it I could find(if you can tell, how to read structures to vector directly from file - you are welcome).
So,everything works fine, but the problem is that I need to create a function which would be able to do the same, but with dynamic array.I wrote something like this:
void read_structs(int vec_size)
{
ifstream input_file("D:\\lab.txt", ios::binary);
//Here I commented 2 ways how I tried to create a dynamic array of structs
//reader* master = new reader[vec_size];
//reader* master = (reader*)malloc(sizeof(reader) * vec_size);
input_file.read((char*)&master, sizeof(master));
for (size_t idx = 0; idx < vec_size; idx++)
{
reader temp;
strcpy(temp.name, master[idx].name);
strcpy(temp.card_num, master[idx].card_num);
strcpy(temp.title, master[idx].title);
vec.push_back(temp);
cout << "Name: " << master[idx].name << endl;
cout << "Card num: " << master[idx].card_num << endl;
cout << "Title: " << master[idx].title<<endl;
}
}
And that worked fine too unless I tried to run it.VS wasn't higlighting error in my code, it just was throwing an exception right as the moment when the program tried to access master[0].name.
There is absolutely no point in the temp struct. See, the
vec.push_back(temp);
is already using copy constructor, so copy constructor must work and then the set of strcpy is not doing anything different from that, so just go with
vec.push_back(master[0]).
You can't read into vector directly. You do need to read into temporary. So that is correct. Except I suppose you want to read all entries from the file no matter how many of them there are, so you need to put the read itself also into the loop.
There is not much point in creating an array of one element.
reader_t master[1];
input_file.read((char*)master, sizeof(master));
// ^ you *don't* need & here, arrays degrade to pointers automatically
and
reader_t master;
input_file.read((char *)&master, sizeof(master));
// ^ but you do need & here.
are equivalent. I would go with the later.
So we are basically down to:
reader temp; // calling it temp; the master name makes no sense.
while (input_file.read((char*)&temp, sizeof(temp)))
// read returns input_file and input_file is false if last operation failed
{
vec.push_back(temp);
// verify the stored values by reading back vfrom vec.back().
cout << "Name: " << vec.back().name << endl;
cout << "Card num: " << vec.back().card_num << endl;
cout << "Title: " << vec.back().title<<endl;
}
In the second example, you didn't initialize master, so it obviously crashed.
There is a more C++ approach though. First, you define a read operator for the structure:
std::istream &operator>>(std::istream &in, reader &r) {
return in.read((char *)&r, sizeof(r));
}
and then you simply read the vector using the istream_iterator:
vec.assign(std::istream_iterator<reader>(input_file),
std::istream_iterator<reader>());
and the standard library will generate the above loop for you.

how do i print out print out vector<string> when i get a 'compilr.com/rayd360/test-songst'

Complete program here for clarification: compilr.com/rayd360/test-songs
struct Album {
string title;
string year;
string track;
vector<string> tracks;
vector<string>::iterator trk;
}MyAlbums[40];
cout << "\n list of songs: \n";
for(int i = 0; i < 5; i++){
cout << *MyAlbums[i].trk << "\n";
}
gives me: "bash: line 1: 232 Segmentation fault "
I am needing to pass the list of tracks to a function that sorts them alphabetically then prints them out.
Any help is very much appreciated!
The line in the for loop dereferences the iterator returned by MyAlbums[i].trk. Since the iterator isn't assigned to anything (its internal pointer isn't pointing to anything) dereferencing it is Undefined Behavior. This can also cause a segmentation fault since your looking into memory that isn't owned by you.
To fix this I think you should remove the iterator from your class. Instead, use one inside your loop:
auto begin = MyAlbums.tracks.begin(),
end = MyAlbums.tracks.end();
for (auto it = begin; it != end; ++it)
{
std::cout << *it;
}
struct Album {
string title;
string year;
string track;
}MyAlbums[40];
vector<Album> tracks;
vector<Album>::iterator trk=tracks.begin();
cout << "\n list of songs: \n";
for(trk;trk!=tracks.end();++trk){
cout << *trk.title << "\n";
Assuming that you have already populated the MyAlbums.
There are two problems:
1) MyAlbums[i].trk is not initialized
2) While iterating through containers, ensure not to access container with invalid index.
(Ex: for(int i = 0; i < 5; i++) is not safe in this context).
// C++11
for ( auto track : MyAlbums.tracks )
{
cout << track << "\n";
}
// If not C++11
for (vector<string>::Iterator trackItr = MyAlbums.begin();
trackItr != MyAlbums.end(); ++trackItr)
{
cout << *trackItr << "\n";
}