I am trying to create a program that uses class, arrays, and functions to show information about two students(Name, id#, classes registered). The part I am struggling with is passing arrays to a function. How do I do that?
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
class Student // Student class declaration.
{
private:
string name;
int id;
string classes;
int arraySize;
public:
void setName(string n)
{
name = n;
}
void setId(int i)
{
id = i;
}
void setClasses(string c, int num)
{
classes = c;
arraySize = num;
}
string getName()
{
return name;
}
int getId()
{
return id;
}
void getClasses()
{
for (int counter=0; counter <arraySize; counter++) {
cout << classes[counter] << endl;
}
}
};
int main()
{
//Student 1
string s1Name = "John Doe";
int s1Id = 51090210;
int const NUMCLASSES1 = 3;
string s1Classes[NUMCLASSES1] = {"C++","Intro to Theatre","Stagecraft"};
//Student 2
string s2Name = "Rick Harambe Sanchez";
int s2Id = 666123420;
int const NUMCLASSES2 = 2;
string s2Classes[NUMCLASSES2] = {"Intro to Rocket Science","Intermediate Acting"};
//
Student info;
info.setName(s1Name);
info.setId(s1Id);
//info.setClasses(s1Classes, NUMCLASSES1);
cout << "Here is Student #1's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
info.setName(s2Name);
info.setId(s2Id);
// info.setClasses(s2Classes, NUMCLASSES1);
cout << "\n\nHere is student #2's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
return 0;
}
The usual way to pass around variable-length lists in C++ is to use an std::vector. A vector is a single object that you can easily pass to a function, copying (or referencing) its contents. If you are familiar with Java, it's basically an ArrayList. Here is an example:
#include <vector>
#include <string>
using namespace std;
class foo {
private:
vector<string> myStrings;
public:
void setMyStrings(vector<string> vec) {
myStrings = vec;
}
}
//...
foo myObj;
vector<string> list = {"foo","bar","baz"};
myObj.setMyStrings(list);
If don't want to use the standard library though, you can pass an array C-style. This involves passing a pointer to the first element of the array, and the length of the array. Example:
void processStrings(string* arr, int len) {
for (int i = 0; i < len; i++) {
string str = arr[i];
//...
}
}
string array[] = {"foo","bar","baz"};
processStrings(array, 3); // you could also replace 3 with sizeof(array)
Passing raw arrays like this, especially if you wanted to then copy the array into an object, can be painful. Raw arrays in C & C++ are just pointers to the first element of the list. Unlike in languages like Java and JavaScript, they don't keep track of their length, and you can't just assign one array to another. An std::vector encapsulates the concept of a "list of things" and is generally more intuitive to use for that purpose.
Life lesson: use std::vector.
EDIT: See #nathanesau's answer for an example of using constructors to initialize objects more cleanly. (But don't copy-paste, write it up yourself! You'll learn a lot faster that way.)
You can pass array of any_data_type to function like this
void foo(data_type arr[]);
foo(arr); // If you just want to use the value of array
foo(&arr); // If you want to alter the value of array.
Use std::vector. Also, don't add functions you don't need. Here's an example of using std::vector
#include <string>
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class Student // Student class declaration.
{
private:
vector<string> classes;
string name;
int id;
public:
Student (const vector<string> &classesUse, string nameUse, int idUse) :
classes (classesUse),
name (nameUse),
id (idUse)
{
}
void print ()
{
std::cout << "Name: " << name << std::endl;
std::cout << "Id: " << id << std::endl;
std::cout << "Classes: ";
for (int i = 0; i < classes.size (); i++)
{
if (i < classes.size () - 1)
{
std::cout << classes[i] << ", ";
}
else
{
std::cout << classes[i] << std::endl;
}
}
std::cout << std::endl;
}
};
int main()
{
Student John ({"C++","Intro to Theatre","Stagecraft"},
"John",
51090210);
John.print ();
Student Rick ({"Intro to Rocket Science","Intermediate Acting"},
"Rick",
666123420);
Rick.print ();
return 0;
}
Name: John
Id: 51090210
Classes: C++, Intro to Theatre, Stagecraft
Name: Rick
Id: 666123420
Classes: Intro to Rocket Science, Intermediate Acting
In the private variables of class Student, you are storing a string:
String classes;
where as you should be storing an array of strings like:
String classes[MAX_NUM_CLASSES];
then in the set classes function, pass in an array of strings as the first argument, so it should be :
void setClasses(string[] c, int num)
{
classes = c; //not sure if simply setting them equal will work, rather copy entire array using a for loop
arraySize = num;
}
This should point you in the right direction
Also, use std::vector instead of string[], it will be easier.
Related
I wanted to create a database like class through OOP. In this class, there are 3 arrays which act as columns in a table.I insert data through insert() function and prints data through printEntries() function. But that function can't access the arrays to retrieve data.
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
class subject{
public:
int numOfStudents;
string subjectId;
int * marksArray;
int * indexArray;
char * gradeArray;
int index ; // index for inserting data
subject(int students , string subjectName){
numOfStudents = students;
subjectId = subjectName;
this->index =0 ;
//creating and pointing to arrays
int A[numOfStudents]; marksArray = A;
int B[numOfStudents]; indexArray = B;
char C[numOfStudents]; gradeArray = C;
}
void insert(int studentId , int mark , char grade){
indexArray[index] = studentId;
marksArray[index] = mark;
gradeArray[index] = grade;
this->index = this->index +1;
}
int getNumberOfEntries(){
return index ;
}
void printEntries(){
cout<< indexArray[0] << " O" << marksArray[0] << " " << gradeArray[0] << endl;
cout<< indexArray[1] << " OOO" << marksArray[1] << " " << gradeArray[1] << endl;
cout<< indexArray[2] << " OO" << marksArray[2] << " " << gradeArray[2] << endl;
}
};
int main(int argc, char const *argv[]){
subject S(10,"Mathematics");
cout<<S.subjectId<<endl;
cout<<S.numOfStudents<<endl;
S.insert(35,34,'A');
S.insert(33,34,'B');
S.insert(54,34,'C');
S.insert(21,34,'D');
S.insert(14,34,'F');
S.printEntries();
return 0;
}
output is :
Mathematics
10
35 O34 A
0 OOO0
As pointed out by #paddy in the comments to your question, your issue is within the constructor.
//creating and pointing to arrays
int A[numOfStudents]; marksArray = A;
int B[numOfStudents]; indexArray = B;
char C[numOfStudents]; gradeArray = C;
What you are doing is saving the address of the very first element and the rest disappears after you leave the constructor. you are lucky that it's even allowing you to save the first insert and to quote the comment what you are doing is "defined is undefined behavior"
Replacing the pointers with std::vectors and inserting you elements there will be must easier.
class subject
{
public: // It's considered bad practive to have public data members in a class
std::vector<int> marksVector;
std::vector<int> indexVector;
std::vector<char> gradeVector;
// ...
void insert(int studentId , int mark , char grade){
indexVector.push_back(studentId);
marksVector.push_back(mark);
gradeVector.push_back(grade);
// No longer need to worry about index for next insert
}
};
I am entirely new to programming so I'm sorry if I don't explain this well. For my C++ assignment I had to write an object-oriented program that reads the names from a text file (the text file is just a list of first names) and prints them to the console in alphabetical order using an array. Originally, the description of the assignment said that the file had 20 names, so I based my code around that. The program works, but now it turns out the assignment description was inaccurate and we shouldn't assume that the text file has a specific number of names. How do I convert my code from specifically reading 20 names to instead reading an undefined number of names, while still using an array?
I don't fully understand the concepts that I'm implementing so it's difficult for me to know how to change my code while still following the requirements of the assignment. Here is my code:
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
using namespace std;
class Names
{
private:
ifstream inStudents;
string studentNames[20];
string name;
int j;
public:
Names();
~Names();
void openFile(string);
void testFile();
void readFile();
void sortNames();
void closeFile();
void display();
};
Names::Names()
{
}
Names::~Names()
{
}
void Names::openFile(string d)
{
inStudents.open(d);
}
void Names::testFile()
{
if (!inStudents)
{
cout << "File did not open" << endl;
exit(10);
}
}
void Names::readFile()
{
cout << "Reading the input file..." << endl;
int j = 0;
while (inStudents >> name && j < 20)
{
studentNames[j++] = name;
}
}
void Names::sortNames()
{
sort(studentNames, studentNames + 20);
}
void Names::closeFile()
{
inStudents.close();
}
void Names::display()
{
cout << endl << "The alphabetical list: " << endl << endl;
for (int i = 0; i<20; i++)
cout << studentNames[i] << " " << endl;
cout << endl << endl;
}
int main()
{
Names r;
r.openFile("students.txt");
r.readFile();
r.testFile();
r.sortNames();
r.display();
r.closeFile();
return 0;
}
You can use std::vector object instead of a regular array. It will look like that:
vector<string> studentNames;
Now, instead of using the following line to insert a name to a known place in the array:
studentNames[j++] = name;
use:
studentNames.push_back(name);
//or
studentNames.emplace_back(name);
The the while loop inside your readFile function, will look like this:
while (inStudents >> name)
{
studentNames.push_back(name);
}
To display it now, all you have to change in your display function is the range. The vector object include a function named size which returns you the current vector size, or in other words- the elements' count that the vector includes. It will seem like the following line:
for (int i = 0; i < studentNames.size(); i++)
I am in need of assistance.
I am trying to create a vector structure where the string contents inside of a char array get automatically assign to another STRING variable within the same structure.
After countless hours, I have not been able to figure it out. When I used function such as string(). It doesn't copy anything. I can't seem to assign char variable to string variable. Please advise.
#include <iostream>
#include <ctime>
#include <fstream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
const int NAME_SIZE = 25;
struct tableInfo
{
char name2[NAME_SIZE];
string name = str(name2); // I need name string to equal name2 character variable
string info;
string link;
};
vector<tableInfo> table(6);
bool compareByWord(const tableInfo &lhs, const tableInfo &rhs);
int main()
{
cin.getline(table[0].name2, 51);
cin.getline(table[1].name2, 51);
cin.getline(table[2].name2, 51);
cin.getline(table[3].name2, 51);
cin.getline(table[4].name2, 51);
sort(table.begin(), table.end(), compareByWord);
cout << table[0].name << endl;
cout << table[1].name << endl;
cout << table[2].name << endl;
cout << table[3].name << endl;
cout << table[4].name << endl;
}
bool compareByWord(const tableInfo &lhs, const tableInfo &rhs)
{
unsigned int length = lhs.name.length();
if (rhs.name.length() < length)
length = rhs.name.length();
int sameLetters = 0;
for (unsigned int i = 0; i < length; ++i)
{
if (sameLetters == length)
return false;
if (tolower(lhs.name[i]) == tolower(rhs.name[i]))
{
++sameLetters;
continue;
}
return(lhs.name[i] < rhs.name[i]);
return(lhs.name[i] < rhs.name[i]);
}
return false;
}
If you want something to happen in a structure (or class), consider making sure it happens by using the constructor. You will need to change your vector so you can no longer default construct the struture, but that's ok.
This works, by enforcing the two fields contain identical data (not withstanding 25 no being long enough):
const int NAME_SIZE = 25;
struct tableInfo
{
tableInfo(char * whatever); //Make it so
char name2[NAME_SIZE];
string name;
string info;
string link;
};
tableInfo::tableInfo(char *whatever)
: name(whatever)
{
strncpy(name2, whatever, NAME_SIZE); //Now they match - unless whatever was too big
}
//vector<tableInfo> table(6);//no longer ok with the non-default constructor
bool compareByWord(const tableInfo &lhs, const tableInfo &rhs);
int main()
{
vector<tableInfo> table;
for (int i = 0; i < 5; ++i)
{
char name2[NAME_SIZE];
cin.getline(name2, 51); //Do you really mean 51?
// It's smaller than NAME_SIZE
table.emplace_back(name2);
}
sort(table.begin(), table.end(), compareByWord);
cout << table[0].name << endl;
cout << table[1].name << endl;
cout << table[2].name << endl;
cout << table[3].name << endl;
cout << table[4].name << endl;
}
How about doing like this:
struct tableInfo
{
char name2[NAME_SIZE];
string name;
string info;
string link;
tableInfo(const char* in_name)
{
memset(name2, 0, NAME_SIZE);
strncpy(name2, in_name, NAME_SIZE - 1);
name = string(name2);
}
};
How to use:
char tmp[NAME_SIZE];
cin.getline(tmp, 51);
table[0] = tableInfo(tmp);
I argue that you don't even need an array in the struct. Just use std::string. getline supports reading into a std::string and you can access individual characters using str[]. If you need to get a pointer to the data you can use str.c_str().
If you really need to use an array in the struct you can create a member function to return a std::string:
struct tableName {
char name[NAME_SIZE];
std::string info;
std::string link;
std::string nameString() const { return name; }
};
I want to make a program that will store the data from the Periodic Table of Elements into an array that I can access whenever I want. I want to do it by making a struct with the data for each element in it, and make an instance of that struct for each element in an array "periodicTable[119]"
Here is my code:
#include <iostream>
using namespace std;
struct element
{
string symbol;
string name;
float atomicWeight;
};
element periodicTable[119];
periodicTable[1].symbol = "H";
periodicTable[1].name = "Hydrogen";
periodicTable[1].atomicWeight = 1.008;
int main()
{
cout << periodicTable[1].symbol << periodicTable[1].name << periodicTable[1].atomicWeight << endl;
return 0;
}
I run linux, and when I try to compile this I get this error: 'error: periodicTable does not have a type'
I would like to know how to make an array of structs correctly, and if anyone has a better way to make a program like this or see any other errors by all means let me know.
You cannot use assignments (or any other statements, for that matter) outside of functions. Use initializers instead:
element periodicTable[119] = {
{"H", "Hydrogen", 1.008}
, {"He", "Helium", 4.003}
, ...
};
Also note that C++ arrays are indexed starting from zero, not from one, so the initial element of the array is periodicTable[0], not periodicTable[1].
Using global variables is not a good idea except that you have a strong reason. So normally you can do as below:
int main()
{
element periodicTable[119];
periodicTable[1].symbol = "H";
periodicTable[1].name = "Hydrogen";
periodicTable[1].atomicWeight = 1.008;
cout << periodicTable[1].symbol << periodicTable[1].name << periodicTable[1].atomicWeight << endl;
return 0;
}
If you really want to use the global variable, you can do like this:
#include <iostream>
using namespace std;
struct element
{
string symbol;
string name;
float atomicWeight;
};
element periodicTable[119]{
{},
{"H", "Hydrogen", 1.008f}, // 1.008 is double, 1.008f is float
};
int main()
{
cout << periodicTable[1].symbol << periodicTable[1].name << periodicTable[1].atomicWeight << endl;
return 0;
}
I have a Spieler class and a Verein class with a vector of Spieler members.
Now if I change something of the Players like the Staerke(german for strength) by using a function of this class in the player class it does not automatically change the value for this player.
Here is the code:
#include <vector>
#include<iostream>
#include <string>
using namespace std;
class Spieler
{
public:
void setinformation(int a, string b, string c, int d)
{
ID = a;
Vorname = b;
Nachname = c;
Staerke = d;
}
void getinformation()
{
cout << "ID: " << ID << endl;
cout << "Vorname: " << Vorname << endl;
cout << "Nachname: " << Nachname << endl;
cout << "Staerke: " << Staerke << endl << endl;
}
void setStaerke(int x)
{
Staerke = x;
}
int getStaerke()
{
return Staerke;
}
private:
string Vorname, Nachname;
int Staerke, ID;
};
class Verein
{
public:
void setSpielerListe(vector<Spieler> x)
{
Spielerliste = x;
}
vector<Spieler> getSpielerListe()
{
return Spielerliste;
}
string getVereinsName()
{
return VereinsName;
}
int getVereinsID() const
{
return VereinsID;
}
void setVereinsID(int x)
{
VereinsID = x;
}
int getGesamtstaerke()
{
Gesamtstaerke = 0;
vector<Spieler> b;
b = getSpielerListe();
for (size_t i = 0; i < b.size(); i++)
{
Gesamtstaerke = Gesamtstaerke + b[i].getStaerke();
}
return Gesamtstaerke;
}
void Vereinsinformationen()
{
vector<Spieler> list;
int id;
string vereinsname;
int gesamtstaerke;
id = getVereinsID();
vereinsname = getVereinsName();
gesamtstaerke = getGesamtstaerke();
list = getSpielerListe();
cout << "VereinsID: " << id << endl;
cout << "Vereinsname: " << vereinsname << endl;
cout << "Gesamstaerke: " << gesamtstaerke << endl << endl;
cout << "Spieler: " << endl;
for (size_t i = 0; i < list.size(); i++)
list[i].getinformation();
}
private:
vector<Spieler> Spielerliste;
int VereinsID, Gesamtstaerke;
string VereinsName;
};
vector<Spieler> spieler;
int main()
{
Spieler Spieler1;
Spieler1.setinformation(0, "Peter", "Pan", 10);
spieler.emplace_back(Spieler1);
Verein Team1;
Team1.setSpielerListe(spieler);
Spieler1.setStaerke(20);
Team1.Vereinsinformationen();
cin.get();
return 0;
}
I'm really new into c++ and programming so the code might be terrible.
Guess it has to do with pointers, I'm really not into the concept of storing data in c++, try to get it by trial & error; So how to change the Staerke in a way that it is changed in the Teams Playerlist too?
The problem is you are storing full object in the vector and not pointers. When you run this line:
spieler.emplace_back(Spieler1);
a copy of Spieler1 is made and put in the vector. So modifying it in the main will have no effect in the vector. Also not that you are copying the vector when setting in Verein class.
You should use pointer if this is what you are after or better yet have a function to modify strength from Verein class taking its id and new strength as parameters might be a good idea. Something like this:
void setStaerke(int id, int x)
{
vector<Spieler>::iterator it = Spielerliste.begin();
while (it != Spielerliste.end())
{
if ((*it).GetId() == id)
{
(*it).setStaerke(x);
break;
}
}
}
If you have access to C++11, it could be made more elegantly.
Hereby you pass and store a copy from the vector into the object:
Team1.setSpielerListe(spieler);
Therefore changes to the original vector and the contained objects will not affect the member.
Further, I don't have much experience with emplace_back, but the more usual way to append an object to a std::vector would also append a copy:
spieler.push_back(Spieler1);
Therefore changes to the original object would not affect the object you've appended to the container.
Make sure you better understand when objects are copied.
For reference:
http://en.cppreference.com/w/cpp/container/vector/emplace_back
http://en.cppreference.com/w/cpp/container/vector/push_back
How to pass objects to functions in C++?