Manipulating vectors inside class methods - c++

I just started learning about vectors, and they seem really handy, if talking about lists from a file. But I'm having a problem while trying to return a new vector from a class method and put it to another method of the same class.
i.e.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
class A
{
public:
string name;
string age;
};
class Test
{
string name;
string age;
public:
void get(vector<A> students)
{
vector<A> specificStudents;
//rewrite a couple of students from vector<A>students
//to vector<A> specificStudents
};
void set(vector<A> specificStudents)
{
//I need to get vector<A> specificStudents here
};
};
int main()
{
vector<A> students;
A stud;
ifstream file("file.txt");
for (int i = 0; i < file.eof(); i++)
{
getline(file, stud.name);
getline(file, stud.age);
students.push_back(stud);
};
Test test;
test.get(students);
return 0;
}
Can I return it as a function argument?

It is not entirely clear, but do you want to save a copy of students inside test?:
class Test
{
vector<A> specificStudents;
public:
const vector<A>& get() const
{
return specificStudents;
}
void set(const vector<A>& students)
{
specificStudents = students;
// maybe modify `specificStudents` here in some way or assign it differently
}
};
int main()
{
vector<A> students;
A stud;
ifstream file("file.txt");
while (getline(file, stud.name) && getline(file, stud.age))
{
students.push_back(stud);
}
Test test;
test.set(students);
//... Do something with test
return 0;
}
If you don't know yet what & and const mean in this, you can just remove them (until you learn about them).
You seem to have gotten get and set mixed up. By usual convention, get gets something stored in the class object to the caller and set sets something in the class object (with a value provided by the caller).
I also fixed your input loop. I don't know what you thought file.eof() does, but comparing to i does not do anything useful.
Also be aware of where ; belongs and where it doesn't. It belongs after single statements and class definitions, but not after } of function definitions or other statement blocks, such as the one of while.

YES, you can return vector from a function.
To do this you can write a function like this one:
std::vector<A> get(vector<A> students)
and the inside it return the vector. An example can be:
vector<A> get(vector<A> students)
{
vector<A> specificStudents;
//rewrite a couple of students from vector<A>students
//to vector<A> specificStudents
return specificStudents;
};

Related

How to pass Dynamic array of structures in c++?

I have created an array dynamically of structures and now i am willing to pass it to function.What is the correct method of doing it?What should i put in parameter of function in MAIN for doing it?
void function(Data *family)
{
//code
}
int main()
{
struct Data{
string name;
int age;
string dob;
};
Data *family = new Data[3];
function(Data); //ERROR in parameter i guess!
}
It is better to use more safe ways using std::vector or std::shared_ptr. Because it is easy to make a mistake when you use raw pointers.
If you really need to use raw pointer than you need fix your code:
#include <string>
#include <iostream>
// "Data" should be declared before declaration of "function" where "Data" is used as parameter
struct Data {
std::string name;
int age;
std::string dob;
};
void function(Data *family)
{
std::cout << "function called\n";
}
int main()
{
Data *family = new Data[3];
// fill all variables of array by valid data
function(family); // Pass variable "family" but not a type "Data"
delete[] family; // DON'T FORGET TO FREE RESOURCES
return 0; // Return a code to operating system according to program state
}
Every c++ programmer needs to learn std::vector, which is a dynamic array:
#include <vector>
struct Data{
string name;
int age;
string dob;
};
void function(const std::vector<Data>& family)
{
//code
}
int main()
{
auto family = std::vector<Data>(3);//family now contains 3 default constructed Data
function(family);
}
Not sure what actually what actually you are looking for, I guess you can try like this:
First define your structure outside from main so it would be accessible as function parameter. Then instead of Data pass object family to the function.
struct Data {
string name;
int age;
string dob;
};
void function(Data *family)
{
//code
}
int main()
{
Data *family = new Data[3];
function(family);
}

C++ Segmentation Fault accessing class data member without explicit use of pointers

