C++ STL vector init - c++

I am just wondering how I could solve this problem.
I have a
vector<char> vstr;
definition in the class Program.
Then in the class constructor I want to init this vector with an array:
char arrayOfChars[] = {'a', 'b', 'c'};
this.vstr = new vector<string>(arrayOfChars, arrayOfChars + sizeof(arrayOfChars)/sizeof(arrayOfChar[0]));
The build gives me a bug:
error: request for member 'vstr' int 'this', which is of non-class type 'Program *const' .
Could you give me a simple solution for this error?

I'm not an expert in C++ but I see at least two problems:
You are trying to initialise an object with a pointer. Don't use new key word.
What is more this pointer points to vector of strings not chars, so replace vector<string> with vector<char>.
As melak47 says in his comment this.vstr is also incorrect because this is a pointer and therefore should be replaced with this->vstr or simply vstr
Once you make all the three corrections it should compile

I think that piece of code is what you want.
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
class Program {
vector<char> vstr;
public:
Program(const char* data)
{
string s(data);
std::copy(s.begin(), s.end(), std::back_inserter(vstr));
}
void PrintData()
{
for (auto it = vstr.begin(); it != vstr.end(); it++)
{
std::cout << (*it);
}
}
};
int main()
{
Program p("simple data");
p.PrintData();
}

Related

How to use it->empty() in an iterator

I want to use an iterator as a condition of a for loop, but when I define it, it->empty() always reports an error. I don’t know where the error is. When I change it to (*it).empty() It will also report an error later
The error is: the expression must contain a pointer type to the class, but it has type "char *"
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
string s("some string");
for (auto it = s.begin(); it != s.end() && !it->empty(); it++)
{
cout<< *it <<endl;
}
}
The problem is that you are trying to access a member function called empty through a non-class type object(a char type object in this case). You can change your code to look like below:
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
std::vector<std::string> vec = {"some", "string", "is", "this"};
for (auto it = vec.begin(); it != vec.end() && !it->empty(); it++)
{
cout<< *it <<endl;
}
}
The above code works because this time we are using/calling the member function empty through a class type object(a std::string object in this modified example).
Also if you only wanted to know why you're having this error then i think the comments and my answer, answer that. If you have any other/further question then you can edit your question to add that.

C++ Dynamic Array Member Variable Assignment

