0

I would like to initialize objects attribute but it just keep saying type mismatch. How to correct it?

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;
class Student{
public:
    int nr_ID;
    char nazwisko[40];
    char imie[40];
    double punkty;
    Student* next;

    Student(int nr_ID, char nazwisko[40], char imie[], double punkty){
        this->nr_ID = nr_ID;
        this->nazwisko = nazwisko;//HERE
        this->imie = imie;//HERE
        this->punkty = punkty;
        next = NULL;
    }

    ~Student(){}

};
Yoda
  • 17,363
  • 67
  • 204
  • 344
  • 1
    Always prefer an initializer list. – chris Apr 09 '13 at 14:56
  • 4
    Stop using character arrays and start using strings – David Heffernan Apr 09 '13 at 14:56
  • If you insist on doing it this way, use `strcpy()` for the char arrays - http://www.cplusplus.com/reference/cstring/strcpy/ – Roger Rowland Apr 09 '13 at 14:56
  • @DavidHeffernan Or vectors. – Alexey Frunze Apr 09 '13 at 14:57
  • 1
    Oh no, don't use vector for a string! – David Heffernan Apr 09 '13 at 14:57
  • 1
    The `nazwisko` parameter is actually a pointer (due to bad language design). You cannot assign an array a pointer. See [_How do I use arrays in C++?_](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c). –  Apr 09 '13 at 14:57
  • 1
    @DavidHeffernan: why not? (and I'm only half kidding) At least it doesn't have any false pretenses. It's a container of chars. So is a `std::string`, but a `std::string` is, at the same time, camouflaged to look like it stores *text*. It doesn't, not any more than `std::vector` does. – jalf Apr 09 '13 at 15:15

6 Answers6

5

There's no such thing as an array type argument. That argument that you've declared char nazwisko[40] is actually transformed into a pointer type char* nazwisko. So now you can see that you're trying to assign a pointer to an array. Of course that won't work.

In fact, you cannot simply assign arrays to each other at all. You must copy the elements across if you need to. You could use the C function strcpy to do that, which will take into account that the argument should be a C-style string. If you want to copy the full array, then you might like to use std::copy.

If you are indeed working with strings of text, you're much better off using the standard std::string type to do this. They are much easier to pass around and assign than arrays of char:

std::string nazwisko;
std::string imie;
// ...

Student(int nr_ID, std::string nazwisko, std::string imie, double punkty){
    this->nazwisko = nazwisko;
    this->imie = imie;
    // ...
}

In fact, you can save yourself the pain of default initializing those member variables and then just assigning to them by using the constructor member initialization list:

Student(int nr_ID, std::string nazwisko, std::string imie, double punkty)
  : nr_ID(nr_ID), nazwisko(nazwisko), imie(imie), punkty(punkty), next(NULL)
{ }
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • 1
    Depending on the semantics, you may also consider `std::vector` instead of `std::string`. –  Apr 09 '13 at 15:02
  • Very rare that `vector` is a valid replacement for `std::string`. – Mats Petersson Apr 09 '13 at 15:07
  • To be honest, if I was designing the standard library I would have made the string library basically a wrapper of any container which then provides a string-like view of the elements. Then `std::string` would just wrap `std::vector` and offer useful string functionality. – Joseph Mansfield Apr 09 '13 at 15:14
3

Just for completeness, here's how you could get closer to the original code (e.g., as someone suggested, if you can't use std::string for some obscene reason). This is largely overkill and highly un-typical code, but hey :)

template <size_t Lnaz, size_t Limi>
Student(int nr_ID, char const (&nazwisko)[Lnaz], char const (&imie)[Limi], double punkty)
    : nr_ID(nr_ID), punkty(punkty), next(nullptr)
{
    static_assert(Lnaz <= sizeof(this->nazwisko)/sizeof(*this->nazwisko), "too large");
    static_assert(Limi <= sizeof(this->imie)/sizeof(*this->imie), "too large");

    std::copy(nazwisko, nazwisko+Lnaz, this->nazwisko);
    std::copy(imie, imie+Limi, this->imie);
}

Note

  • this allows the strings to contain embedded NUL characters.
  • the trick is to pass the arrays by reference in order to avoid decay-to-pointer as described by others
  • also, the template is there because "hello" would be char const (&)[6], and "bye" would be char const (&)[4] - different argument types

See it live on http://liveworkspace.org/code/2rxQrg$1

sehe
  • 374,641
  • 47
  • 450
  • 633
1

You could simplify the problem by replacing the char arrays be std::string (or std::vector<char> if your char arrays are not meant contain null terminated strings):

class Student{
public:
  int nr_ID;
  std::string nazwisko;
  std::string imie;
  double punkty;
  Student* next;

  Student(int nr_ID, 
          const std::string& nazwisko, 
          const std::string& imie, 
          double punkty)
    : nr_ID(nr_ID), nazwisko(nazwisko), imie(imie), punkty(punkty), next(NULL)
  {}
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • `std::string` does contain a null-terminated string in C++11 as far as I'm aware, or it can at least be used with C functions. – chris Apr 09 '13 at 15:06
  • @chris what I mean is, in the unlikely event that OP's `char` arrays were not meant to contain null terminated strings, `std::vector` would be a more suitable replacement than `std::string`. – juanchopanza Apr 09 '13 at 15:07
  • Actually, yeah, I was just thinking back to using them for C string functions, not data :p – chris Apr 09 '13 at 15:11
0

To copy c-style character arrays, you need to use the strcpy function.

In C++, please use the std::string class. Everything else is a bug waiting to happen.

I just noticed you have a next pointer. If this isn't a homework assignment for linked lists, please consider using a container like std::list or std::vector instead.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
0

You didn't determine nazwisko stores a string or sequence of characters!

I assumed, it's a sequence of characters. (not a C-style string)

Use std::memcpy or std::copy

 Student(int nr_ID, char nazwisko[40], char imie[], double punkty){
        //...
        std::memcpy(this->nazwisko, nazwisko, 40);

        or

        std::copy(nazwisko, nazwisko+40, this->nazwisko);
        //...
    }
masoud
  • 55,379
  • 16
  • 141
  • 208
0

You cannot assign an array to another array (which looks like what you wanted), and you cannot assign a pointer to an array (which is what you are trying). You will need to copy the elements.

On a function signature, and when calling that function, arrays decay to pointers, I usually find that having the code look like what the compiler processes help in readability of the code. Your constructor signature is:

Student(int nr_ID, char *nazwisko, char *imie, double punkty)

You might want to consider adding extra size arguments to determine how big the block of memory passed to the function in the second and third arguments are. If they are plain strings, you can use strncpy to initialize the array members:

Student(int nr_ID, 
        char const *nazwisko, // make it 'const' you don't modify the argument
        char const *imie,     // same here
        double punkty)
   : nr_ID(nr_ID), punkty(punkty)       // prefer initializer lists
{
   strncpy(this->nazwisko, nazwisko, 39); this->nazwisko[39] = 0;
   strncpy(this->imie,     imie,     39); this->imie[39] = 0;
}
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489