Meningkatkan ukuran array secara dinamis di Struct C

Pertanyaan saya sederhana...Saya telah mendeklarasikan struct berikut:

struct Address {
   int id;
   int set;
   char *name;
   char *email;
};

struct Database {
   struct Address rows[512];
};

struct Connection {
   FILE *file;
   struct Database *db;
};

Sekarang setelah jelas, saya menginisialisasi "Database" saya di dalam "Koneksi" saya dengan beberapa Alamat tiruan. Saya kemudian mengambil database ini dan menyimpannya ke dalam file di dalam struct "Koneksi" saya dengan:

void Database_write(struct Connection *conn){
   rewind(conn->file);

   int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
      if(rc != 1){
         die("Failed to write database.\n",conn);
      }

   rc = fflush(conn->file);
      if(rc == -1){
         die("Cannot flush database.\n",conn);
      }

Semuanya berfungsi dengan baik ketika saya memiliki jumlah baris yang telah ditentukan di dalam struct "Database" untuk Alamat saya, yaitu 512. Namun, bagaimana jika saya ingin membuat jumlah baris secara dinamis? Seperti mungkin param diteruskan ke suatu fungsi? Saya sudah mencoba menggunakan yang berikut ini...

struct Database {
   struct Address *rows;
};

Dan mengalokasikan ruang ke penunjuk ini dengan:

conn->db->rows = (struct Address*) malloc(sizeof(struct Address)*max_rows);

Dengan max_rows menjadi param yang diteruskan ke suatu fungsi...Tapi, sekarang masalahnya adalah ketika saya pergi dan mencoba menyimpan ini ke file di dalam struct "Koneksi" saya, saya hanya menyimpan penunjuk "struct Address *rows;" dan bukan data dengan ruang yang dialokasikan untuk itu. Adakah saran tentang cara menghemat ruang yang dialokasikan ini atau memiliki array yang telah ditentukan di dalam suatu struct dan kemudian mengembangkannya secara dinamis?

Terima kasih sebelumnya!


person Sebastian Serrano    schedule 09.05.2017    source sumber
comment
Seperti apa kode tulis Anda yang baru diperbarui dan tidak berfungsi?   -  person Chris Turner    schedule 09.05.2017
comment
Anda harus menyimpan penunjuknya? Apakah Anda baru saja membuang struktur ke file sebagai byte? Itu ide yang buruk. File itu hanya akan dibaca dengan benar di sebagian mesin. Yang Anda butuhkan adalah menulis representasi logis dari data ke file, bukan hanya membuang byte seperti yang ada di memori proses Anda.   -  person StoryTeller - Unslander Monica    schedule 09.05.2017
comment
Anda harus menulis beberapa serialisasi rutin yang mem-parsing struct.   -  person Lundin    schedule 09.05.2017
comment
Apakah Anda PERLU mentransmisikan malloc() ke struct Address *? atau Anda melakukannya karena Anda melihatnya di tempat lain? Saya menanyakan hal ini karena akan jauh berbeda jika Anda HARUS melakukan cast, bahasanya akan sangat berbeda. Selain itu, conn->db->rows mungkin mereferensikan penunjuk NULL jika Anda tidak berhati-hati. Dan apa itu die()?, itu membuat kodenya terlihat seperti PHP, dan itu PHP jadi, itu PHP.   -  person Iharob Al Asimi    schedule 09.05.2017
comment
Semua struct saya sama dengan pengecualian untuk Database saya yang saya ubah ke yang saya sebutkan menggunakan pointer struct Address *rows dan coba simpan ini dengan void Database_write yang sama dan ketika saya mencoba membuka file tentu saja data saya ditunjuk oleh penunjuk *baris saya tidak ada :/ dan fungsi die() saya hanyalah rutinitas umum untuk membersihkan memori yang dialokasikan   -  person Sebastian Serrano    schedule 09.05.2017
comment
Bagaimana cara kerjanya sebelumnya ketika name dan email juga merupakan pointer? Anda hanya perlu menulis teks ke file, atau melakukan apa yang komentar ini disarankan.   -  person Iharob Al Asimi    schedule 09.05.2017
comment
Kedengarannya itu ide yang bagus, tapi masalahnya adalah saya tidak tahu bagaimana cara melakukannya :/   -  person Sebastian Serrano    schedule 09.05.2017
comment
@IharobAlAsimi Kode memerlukan pemeran sebanyak/sedikit karena komentar tentang casting diperlukan di sini.   -  person chux - Reinstate Monica    schedule 09.05.2017


Jawaban (1)


Anda berada di jalur yang benar dengan malloc untuk membuat sejumlah Alamat dinamis.

conn->db->rows = (struct Address*) malloc(sizeof(struct Address)*max_rows);

Namun kemudian Anda mengalami masalah dalam menuliskannya ke file di Database_write. Hal ini karena struktur yang dialokasikan secara dinamis tidak lagi memiliki jumlah baris yang tertanam di dalamnya. Anda harus mengubah Database_write menjadi

  1. Masukkan berapa baris yang akan ditulis.
  2. Sesuaikan baris fwrite Anda untuk menuliskan semua baris.

Anda memiliki:

void Database_write(struct Connection *conn)
{
    rewind(conn->file);

    int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
    if(rc != 1){
        die("Failed to write database.\n",conn);
    }
...

Anda sekarang membutuhkan sesuatu seperti:

void Database_write(struct Connection *conn, int num_rows)
{
    rewind(conn->file);

    int rc = fwrite(conn->db, sizeof(struct Database), num_rows, conn->file);
    if(rc != num_rows)
    {
        die("Failed to write database.\n",conn);
    }

...

Anda juga bisa menambahkan jumlah baris ke struct database Anda untuk mencatat berapa banyak baris yang seharusnya ada dalam file:

struct Database 
{
    int num_rows;
    struct Address *rows;
};

Dalam hal ini Anda harus menulis jumlah baris yang akan diarsipkan terlebih dahulu, lalu menulis jumlah_baris dari Alamat Struktur.

Anda mungkin juga ingin mencari realloc untuk mengubah jumlah baris dengan cepat. Petunjuk - gunakan dengan hati-hati, dan perhatikan baik-baik nilai pengembaliannya.

person Gavin Shreeves    schedule 09.05.2017