Note: Similar questions have been asked, but nearly all that I've found seem to make direct use of a pointer which may not be relevant here
For this snippet of code
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class Unit{
public:
string name;
char value;
vector<Unit> inner;
Unit(string Name){
name=Name;
}
Unit(char Value){
name="Character";
}
};
class Instruction{
public:
int size;
string type;
string value;
map<string, vector<Unit>> vars;
vector<Instruction> inner;
vector<Instruction> outer;
Instruction(string Type,string Value,vector<Instruction>& Outer,map<string, vector<Unit>> &Vars){
type=Type;
value=Value;
outer=Outer;
vars=Vars;
size=0;
}
Instruction(string Type,vector<Instruction>& Outer,map<string, vector<Unit>> &Vars){
type=Type;
outer=Outer;
vars=Vars;
size=0;
}
bool matches(vector<Unit> &info,int position=0, int vectLocation=0){
cout<<value<<'\n'; //Segmentation Fault Occurs Here
return false;
}
};
void breakUp(vector<Unit>&u,string s){
for(int i=0;i<s.size();i++){
u.push_back(Unit(s[i]));
}
}
int main(){
//String to be matched
vector<Unit> v;
breakUp(v,"For the love of tests");
//Instruction Vector
vector<Instruction> i;
//Var Vector
map<string, vector<Unit>> x;
//Add initial instruction
Instruction constant("Constant","",i,x);
constant.inner.push_back(Instruction("String","For the love of tests",constant.inner,x));
//Test match
bool result=i[0].matches(v);
if(result==true){
cout<<"Match True\n";
}else{
cout<<"Match False\n";
}
return 0;
}
I get a segmentation fault when attempting to access one of the data members within the matches function. This also occurs when it attempts to print size or type. I have not been able to discern the exact cause of this memory issue and would appriciate any advice or considerations.
vector<Instruction> i;
...
bool result=i[0].matches(v);
i is empty, so accessing i[0] yields undefined behavior.
The reason for SIGSEGV seems to be
bool result=i[0].matches(v);
When you did
vector<Instruction> i;
A new std::vector object was created with size 0.
Now, when you try to access the first element by the above statement, it may give Segmentation fault.
Suggestion:
1) Use const std::string & instead of std::string in the constructor. Using std::string will lead to the string getting copied twice (which won't be good for performance).

c++ 2 Constructor 1 Object, How to?

I have to set up an object and, after an user chose, i have to change some param into the object but not every each.
example:
{
class Champ
{
private:
int hp;
std::string class;
public:
Champ();
Champ(std::string chose);
};
Champ::Champ() {hp=10; class="";}
Champ::Champ(std::string chose) {class = chose;}
main()
{
Champ Test;
std::string chose;
getline(cin,chose);
Test(chose);
return 0;
}
this code give me an error.
i need hp equal for all "Champ" created but class can be changed.
The hp can't be "const" because this value may undergo changes...
how can i do this? :/
The comments in the code below should explain what is going on well enough...
#include <iostream>
#include <string>
class Champ {
int hp;
std::string job;
public:
Champ():
hp(10) { } // don't need to explicitly initialize `job` because the default constructor for string does what we want.
explicit Champ(const std::string& choose):
hp(10),
job(choose) { }
};
int main(int argc, const char * argv[]) {
using namespace std;
// this is most like how you had it with the compile error fixed.
{
Champ test; // this creates a Champ object using the default constructor
string choose;
getline(cin, choose);
test = Champ(choose); // this creates a new Champ object and assigns it to test... Throwing away the one that was created earlier.
}
// this is, imho, a better way to do it:
{
string choose;
getline(cin, choose);
auto test = Champ(choose); // declare the variable as late as possible, and after you have all the data for its construction. That way, you only make one of them.
}
return 0;
}

I am stuck with creating an output member function

I am stuck on the output member function of the class. I have no idea how to create it and just simply couting it does not seem to work. also any other advice would be great. thanks in advance
here's the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class StringSet
{
public:
StringSet(vector<string> str);
void add(string s);
void remove(int i);
void clear();
int length();
void output(ostream& outs);
private:
vector<string> strarr;
};
StringSet::StringSet(vector<string> str)
{
for(int k =0;k<str.size();k++)
{
strarr.push_back(str[k]);
}
}
void StringSet::add(string s)
{
strarr.push_back(s);
}
void StringSet::remove(int i)
{
strarr.erase (strarr.begin()+(i-1));
}
void StringSet::clear()
{
strarr.erase(strarr.begin(),strarr.end());
}
int StringSet::length()
{
return strarr.size();
}
void StringSet::output()
{
}
int main()
{
vector<string> vstr;
string s;
for(int i=0;i<10;i++)
{
cout<<"enter a string: ";
cin>>s;
vstr.push_back(s);
}
StringSet* strset=new StringSet(vstr);
strset.length();
strset.add("hello");
strset.remove(3);
strset.empty();
return 0;
}
Ok, you should begin by solving some errors in your code:
You use a pointer to StringSet and after that you are trying to access the member-functions with the . operator instead of the ->. Anyway, do you really need to allocated your object dynamically ?
StringSet strset(vstr); // No need to allocated dynamically your object
After that, you are calling an empty() method which does not exist...
Also if you stay on dynamic allocation, don't forget to deallocated your memory :
StringSet* strset = new StringSet(vstr);
// ...
delete strset; // <- Important
Finally, I think that your function output should write in the stream the content of your vector, you can do it that way :
#include <algorithm> // For std::copy
#include <iterator> // std::ostream_iterator
void StringSet::output( ostream& outs )
// ^^^^^^^^^^^^^ don't forget the arguments during the definition
{
std::copy(strarr.begin(), strarr.end(), std::ostream_iterator<string>(outs, "\n"));
}
HERE is a live example of your code fixed.
I would suggest you to understan how class works : http://www.cplusplus.com/doc/tutorial/classes/
If your output function is going to print the state of the StringSet object, you may implement is like this:
#include<iterator> //std::ostream_iterator
#include<algorithm> //std::copy
void StringSet::output(ostream& outs)
{
std::copy(starr.begin(), starr.end(), std::ostream_iterator<string>(outs, "\n"));
}

How to include a declaration in the comma operator?

I have two simple testing lines:
cout<<(cout<<"ok"<<endl, 8)<<endl;
cout<<(int i(8), 8)<<endl;
The first line worked, but the second failed compilation with
error: expected primary-expression before 'int'
For some reason, I do need a declaration in the comma operator. To be more specific, I want to declare some variables, obtain their values, and assign them to my constant class members from the initialization list of my class constructor. Following shows my intentions. If not achievable using comma operator, any another suggestions?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
void readFile(const string & fileName, int & a, int & b)
{
fstream fin(fileName.c_str());
if (!fin.good()) {cerr<<"file not found!"<<endl; exit(1);}
string line;
getline(fin, line);
stringstream ss(line);
try {ss>>a>>b;}
catch (...) {cerr<<"the first two entries in file "<<fileName<<" have to be numbers!"<<endl; exit(1);}
fin.close();
}
class A
{
private:
const int _a;
const int _b;
public:
A(const string & fileName)
:
_a((int a, int b, readFile(fileName,a,b), a)),
_b((int a, int b, readFile(fileName,a,b), b))
{
/*
int a, b;
readFile(fileName,a,b);
_a = a;_b = b;
*/
}
void show(){cout<<_a<<" "<<_b<<endl;}
};
int main()
{
A a("a.txt");
a.show();
}
Declarations are statements and not expressions. You cannot place statements inside of expressions, though you can place expressions inside of statements. Accordingly, you cannot declare a variable in the way that you're describing above. You'll need to separate it out into multiple different statements.
I would be surprised if if you actually needed to do this. If you do, there is probably something problematic about your design.
Hope this helps!
You should have a look at Boost Phoenix (which has phoenix::let to do roughly this). Bear in mind, Phoenix is an eDSL, really (embedded domain specific language).
You could do an ugly trick and abuse lambdas:
cout<< ([]->int{ int i(8); return 8; })() <<endl;
A lambda allows a declaration within an expression. So this is possible:
std::cout << ([]{ int i(8); m_i = i; }(), 8) << std::endl;
But it's really weird - I assume this will be in some #define macro that makes it appear closer to normal.
You cannot. This is unpossible in C++. The fact that you are trying to do this is also a code smell. Something's not right here.
I want to declare some variables, obtain their values, and assign them
to my constant class members from the initialization list of my class
constructor. Not sure how to achieve this.
You didn't say what you intended to do with these variables you declare after you've used the values, but I'm guessing that once you've finished with the values, you've finished with the variables. In other words, they are temporary.
Your edited example suggests that my assumption is correct. It also confirms the code smell. Based on your (intended) code, you are going to read the file twice.
I'd say the most straightforward way to do this is to use an intermediary, kind of like a factory class. This also has the benefit of being able to read the file only once, as opposed to twice as you are doing now.
void readFile (const std::string& fileName, int& a, int& b)
{
// some magic
a = 42;
b = 314;
}
class FileReader
{
public:
FileReader (const std::string fileName)
:
mFileName (fileName),
mA (42),
mB (314)
{
// something happens like reading the file
}
int GetA () const
{
return mA;
}
int GetB () const
{
return mB;
}
private:
int mA;
int mB;
std::string mFileName;
};
class A
{
private:
const int mA;
const int mB;
public:
A (const FileReader& reader)
:
mA (reader.GetA()),
mB (reader.GetB())
{
}
};
Using this FileReader is simple:
int main()
{
A myA (FileReader ("somefile.txt"));
}