I am having a problem with assigning new values to a dynamic int array that is a data member variable of the class IntersectionFlowRate(). I can initialize and print the values of the array inside the constructor. However, when I exit the constructor to the another class and then later call a function within the IntersectionFlowRate() class passing in variables to overwrite the initial values of the data member it will segmentation fault. I have debugged to find that overwriting the array is causing the seg fault. And that even attempting to access the dynamic array within one of its functions will seg fault.
My question is how can I edit the values of a dynamic int array member variable from within one of its functions i.e setArrayElement(int index, int x).
Here is some of my code. Sorry if I am unclear or missing something ridiculous. I have been stuck on this for hours.
#ifndef INTERSECTIONFLOWRATE_H
#define INTERSECTIONFLOWRATE_H
class IntersectionFlowRate
{
public:
IntersectionFlowRate();
~IntersectionFlowRate();
void setFlowCycle(int index, int flow);
private:
int* m_flowRateMotorCycle;
};
#endif
in the .h file ^
#include "IntersectionFlowRate.h"
#include <cstdlib>
#include <iostream>
#include <new>
using namespace std;
IntersectionFlowRate::IntersectionFlowRate()
{
const int SIZE = 4; //Constant for m_flowRates[] size
//DYNAMIC MEMORY DELETE LATER
m_flowRateMotorCycle = new int[SIZE];
for(int i = 0; i < SIZE; i++){
m_flowRateMotorCycle[i] = 0;
cout << m_flowRateMotorCycle[i] << endl;
cout << "WE GOT HERE" << endl;
}
}
void IntersectionFlowRate::setFlowCycle(int index, int flow){
cout << "INDEX: " << index << endl;
cout << "FLOW: " << flow << endl;
m_flowRateMotorCycle[index] = flow; //seg fault is here
}
I have another class that creates a pointer to a IntersectionFlowRate() object and then calls its setFlowCycle function passing in two VALID ints. With the debugging I was able pass 0 and 3 to the function setFlowCycle(0, 3) just fine and output those variables within the function.
#ifndef TRAFFICSIM_H
#define TRAFFICSIM_H
#include "IntersectionFlowRate.h"
using namespace std;
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
~TrafficSim(); //Destructor
private:
IntersectionFlowRate* m_flowRate;
};
#endif
#include "TrafficSim.h"
#include "IntersectionFlowRate.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
I replicated the error with this code. If no one else can I am completely unsure of what is possibly wrong anymore.
You are setting a local variable called m_flowRate, not the member variable m_flowRate of your TrafficSim class:
Instead of this:
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
It should be this:
TrafficSim::TrafficSim()
{
m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
But overall, it not need be a pointer. It could be an object member within your class. That would cut down on the pointer usage a bit:
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
private:
IntersectionFlowRate m_flowRate;
};
Then:
TrafficSim::TrafficSim()
{
m_flowRate.setFlowCycle(0, 3);
}
As to your question as to how to incorporate usage of std::vector in your class, here is a code sample of the IntersectionFlowRate class, rewritten using vector:
Vector sample
Also, another source of problems is that your classes fail to follow the Rule of 3 when you have pointers to dynamically allocated memory in your class.
Using std::vector takes care of this automatically, but if you insist on using pointers, you need to adhere to the directions at the link posted.
Yes, use a std::vector, it is much simpler, and it is a template so it also pretty fast and works any type (best for primitive types or pointers to objects) , and it also has boundary checking and other useful things.
If you need fast array-like access then you could use std::map which associates a key with a value, like so
std::map<UINT, YourClass*> m_mapIDs_to_YourClass;
When you first start using stl containers they might seem a little strange, but after a short while you cannot do without them, luckily they have been part of the C++ standard for some time now.
Boundary check for both these containers can be done by comparing your iterator to mapYourMap.end(), if they are equal you have passed the last element and trying to access data through the iterator will cause an exception.
Example for std::vector (if vecInt is a vector< int >):
vector<int>::iterator it = vecInt.begind();
if (it == vecInt.end()) return; // vector is empty
do { // runs through elememts until out of bound, useful for searching
i++
while (it != vecInt.end());

Vector with multiple class objects yields a compilation error?

For the following class I wanted to make a vector with 10 Ship() objects
However this yields the following compilation error invalid conversion from 'int' to 'const char*' [-fpermissive]
( If I omit the vector line it compiles just fine)
I did a little search and could not find an answer.
class Ship
{
protected:
std::string name;
public:
Ship(std::string name="Ship")
{
std::ostringstream tmp;
std::string temp;
tmp << name << ++id;
name = tmp.str();
}
};
Vector Declaration in main()
#include <iostream>
#include <vector>
#include <string>
#include "Ship.h"
using std::cout;
using std::endl;
using std::vector;
int main()
{
vector<Ship> Shipyard; //10% of map dimension is number of ships
Shipyard.push_back(Ship(10)); //push_back(Ship(),10); doesn't work also
}
The constructor takes a std::string, but you're passing an integer
For 10 objects construction of same name use this 2nd form of constructor of std::vector :
vector<Ship> Shipyard( 10, Ship() );
Ship(10)
This will try to create one Ship object and call the constructor. However your constructor take string as argument and hence the error.
To create vector of 10 Ships use:
vector<Ship> Shipyard(10, Ship());
You are constructing a Ship object with the value of 10. Since the constructor takes std::string, you cannot pass an integer to the constructor.
To add 10 ships:
std::vector<Ship> ShipYard(10);
or
std::vector<Ship> ShipYard;
ShipYard.resize(10);

C++ Generic Swap Function

In my class.h i got:
template<class T> void Swap(T, T);
And in class.cpp:
template<class T>
void class::Swap(T& p1, T& p2)
{
T aux = p1;
p1 = p2;
p2 = aux;
}
When I try :
this->Swap<char*>(&lit[i][k], &lit[i][l]);
And another question:
What am i doing wrong here: i want to split my string after some delimitators ("+-") and strtok isn't working as I expected.
int counter = 0;
char* s = strtok(eq_clone ," ");
while(s != NULL)
{
counter++;
if(s == "")
counter--;
s = strtok(eq_clone ,"+-");
}
This looks like a mistake as it will never be true:
if(s == "")
this is comparing the address of s to the address of the string literal "": it is not checking if s is an empty string. An alternative to using strtok() would be boost::algorithm::split:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
int main()
{
std::string s("a,string+with-multiple delimiters");
std::vector<std::string> s_tokens;
boost::algorithm::split(s_tokens, s, boost::is_any_of(",+- "));
std::for_each(s_tokens.begin(),
s_tokens.end(),
[] (const std::string& s)
{
std::cout << s << "\n";
});
return 0;
}
Output:
a
string
with
multiple
delimiters
Regarding swap, as has already been stated in comments and other answer(s) just use std::swap(). I am guessing that lit is a char[][] so std::swap(lit[i][k], lit[i][l]); will do exactly what you require.
EDIT:
After comment giving declaration string* lit and that lit appears to be an array (from example usage) then use std::swap() in this manner:
std::string* lit = new std::string[4];
lit[0] = "zero";
std::swap(lit[0][1], lit[0][2]); // The characters will be passed by reference,
// don't take address.
std::cout << lit[0] << "\n"; // Prints "zreo"
Note, that the declaration of your Swap() passes arguments by value (incorrect), but the definition of Swap() passes arguments by reference (correct). If you change the declaration of your Swap() and invoke it as follows it will work (if you really don't want to use std::swap():
template<class T> void Swap(T&, T&);
//^ //^
Swap(lit[i][k], lit[i][l]);
1) Why is Swap() a class member? Class members should somehow be tightly coupled to your classes. In most cases it is is sign of bad design if something, which does not use private members or is very similar to a method that does (i.e. a convinience method), becomes a class member. C++ is not java where everything has to belong to a class. Make your swap() method a free standing template method.
2) Better yet, do not reinvent the wheel. std::swap() is there and it works mightily well. In many cases you can expect the methods and classes provided by the standard library to work better than something you could write up.
3) In your class you called the method Sort(), but the question is about Swap(). Since you did not write what you expected to happen and what actually happens, this is the only thing I can find which might be wrong.
4) Do not use strtok() in C++ unless you have to. char* are C-Style strings and should not be used in C++. Use std::string instead.

