I am creating CPP application that can create List's: string arrays. When initialization is called it get's variadic parameters and should insert them into a string array. It gives Segmentation error. Also if I remove Students_Second_Group.push(), everything works fine. Any suggestions?
// Main.cpp
#include "List.h"
int main() {
List Students_First_Group(4), Students_Second_Group(3);
Students_First_Group.push("Jonas Jonaits", "Tomas Tomaitis", "Petras Petraitis", "Donatas Petkevicius");
Students_Second_Group.push("Mantas Jonaitis", "Tautvydas Tomaitis", "Linas Linaitis");
return 0;
}
// List.h
#ifndef _LIST_H_
#define _LIST_H_
#include <iostream>
#include <string>
#include <vector>
#include <cstdarg>
using namespace std;
class List {
private:
size_t size;
vector<string> arr;
public:
List(int size);
void push(const char* str...);
~List();
};
#endif
// List.cpp
#include "List.h"
List::List(int s) {
if(size > 0)
size = s;
else
size = 10;
arr = vector<string> (s);
}
void List::push(const char* str...) {
va_list arg;
va_start(arg, str);
while (str) {
arr.push_back(str);
str = va_arg(arg, const char *);
}
va_end(arg);
}
List::~List() {}
you can solve your issue with varadic template but
because they are template varadic template should be put in the header
for more info http://en.cppreference.com/w/cpp/language/parameter_pack
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class List {
private:
size_t size;
vector<string> arr;
void push() {}
public:
List(int size);
template<typename ... Rest>
void push(const char* first, Rest ... rest) {
arr.push_back(first);
push(rest...);
}
~List();
};
List::List(int s) {
if(size > 0)
size = s;
else
size = 10;
arr = vector<string> (s);
}
List::~List() {}
int main() {
List Students_First_Group(4), Students_Second_Group(3);
Students_First_Group.push("Jonas Jonaits", "Tomas Tomaitis", "Petras Petraitis", "Donatas Petkevicius");
Students_Second_Group.push("Mantas Jonaitis", "Tautvydas Tomaitis", "Linas Linaitis");
return 0;
}
I've got a huge problem with memory leaks in my program.
I use Valgrind to check memory leaks and with some changes I got about ~20 errors or ~40 errors, but still I can't eliminate all and don't know how.
And I can't change the code in main function, I must fit to it.
I can't change specialisation to string!
Question is what is a properly way to manage with char* and memory.
Rules:
Main code is unchangable
Don't pack char* in any smart pointers or other types.
Problem
Managing memory with char* with containers.
Is it still possible ?
Or instead of container safer is normally allocated array ?
What is wrong with my destructor for char* ?
My main function:
#include <iostream>
#include "test.h"
#include <vector>
using namespace std;
int main()
{
char * cpt[]={"tab","tab2","tab3"};
test<char*> test1;
test1.addItem(cpt[1]);
char * item=test1.getItem(0);
item[0]='Z';
cout<<item<<endl;
return 0;
}
test.h
#ifndef TEST_H
#define TEST_H
#include <vector>
using namespace std;
template<class T>
class test
{
public:
~test();
void addItem(T element){
elements.push_back(element);
}
T getItem(int i){
return elements[i];
}
vector<T> elements;
};
#endif // TEST_H
test.cpp
#include "test.h"
#include <iostream>
#include <cstring>
using namespace std;
template<>
char * test<char*>::getItem(int i)
{
/*char *nowy=new char(strlen(elements[i])+1);
//strcpy(nowy,elements[i]);
return nowy;
//with above code 39 errorr in Valgrind
*/
return elements[i]; // with this instead of above 19 errors in Valgrind
}
template<>
void test<char*>::addItem(char* element){
char * c= new char( strlen (element)+1);
strcpy(c,element);
elements.push_back(c);
}
template<>
test<char*>:: ~test(){
for( auto v: elements)
delete []v; //with this 20 errors
//delete v; instead of above line 19 errors;
}
You should replace
new char(strlen (element) + 1); // this allocate one char with given initial value
by
new char[strlen (element) + 1]; // array of (uninitialized) char
to allocate array of char.
then you have to call delete [].
I'm trying to overload << operator but I get an error which is below.
rollingDice.h|14|error: ‘std::ostream& rollingDice::operator<<(std::ostream&, const rollingDice&)’ must take exactly one argument|
Here is my code. I separated implementation and decleration. I think the problem occurs due to that because I coded same as so many web pages and Deitel&Deitel show.
rollingDice.cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <stdlib.h>
#include "rollingDice.h"
using namespace std;
rollingDice::rollingDice(unsigned int valN)
{
n=valN;
r=new int [n];
}
int rollingDice::length()
{
return n;
}
void rollingDice::generate()
{
srand48(time(NULL));
int i=0;
for (i=0; i<n; ++i)
{
r[i]=1+(lrand48()%6);
}
}
rollingDice& rollingDice::init(unsigned int valN)
{
n=valN;
r=new int [n];
return *this;
}
ostream& operator << (ostream& output, rollingDice& rd)
{
int temp=n;
if (temp>12)
temp=12;
int i=0;
for (i=0; i<temp; ++i)
{
output << rd.r[i] << " ";
}
return output;
}
double rollingDice::getAverage()
{
generate();
double total=0;
int i=0;
for (i=0; i<n; ++i)
total+=r[i];
total=total/double(n);
return total;
}
rollingDice.h
#ifndef rollingDice_H
#define rollingDice_H
#include <string>
using namespace std;
class rollingDice
{
public:
rollingDice(unsigned int n);
void generate();
rollingDice& init(unsigned int valN);
double getAverage();
int length();
ostream& operator << (ostream& output, const rollingDice& rd);
private:
unsigned int n;
int* r;
};
#endif
rollingDiceApp.cpp
#include <iostream>
#include "rollingDice.h"
using namespace std;
int main()
{
rollingDice r(16);
cout<<r.getAverage()<<endl;
cout<<r.length()<<endl;
r.init(8).generate();
cout<<r.getAverage()<<endl;
cout<<r.length()<<endl;
}
In the class definition add keyword friend to the operator declaration
friend ostream& operator << (ostream& output, const rollingDice& rd);
Otherwise the compiler consideres the operator as a member function with the first implicit parameter that corresponds to this
Also take into account that in the operator definition it seems you have to use
int temp=rd.n;
instead of
int temp=n;
Friend functions can't access variables of the classes
I'm having a problem with several friend functions not being able to access the variables in classes where they have been declared as friends.
The actual error text is:
error: 'fid' was not declared in this scope. this repeats for the other private variables.
The same error is given for three functions, read, negative, and write.
A couple of notes:
1) This lab requires that I write the code so that the functions can be used by both classes.
I'm compiling this in windows with code::blocks using g++ and I've also tried compiling my code in ubuntu using g++ from the terminal using the -g flag and I get the same error both times.
Any suggestions you have would be greatly appreciated.
Header File
#ifndef PXMUTILS_H
#define PXMUTILS_H
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
using namespace std;
typedef unsigned char uchar;
class pgm
{
public:
pgm();
~pgm();
void read(string &);
void negative();
void write(string);
friend void read (const string &);
friend void write(string);
friend void negative();
private:
int nr;
int nc;
int mval;
int ftyp;
string fid;
uchar **img;
};
class ppm
{
public:
ppm();
~ppm();
void read(string &);
void negative();
void write(string);
friend void read (const string &);
friend void write (string);
friend void negative ();
private:
int nr;
int nc;
int mval;
int ftyp;
string fid;
uchar **img;
};
#endif
C++ program
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include "pxmutils.h"
using namespace std;
typedef unsigned char uchar;
uchar ** newimg(int nr, int nc, int ftyp)
{
uchar **img=new uchar *[nr];
img[0]=new uchar [nr*nc*ftyp];
for(int i=1; i<nr; i++)
{
img[i]=img[i-1]+nc*ftyp;
}
return img;
}
void deleteimg(uchar **img)
{
if(img)
{
if(img[0])
{
delete [] img[0];
}
delete [] img;
}
}
void read (const string &fname)
{
ifstream fin(fname.c_str(), ios::in);
if(!fin.is_open())
{
cerr<<"Could not open "<<fname<<endl;
exit(0);
}
fin >>fid
>>nc
>>nr
>>mval;
while (fin.get() != '\n') { /*skip to EOL */ }
img=newimg(nr, nc);
fin.read((char *)img[0], nr*nc);
fin.close();
}
void set_cmap(string mname)
{
}
void negative()
{
for(int i=0; i<nr; i++)
{
for(int j=0; j<nc; j++)
{
int t=img[i][j];
img[i][j]=(255-t);
}
}
}
void write(string fname)
{
ofstream fout (fname.c_str(), ios::out);
size_t dp;
if ((dp = fname.rfind(".pgm")) != string::npos)
{
fout<<"P5"<<endl;
}
if((dp= fname.rfind(".ppm")) != string::npos)
{
fout<<"P6"<<endl;
}
fout<<nc<<" "<<nr<<endl;
fout<<mval<<endl;
for(int i=0; i <nr; i++)
{
for (int j=0; j<nc; j++)
{
fout<<img[i][j]<<" ";
}
fout<<endl;
}
fout.close();
}
pgm::pgm()
{
nr=0;
nc=0;
mval=0;
ftyp=1;
fid="";
img=NULL;
}
pgm::~pgm()
{
deleteimg(img);
}
ppm::ppm()
{
nr=0;
nc=0;
mval=0;
ftyp=1;
fid="";
img=NULL;
}
ppm::~ppm()
{
deleteimg(img);
}
Program to test functions
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
#include "pxmutils.h"
int main(int argc, char *argv[])
{
if (argc == 1) {
cerr << "No input file specified!\n";
exit(0);
}
string fname = argv[1];
size_t dp;
if ((dp = fname.rfind(".pgm")) == string::npos) {
cout << "PGM error: file suffix " << fname
<< " not recognized\n";
exit(0);
}
fname.erase(dp);
pgm img_g;
ppm img_c;
img_g.read(fname+".pgm");
if (argc == 3)
img_c.set_cmap(argv[2]);
img_c = img_g;
img_g.negative();
img_g.write(fname+"_n.pgm");
img_c.write(fname+"_c.ppm");
}
fin >>fid
>>nc
>>nr
>>mval;
while (fin.get() != '\n') { /*skip to EOL */ }
In this code, fid, nc, nr etc are undefined. You need to use the class instance to be able to access them, they don't exist by themselves.
Your functions don't accept the class objects as parameters, so how are you going to read into them?
You should have another think of your design. It is best to avoid friend functions if possible,
You need to go a bit back to basics. When you define non-static members of a class you are defining attributes or operations of the objects of the class, but those attributes don't exist by themselves, only as part of the instances of the class.
This concept is orthogonal to access and access specifiers, that is, this is so regardless of the members being public, protected or private. Once you have an instance, when your try to access those members the access specifiers come into play, and there is where friendship comes into play: it will grant your code access to members that would otherwise be inaccessible (private or protected outside of the inheritance hierarchy).
The problem in your code is that you don't have an object, and thus cannot access the members of the object. You will need to either create or pass an object of the appropriate type to the functions.
There are other problems in the code, like for example, the memory allocations inside newimg look a little suspicious (what were you intending to allocate?) but that is outside of the scope of this question.
Say there is a list of integers [1,2,3,4,5] and a map function that multiplies each element with 10 and returns modified list as [10,20,30,40,50] , with out modifying the original list.
How this can be done efficiently in c++.
Here's an example:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int multiply(int);
int main() {
vector<int> source;
for(int i = 1; i <= 5; i++) {
source.push_back(i);
}
vector<int> result;
result.resize(source.size());
transform(source.begin(), source.end(), result.begin(), multiply);
for(vector<int>::iterator it = result.begin(); it != result.end(); ++it) {
cout << *it << endl;
}
}
int multiply(int value) {
return value * 10;
}
Along the lines of #darids answer, but C++03 (current at the time of original post):
#include <vector>
#include <algorithm>
#include <functional>
std::vector<int> src;
std::vector<int> dst;
std::transform(src.begin(), src.end(),
std::back_inserter(dst),
std::bind1st(std::multiplies<int>(), 10));
If you can use it, probably the best idea is to use a function in the Standard Template Library.
For example, you might want to check out for_each or transform, which basically do just that.
I only post this to illustrate using a functor in transform rather than a global function:
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;
struct MulBy : public std::unary_function<int, int>
{
MulBy(int v) : v_(v) {}
int operator()(int lhs) const
{
return lhs * v_;
}
private:
int v_;
};
int main()
{
int incoming[5] = {1, 2, 3, 4, 5};
int result[5] = {0, 0, 0, 0, 0};
transform(&incoming[0], &incoming[5], &result[0], MulBy(10));
copy(&result[0], &result[5], ostream_iterator<int>(cout, " "));
return 0;
}
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
struct MulBy : public std::unary_function<int, int>
{
MulBy(int v) : v_(v) {}
int operator()(int lhs) const
{
return lhs * v_;
}
private:
int v_;
};
int main()
{
vector<int> ListOfNumber;
ListOfNumber.push_back(1);
ListOfNumber.push_back(2);
ListOfNumber.push_back(3);
ListOfNumber.push_back(4);
ListOfNumber.push_back(5);
vector<int> ListResult;
ListResult.resize(ListOfNumber.size());
//Produces a new list
transform(ListOfNumber.begin(),ListOfNumber.end(),ListResult.begin(),MulBy(10));
copy(ListOfNumber.begin(),ListOfNumber.end(),ostream_iterator<int>(cout,"\t"));
//Modifies the original list
transform(ListOfNumber.begin(),ListOfNumber.end(),ListOfNumber.begin(),MulBy(10));
copy(ListResult.begin(),ListResult.end(),ostream_iterator<int>(cout,"\t"));
cin.get();
}
This is my implementation for an array map method, inspired directly from javascript
#include <vector>
#include <functional>
namespace wh{
namespace array{
template<typename T>
std::vector<T> map(const std::vector<T> &vectorToMap, const std::function<T(T)> &functor){
std::vector<T> ret;
for(auto &element: vectorToMap){
ret.push_back(functor(element));
}
return ret;
}
...
}
}
#include <iostream>
int main()
{
//'spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'
std::vector<std::string> words = {"spray", "limit", "elite", "exuberant", "destruction", "present", "windows", "wlol"};}
// and this is how it is used:
words = wh::array::map<std::string>(words, [](auto word){return word+"l";});
for(auto &word: words) std::cout << word << std::endl;
return 0;
}
Maybe this will be useful for someone else, still, if <algorithm> functions are a better approach, go ahead and use them.