Can't do a strcpy from 2D array to another 2D array - c++

Both are in the operator= in the same class
here is the definition of the function.
void segment::operator=(const segment& w) {
strcpy(this->phrase, w.getPhrase()); //this line creates a problem.
error is below:
segment.cpp: In member function ‘void segment::operator=(const segment&)’:
segment.cpp:186: error: passing ‘const segment’ as ‘this’ argument of ‘const char*
segment::getPhrase()’ discards qualifiers
segment.cpp:186: error: cannot convert ‘char (*)[40]’ to ‘char*’ for argument ‘1’ to ‘char* strcpy(char*, const char*)’
const char* segment::getPhrase(){
return *phrase;
}
And above is the function getPhrase
I don't know why I can't do a strcpy for that.
I'm trying to completet the assignment.
EDIT:
This is the type of phrase
char phrase[10][40];

There are two problems. First you have to make getPhrase a const method. The second problem is that strcpy doesn't work with an extra level of indirection. You probably need something like this:
const char* segment::getPhrase(int index) const {
return phrase[index];
}
void segment::operator=(const segment& w) {
int index;
for (index = 0; index < 10; ++index) {
strcpy(this->phrase[index], w.getPhrase(index));
}
}
You should replace the 10 with constant
class segment {
//other stuff
static const int kNumPhrases = 10;
char phrase[kNumPhrases][40];
}

Related

Why initialization of const char array member incompatible in constructor initializer?

I have a Test class with overloaded constructor. Initializing const char array member by string literals work fine. But, initialization by const char * gives error -
error: incompatible types in assignment of ‘const char*’ to ‘const
char [25]’
class Test
{
const char d_arr[25];
public:
Test() : d_arr("Test Class") {}
Test(const char * arr) : d_arr(arr) {}
};
How to resolve this?
You are assigning a pointer to an array, which is not allowed.
i.e. You cannot do following:
const char *arr = "ABC";
const char d_arr[25] = arr;
What you need to do is copy the chars manually i.e. something like:
Test(const char * arr) {
size_t index = 0;
if (arr) {
while (arr[index] && index < 24) {
d_arr[index] = arr[index];
++index;
}
}
d_arr[index] = 0;
}
That all said, as said in comments, its better to use std::string.

Growing Array of Pointers ERROR: Incompatible types in assignment

I'm working on an assignment and I have this error which makes no sense to me. Basically we have the class "Playlist" which has an array of pointers to "Track"s
class Playlist{
private:
string playlistName;
int trackCount;
Track* tracks[0];
public:
Playlist(string name);
Track* GetTrack(int index);
int GetTrackCount();
void AddTrack(Track* track, int index);
void AddTrack(Track* track);
void RemoveTrack(int index);
void RemoveTrack(Track* track);
};
The error is occurring in the functions AddTrack(Track t,int i) and RemoveTrack(int i)
Playlist.cpp: In member function ‘void Playlist::AddTrack(Track*, int)’:
Playlist.cpp:27:11: error: incompatible types in assignment of ‘Track* [(((Playlist*)this)->Playlist::trackCount + 1)]’ to ‘Track* [1]’
tracks= newtracks;
^
Playlist.cpp: In member function ‘void Playlist::RemoveTrack(int)’:
Playlist.cpp:42:12: error: incompatible types in assignment of ‘Track* [(((Playlist*)this)->Playlist::trackCount + -1)]’ to ‘Track* [1]’
tracks = newtracks;
^
student#ldnel:~/Documents/A2$ g++ -std=c++14 *.cpp
Playlist.cpp: In member function ‘void Playlist::AddTrack(Track*, int)’:
Playlist.cpp:28:11: error: incompatible types in assignment of ‘Track* [newSize]’ to ‘Track* [1]’
tracks= newtracks;
^
Playlist.cpp: In member function ‘void Playlist::RemoveTrack(int)’:
Playlist.cpp:44:12: error: incompatible types in assignment of ‘Track* [newSize]’ to ‘Track* [1]’
tracks = newtracks;
^
Here's my function implementations:
Playlist::Playlist(string name){
playlistName=name;
}
Track* Playlist::GetTrack(int index){
return tracks[index];
}
int Playlist::GetTrackCount(){
return trackCount;
}
void Playlist::AddTrack(Track* track, int index){
int newSize = trackCount+1;
Track *newtracks[newSize];
for(int i=0;i<newSize;i++){
if(i<index){
newtracks[i] = tracks[i];
}else if(i==index){
newtracks[i]=track;
}else{
newtracks[i]=tracks[i-1];
}
}
tracks= newtracks;
trackCount++;
}
void Playlist::AddTrack(Track* track){
AddTrack(track,trackCount);
}
void Playlist::RemoveTrack(int index){
int newSize = trackCount-1;
Track *newtracks[newSize];
for(int i=0;i<newSize;i++){
if(i<index){
newtracks[i]=tracks[i];
}else{
newtracks[i]=tracks[i+1];
}
}
tracks = newtracks;
trackCount--;
}
void Playlist::RemoveTrack(Track* track){
for(int i=0;i<trackCount;i++){
if(tracks[i]==track){
RemoveTrack(i);
return;
}
}
}
What I plan on doing is having a Data Manager class that dynamically stores all Tracks and playlists would have a refernce to the tracks it includes. I do not know why it considers the two arrays of different types
You are trying to assign an array of the length x to an array of a different size. I suggest you use std::vector(http://en.cppreference.com/w/cpp/container/vector) instead of an array.
You might also want to consider using a std::shared pointer (http://en.cppreference.com/w/cpp/memory/shared_ptr).
You might also need to take a look at iterators (http://en.cppreference.com/w/cpp/iterator/iterator) for your AddTrack(Track * track, int index) function.
I would implement it like this:
class Playlist {
private:
std::string playlistName;
int trackCount;
std::vector<std::shared_ptr<Track>> tracks;
public:
Playlist(std::string name);
std::shared_ptr<Track> GetTrack(int index);
int GetTrackCount();
void AddTrack(std::shared_ptr<Track> track, int index);
void AddTrack(std::shared_ptr<Track> track);
void RemoveTrack(int index);
void RemoveTrack(std::shared_ptr<Track> track);
};
Here would be my add functions:
void Playlist::AddTrack(std::shared_ptr<Track> track, int index) {
std::vector<std::shared_ptr<Track>>::iterator itor = tracks.begin();
itor += index;
tracks.insert(itor, track);
}
void Playlist::AddTrack(std::shared_ptr<Track> track) {
tracks.push_back(track);
}
I am confident you can implement the rest on your own. :)

Error: invalid conversion from 'int' to 'const char*' [-fpermissive]

I am experiencing an error and I can't figure out why.
I have a subclass: (Header)
class motionSensor: public sensorLeaf
{
public:
motionSensor(const int& sensorID, const int& sensorType, bool sensorActivate);
Which inherits from superclass "sensorLeaf"
The subclass has 2 private variables
const float minDistance;
const float maxDistance;
In my class file; here is my constructor:
motionSensor::motionSensor(const int &sensorID, const int &sensorType, bool sensorActivate)
:sensorLeaf(sensorID, sensorType, sensorActivate), minDistance{1.0f}, maxDistance{5.0f}
But once I compile it, I get following error:
/home/jb/EmergencySensor/motionsensor.cpp:8: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
:sensorLeaf(sensorID, sensorType, sensorActivate), minDistance{1.0f}, maxDistance{5.0f}
^
Sensorleaf Constructor is :
sensorLeaf::sensorLeaf(const int sensorID, const std::string sensorType, bool sensorActivate)
{
_sensorID = sensorID;
_sensorType = sensorType;
_sensorActivate = sensorActivate
}
With as private variables:
private:
int _sensorID;
std::string _sensorType;
bool _sensorActivate;
};
After doing some research I found that the error could occur when you define a string as ' ' and not " " but I have not used this anywhere so.
You're trying to force a const int &sensorType from motionSensor constructor to const std::string sensorType of sensorLeaf constructor.
motionSensor::motionSensor(const int &sensorID, const int &sensorType, bool sensorActivate)
------------------------------------------------------------^
:sensorLeaf(sensorID, sensorType, sensorActivate), minDistance{1.0f}, maxDistance{5.0f}
-----------------------^
sensorLeaf::sensorLeaf(const int sensorID, const std::string sensorType, bool sensorActivate)
-------------------------------------------------------------^

How do you compare a string to a vector value?

How to you do a string comparison in a to a value in a vector<std::string>?
I tried str, the error is printed below.
.....
vector<std::string> dat;
vector<std::string> pdat;
dat = my();
for(int b = 2; b < dat.size(); b+=7){
// cout << dat[b] << " " << endl;
if(!strcmp(dat[b], "String\n"){ // The error is here
pdat.push_back(dat[b]);
}
}
my.cpp: In function 'std::vector > ngr()':
my.cpp:53:32: error: cannot convert '__gnu_cxx::__alloc_traits > >::value_type {aka std::basic_string}' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'
std::string is compared with plain ==. This works because the == operator is overloaded to do a string comparison for std::strings.
if (dat[b] == "String\n") {
If you're dealing with C++ strings, you shouldn't need any of the str* functions from string.h, so you might as well not include it at all.
Simply use operator== on to compare an std::string and a const char* :
if(dat[b] == "String\n"){ //
pdat.push_back(dat[b]);
}
For the record, the exact overload used here is the function template :
template< class CharT, class traits, class Alloc >
bool operator==( const basic_string<CharT,Traits,Alloc>& lhs, const CharT* rhs );
strcmp (that you dont need here, and rarely need in C++) expects const char* arguments :
int strcmp( const char *lhs, const char *rhs );
So you could (but shouldn't) invoke it with th help of the c_str() member function :
if(!strcmp(dat[b].c_str(), "String\n")
...
strcmp() expects 2 const char*s but dat[b] is a string, so you aren't comparing apples with apples.
You can either do
if(!strcmp(dat[b].c_str(), "String\n"){
Or
if (dat[b] == "String\n") {
The second is the more C++ approach.

Ambiguous overload of std::vector::operator[]

I have a simple wrapper around C null-terminated string, which is essentially a subclass of std::vector< char >. (Yes, I know about std::string, but my wrapper is easier to cooperate with C functions expecting char*. Also, std::string isn't guaranteed to be contiguous in C++03)
Here is the code:
#include <cstdio>
#include <vector>
typedef std::vector<char> vector_char;
class c_string : public vector_char
{
public:
c_string(size_t size) : vector_char(size+1) {}
c_string(const char* str)
{
if(!str) return;
const char* iter = str;
do
this->push_back(*iter);
while(*iter++);
}
c_string() {}
//c_string(std::nullptr_t) {}
char* data()
{
if(this->size())
return &((*this)[0]); //line 26
else
return 0;
}
const char* data() const { return this->data(); }
operator char*() { return this->data(); }
operator const char*() const { return this->data(); }
};
int main()
{
c_string first("Hello world");
c_string second(1024);
printf("%s",first.data());
printf("%c\n",first[0]);
snprintf(second, second.size(), "%d %d %d", 5353, 22, 777);
printf(second);
}
MinGW complains about:
D:\prog\PROJEKTYCPP\hehe_testc_cpp.cpp: In member function 'char* c_string::data()':
D:\prog\PROJEKTYCPP\hehe_testc_cpp.cpp:26:22: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
In file included from d:\prog\mingw\bin\../lib/gcc/mingw32/4.7.0/include/c++/vector:65:0,
from D:\prog\PROJEKTYCPP\hehe_testc_cpp.cpp:2:
d:\prog\mingw\bin\../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_vector.h:768:7:note: candidate 1: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[]:(std::vector<_Tp, _Alloc>::size_type) [with _Tp = char; _Alloc = std:
:allocator<char>; std::vector<_Tp, _Alloc>::reference = char&; std::vector<_Tp,_Alloc>::size_type = unsigned int]
D:\prog\PROJEKTYCPP\hehe_testc_cpp.cpp:26:22: note: candidate 2: operator[](char
*, int) <built-in>
How can I enforce calling correct overload? Can this problem hurt me silently?
By having an operator char * you've provided two ways to do operator[]. The first is std::vector::operator[] applied directly; the second is to convert this to char* and apply [] to that. In this case they both result in the same thing, but the compiler can't know that.
Resolve it by specifying explicitly which one you want.
return &(operator[](0)); //line 26
or
return &((char*)(*this)[0]); //line 26
To delete the first warning, you can do this:
char* data()
{
if(this->size())
return &vector_char::operator[](0);
else
return 0;
}
To delete all warnings, remove the operator char*() and operator const char*() members.