Using explicit/raw pointers in c++

I read that using raw pointers in C++ is bad. Instead we should use auto_ptr. In the below code I am populating a vector in foo() that is created in the main(). Am I doing it right or is there a better way to do without using explicit pointers.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void foo(vector<string> *v){
(*v).push_back(" hru");
}
int main(){
vector<string> v;
v.push_back("hi");
foo(&v);
for(int i=0;i<v.size(); i++){
cout << v[i];
}
}
C++ uses references for what you are trying to do:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void foo(vector<string>& v){
v.push_back(" hru");
}
int main(){
vector<string> v;
v.push_back("hi");
foo(v);
for(int i=0;i<v.size(); i++){
cout << v[i];
}
}
References and pointers are similar, with one very important distinction: there is no such thing as a null reference (Constructing one is Undefined Behavior in C++ you can construct one, but doing so is considered a hack).
In C++ you can avoid the pointer and use a pass-by-reference:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void foo(vector<string>& v){
v.push_back(" hru");
}
int main(){
vector<string> v;
v.push_back("hi");
foo(v);
for(int i=0;i<v.size(); i++){
cout << v[i];
}
}
You can begin to think about using auto_ptr when you deal with objects created on heap (e.g. a class instance created by "new"). Your vector holds its elements by value, std::string elements it is. So you don't need to consider auto_ptr here at all. If your vector would hold instances created on heap then you could use something like this:
std::vector< auto_ptr< MyType > > vec;
auto_ptr< MyType > a( new MyType() );
vec.push_back( a );
and then when your vector elements get erased by e.g. your vec leaving its scope then instance 'a' will get deleted automatically.
With other words, auto_ptr is a kind of garbage collector which does a kind of automatic object deletion for you. See here for more information about auto_ptr http://www.cplusplus.com/reference/std/memory/auto_ptr