Constructor

Hi,
I have in class private char* region. I need create constructor which takes as argument data of type char* and on the basis of that data constructor determines region of some object. Data which is argument looks like this:(for example:"Lombardia Milano").So region is, in this case, Lombardia and city is Milano. How to do that?
why not use string instead?

what exactly do you want to do? It isnt clear.
you can copy the argument's data to your private variable. to do that, you need something like
int l = strlen(input);
private_var = new char[l+1];
strcpy(private_var, input);
and your destructor needs to release the memory.

is that ^^^ what you want to know?

do not just copy the pointers:
private_var = input; //this will work, but its very risky. any changes to input in the calling program will break the class variable too, and it takes away the private-ness of the variable. This idea can be useful in high performance code where you accept the risks and manage them, but in general, this idea is poor.

ideally you would use string and just say
private_var = input; //ok, not pointers, copying is correct and safe and simple.
Maybe he's trying to split the input string at the space. This is perhaps the simplest way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <sstream>
#include <string>

class Place {
    std::string region, city;
public:
    Place(std::string s) {
        std::istringstream iss(s);
        iss >> region >> city;
    }
    void print() const {
        std::cout << region << ", " << city << '\n';
    }
};

int main() {
    Place place("  Lombardia    Milano  ");
    place.print();
}

Yes, dutch. I need to split that, but I don't think I have to use this method (with std::string).
My assignment is next.
Write class GeoMap with following private attributes:
region(char*)
city(char*)
surface(double)
population (int)
timezone(int)
hours (int)
minutes (int)
mark(char*)
Write constructor that takes as argument one char array (data of type char*) and on the basis of it sets values of attributes. For example:"Lombardia Milano 181.76 1360422 +5".
I tried to use strtok, but it doesn't work. Am I maybe clearer now?
I tried to use strtok, but it doesn't work.

std::strtok() is a vintage C legacy, but it works.
Anyway, it modifies the passed char*, so you need to guarantee you’re working on a memory area you own.
https://en.cppreference.com/w/cpp/string/byte/strtok

You’d better take good note of what jonnin told you:
jonnin wrote:
to do that, you need something like
int l = strlen(input);
private_var = new char[l+1];
strcpy(private_var, input);
and your destructor needs to release the memory.

Once you have got your ‘private_var’ pointer (which points to a memory area you own), you can use std::strtok on it.

However, we can help you with your code if you post it. Otherwise, it’s a guessing game.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string.h>
#include <string>
#include <stdlib.h>
using namespace std;
class GMapa{
private:
    char * regija;
    char * grad;
    double povrsina;
    int brojStanovnika;
    char *zona;
    int sati;
    int minuti;
    char * oznaka;
public:
GMapa(char* c){
    char f[]=" ";
regija=strtok(c,f);
grad=strtok(NULL,f);
povrsina=atof(strtok(NULL,f));
brojStanovnika=int(strtok(NULL,f));
zona=strtok(NULL,f);
    }
void ispis(){
cout<<regija<<endl;
cout<<grad<<endl;
cout<<povrsina<<endl;
cout<<brojStanovnika<<endl;
cout<<zona<<endl;
}
};
int main(){
    GMapa g("Lombardija Milano 181.76 1360422 +5");
    g.ispis();
    return 0;
}

It does not work. Resaons and advices what to fix?
Last edited on
It does not work. Resaons and advices what to fix?


Reasons
---------

The compiler is already explaining the problem. Just read:
main.cpp:34:13: error: ISO C++ forbids converting a string constant to 'char*' [-Werror=write-strings]
   34 |     GMapa g("Lombardija Milano 181.76 1360422 +5");
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


A “string constant”, also known as a string literal is stored in a read-only memory area. You cannot assign it to a char* (in standard C++).

This program raises a warning:
1
2
3
4
int main()
{
    char * str = "Lombardija Milano 181.76 1360422 +5";
}


This program compiles fine:
1
2
3
4
int main()
{
    const char * str = "Lombardija Milano 181.76 1360422 +5";
}


Anyway, even assuming you changed your (badly indented and plenty of issues) code from
 
GMapa(char* c)

to
 
GMapa(const char* c)

you would anyway face another error:
main.cpp: In constructor 'GMapa::GMapa(const char*)':
main.cpp:19:15: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
   19 | regija=strtok(c,f);
      |               ^
      |               |
      |               const char*
In file included from main.cpp:2:
/usr/include/string.h:343:39: note:   initializing argument 1 of 'char* strtok(char*, const char*)'
  343 | extern char *strtok (char *__restrict __s, const char *__restrict __delim)
      |                      ~~~~~~~~~~~~~~~~~^~~


Advice
-------

You can easily solve this last problem simply by reading what you have already being told.
(Later we can deal with the following one.)
Enoizat,
OK, I think this method is good. Can you explain why?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string.h>
#include <string>
#include <stdlib.h>
using namespace std;
class GMapa{
private:
    char * regija;
    char * grad;
    double povrsina;
    int brojStanovnika;
    char *zona;
    int sati;
    int minuti;
    char * oznaka;
public:
GMapa(char* c){
    char f[]=" ";
regija=strtok(c,f);
grad=strtok(NULL,f);
povrsina=atof(strtok(NULL,f));
brojStanovnika=int(strtok(NULL,f));
zona=strtok(NULL,f);
    }
void ispis(){
cout<<regija<<endl;
cout<<grad<<endl;
cout<<povrsina<<endl;
cout<<brojStanovnika<<endl;
cout<<zona<<endl;
}
};
int main(){
   string str = "Lombardija Milano 181.76 1360422 +5";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
    GMapa g(cstr);
    g.ispis();
    return 0;
}
I think this method is good

I can guarantee you jonnin’s method was correct as well:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <cstdlib>
#include <cstring>
#include <iostream>


class GMapa {
public:
    explicit GMapa(const char * const s);
    ~GMapa();
    void ispis();

private:
    char * regija { nullptr };
    char * grad { nullptr };
    double povrsina {};
    int brojStanovnika {};
    char *zona { nullptr };
    int sati {};
    int minuti {};
    char * oznaka { nullptr };
};


GMapa::GMapa(const char * const s)
{
    const auto len { std::strlen(s) + 1 };
    auto * s_new { new char[len] };
    std::strcpy(s_new, s);

    regija = std::strtok(s_new, " ");
    grad = std::strtok(nullptr, " ");
    povrsina = std::atof( std::strtok(nullptr, " ") );

    // This is wrong and causes the compilation to fail:
    // brojStanovnika = int( std::strtok(nullptr, " ") );

    zona = std::strtok(nullptr, " ");
    // sati?
    // minuti?
    // oznaka?
}


GMapa::~GMapa()
{
    // clean up the memory here
}


void GMapa::ispis()
{
    std::cout << regija << '\n'
              << grad << '\n'
              << povrsina << '\n'
              << brojStanovnika << '\n'
              << zona << '\n';
}


int main()
{
    GMapa g("Lombardija Milano 181.76 1360422 +5");
    g.ispis();
    return 0;
}


Output:
Lombardija
Milano
181.76
0
1360422


Can you explain why?

I can try, but what parts of the previous three explanations are not clear?
Or better: how many words may I use before you stop reading?

std::strtok modifies the passed (C-style) string.
Therefore it’s first argument can be neither const nor stored in a read only memory area.
You need to pass a pointer to a memory area you own, for example one you obtain from “new”.
Thanks. I am beginner in C++ and in work with pointers, but I think that I understood your explanation.
Registered users can post here. Sign in or register to post.