Proyek saya meminta untuk mengimplementasikan kelas string di C ++, namun, saya bingung tentang salah satu fungsi publik

class String
{
private:
    char* buffer;
    int size;
    
public:
    // Initializes a string to be empty (i.e., its length will
    // be zero and toChars() will return "").
    String();

    // Initializes a string to contain the characters in the
    // given C-style string, which is assumed to be null-terminated.
    String(const char* chars);

    // Initializes a string to be a copy of an existing string,
    // meaning that it contains the same characters and has the
    // same length.
    String(const String& s);

    // Destroys a string, releasing any memory that is being
    // managed by this object.
    ~String() noexcept;
};

Selain fungsi String(const char* chars);, saya mengimplementasikan semuanya dengan benar, tetapi saya tidak memiliki petunjuk tentang cara mengimplementasikan yang ini.

Diedit: Sejak perpustakaan standar C ++ tidak dapat digunakan, saya harus menghitung ukuran chars dengan tidak menggunakan strlen()

String::String(){
    size = 0;
    buffer = nullptr;
}

String::String(const char* chars){
    int i = 0;
    for (char* p = chars;*p != '\0'; p++){
        ++i;
    }
    size = i;

    buffer = new char[size+1];
    i = 0;
    for(;i<size;i++){
        buffer[i] = chars[i];
    }

    buffer[i] = '\0';
}

String::String(const String& s){
    size = s.size;
    buffer = new char[size];
    for int(i=0;i<size;i++){
        buffer[i] = s.buffer[i];
    }
}

String::~String() noexcept{
    delete[] buffer;
}
c++
-3
Alex 5 April 2021, 14:50

2 jawaban

Jawaban Terbaik

Ada beberapa perbedaan dalam berapa banyak memori yang Anda alokasikan yang akan kembali dan menggigit Anda.

  • Konstruktor default Anda tidak mengalokasikan apa pun.
  • Konstruktor konversi Anda mengalokasikan size + 1 char s.
  • Copy CoporStor Anda mengalokasikan size char s.
  • Anda juga perlu menambahkan pemindahan konstruktor dan menyalin + memindahkan operator penugasan.

Saya sarankan Anda mengalokasikan size + 1 di mana-mana untuk meninggalkan ruang untuk terminator nol. Ini juga akan membuatnya sangat mudah untuk mengimplementasikan fungsi toChars() yang disebutkan dalam Contoh Komentar:

char* String::toChars() { return buffer; }

Karena Anda tidak diizinkan menggunakan salah satu fungsi pustaka standar, seperti std::strlen() atau std::memcpy(), dan karena Anda mungkin perlu fungsi seperti itu lebih dari sekali, Anda dapat menulis fungsi yang sama saja menempatkan kode itu di dalam fungsi kelas Anda di beberapa tempat. Tentukan mereka sekali dan gunakan berkali-kali.

// a function to get the length of a null terminated C string
unsigned len(const char* chars) {
    unsigned result = 0;
    for(;*chars != '\0'; ++chars, ++result) {}
    return result;
}

// A function to copy a certain amount of chars
void cpy(const char* from, char* to, unsigned len) {
    for(; len; --len, ++from, ++to) {
        *to = *from;
    }
}

Dengan itu, konstruktor Anda akan sangat sederhana. Saya sengaja tidak menggunakan anggota initializer-daftar di sini - tapi tolong lakukan Periksa mereka.

String::String() {                   // default ctor
    size = 0;
    buffer = new char[size + 1]{};   // {} makes it zero initialized
    // buffer[0] = '\0';             // or you could do this instead
}

String::String(const char* chars) {  // converting ctor
    size = len(chars);               // use the len() function
    buffer = new char[size + 1];
    cpy(chars, buffer, size + 1);    // and use the cpy() function
}

String::String(const String& s) {    // copy ctor
    size = s.size;
    buffer = new char[size + 1];
    cpy(s.buffer, buffer, size + 1); // use the cpy() function again
}
0
Ted Lyngmo 5 April 2021, 13:45

Anda harus menggunakan std::vector<char> untuk buffer Anda sehingga Anda < a href = "https://github.com/isocpp/cppcoreguidelines/blob/master/cpcoreguidelines.md#rr-newelete" rel = "nofollow noreferrer"> jangan secara eksplisit menelepon {{x1} dan {{{x2} } . std::vector adalah bagian dari C ++ (dan sudah lama), jadi ini tentu saja "mengimplementasikan [ing] kelas string di C ++ ..." (dan tidak menggunakan std::string).

class String final
{
    std::vector<char> buffer;

public:
    String() = default;
    String(const char* chars){
       auto begin = chars;
       auto end = begin + strlen(chars);
       buffer.insert(buffer.begin(), begin, end);
   }
   String(const String& s){
      buffer = s.buffer;
   }
   ~String() = default;
};

Perhatikan seberapa sederhana berbagai konstruktor sekarang. Ini memiliki keuntungan tambahan untuk menghindari kebocoran memori dan menjadi pengecualian aman; dan tanpa Anda harus bahkan (hampir tidak) berpikir tentang kekhawatiran itu.

Jika Anda benar-benar ingin menghindari menggunakan std::vector (mengapa? Ini sempurna untuk kasus ini), maka paling tidak Anda harus menggunakan std::unique_ptr<char[]> (atau mungkin std::shared_ptr<char[]>) yang ditambahkan ke C ++ 11.

class String final
{
    std::unique_ptr<char[]> buffer;
public:
    String() = default;
    ~String() = default;
    String(const String&) = delete;
    String& operator=(const String&) = delete;
    String(const char* chars) {
       const auto len = strlen(chars);
       buffer = std::make_unique<char[]>(len + 1);
       strcpy(buffer.get(), chars);
    }
};

Edit Anda yang terbaru tidak masuk akal. Seperti yang dapat dilihat dari strlen() bahkan yang tampaknya " Fungsi yang mudah "bisa sulit untuk mendapatkan yang benar; Itu sebabnya kami memiliki perpustakaan standar. Dan jika Anda tidak dapat menggunakan apa pun pustaka standar, maka bahkan tidak ada cara untuk secara dinamis mengalokasikan memori karena yang dilakukan dengan malloc().

2
Ðаn 5 April 2021, 13:26