Adding a new field to a struct in C

Mọi người cho mình hỏi, mình muốn thực hiện việc thêm 1 trường mới vào cấu trúc theo ý người dùng thì mình dùng cách gì, mọi người có tài liệu tham khảo càng tốt ạ :<
Mình cần code bằng C một chương trình khi chạy lên sẽ có các chức năng, khi chọn chức năng add field, người dùng sẽ nhận được thông báo yêu cầu nhập tên field mới, kiểu dữ liệu của nó rồi tiến hành nhập dữ liệu vào. Ví dụ struct này:

struct contact
{
    char name[25];
    char company[10];
    int phone;
    char email[25];
};

Oh, câu hỏi thú vị đấy. Để giải quyết câu hỏi này, cậu cần:

  • Một trình soạn thảo. Tớ recommend notepad, đó là 1 trình soạn thảo vô cùng phức tạp, nhưng tốc độ nhanh vô đối và được sử dụng rộng rãi.
  • Kiến thức sử dụng trình soạn thảo để edit file.

Để edit file, cậu cần thực hiện rất nhiều bước. May mắn thay, NASA đã có một bài viết chi tiết hướng dẫn cách sử dụng notepad để edit file. Cậu nên tham khảo nó, vì đó là tài liệu của tổ chức lớn, nên yên tâm về độ chính xác.
Trong TH của cậu, sau khi cậu mở file xong, cậu đưa con trỏ vào vị trí struct, ấn enter và thêm field mà người dùng muốn. Tớ hiểu lần đầu làm sẽ hơi khó, nên nhớ làm lần lượt các bước nhé! Sau khi làm vài lần, nó sẽ trở thành kỹ năng của cậu thôi.

Hope it helps!

4 Likes

“Theo ý người dùng”?
Ý bạn là người dùng đoạn mã (được chia sẻ) của bạn hay người dùng chương trình do bạn viết ra.
Nếu ý 1: @library đã hướng dẫn.
Nếu ý 2:
Trong C++ có template std::pairstd::vector sẽ tiện lợi cho mục đích của bạn.
Nhưng trong C lại không có, bạn vẫn có thể thay thế bằng cấu trúc tương đương.

struct Dat{
    char* name;
    void* data;
    char* dataType;
    int dataSize;
}
5 Likes

Tks, để mình đọc tài liệu này xem sao

1 Like

Đúng ý 2 đó, nhưng bạn có thể viết rõ hơn được không, để người dùng chương trình tự nhập tên field, kiểu dữ liệu rồi mới thêm dữ liệu vào struct thì tiếp theo mình làm như thế nào thế. Có thể cho mình giải pháp và mình tự search cũng được, tks

Oh, cậu nên đề cập vấn đề rõ hơn lần sau nha :smile: Tớ đầu óc đơn giản nên sẽ chỉ hiểu nghĩa đen thôi :crazy_face:

Về vấn đề thực sự của cậu, @SITUVN.gcd có đề cập rồi:

Về cơ bản C không có cách thay đổi struct in runtime đâu. Cách trên SITU chỉ là sử dụng con trỏ void để khai báo 1 data kiểu gì cũng được. Trong runtime, cậu có thể gán bất cứ thứ gì vào con trỏ này.
Cơ mà, tại sao cậu lại muốn thay đổi struct in runtime vậy? Biết đâu có solution khác cho vấn đề đó thì sao?

2 Likes

Hình như bạn hiểu sai ý mình. Mình cần code bằng C một chương trình khi chạy lên sẽ có các chức năng, khi chọn chức năng add field, người dùng sẽ nhận được thông báo yêu cầu nhập tên field mới, kiểu dữ liệu của nó rồi tiến hành nhập dữ liệu vào.

1 Like

Oh, tớ không hiểu sai ý cậu, là cậu diễn đạt sai ý cậu đấy chứ? :smile:
Cậu nên diễn đạt thế này:

Mọi người cho mình hỏi, mình muốn thực hiện việc thêm 1 trường mới vào cấu trúc theo ý người dùng in runtime thì mình dùng cách gì? Mọi người có tài liệu tham khảo càng tốt ạ :<

Thêm bối cảnh cậu muốn thực hiện kỹ thuật là điều tốt để mọi người hiểu. Cậu không thể bắt mọi người đoán bối cảnh là runtime, phải không? :smile:

Hoặc như cách cậu giải thích cũng tốt:

Mình cần code bằng C một chương trình khi chạy lên sẽ có các chức năng, khi chọn chức năng add field, người dùng sẽ nhận được thông báo yêu cầu nhập tên field mới, kiểu dữ liệu của nó rồi tiến hành nhập dữ liệu vào.

Nếu không, mọi người sẽ hiểu cậu muốn edit file và add field mới :smile:
Cậu nên tránh việc để mọi người phải hiểu ý cậu, vì nó có thể gây hại cho cậu khi cậu đi làm sau này. Nhớ để ý cách diễn đạt nha! :smile:

5 Likes

Tks, mình đã sửa topic và sẽ cải thiện ở các topic sau

1 Like

Ví dụ: struct contact

{
    char name[25];
    char company[10];
    int phone;
    char email[25];
};

Có các data là:

{ name1, company1, 123456, email1 }
{ name2, company2, 321456, email2 }
{ name3, company3, 234567, email3 }
{ name4, company4, 654321, email4 }

Khi chạy chương trình, người dùng chọn add field và thêm vào name2 một field mới là address, kiểu dữ liệu char, và nhập vào address2, còn name 3 sẽ thêm một field Note, kiểu char và nhập dữ liệu là Note3 thì data sẽ thay đổi:

{ name1, company1, 123456, email1, address2 }
{ name2, company2, 321456, email2 }
{ name3, company3, 234567, email3, Note3 }
{ name4, company4, 654321, email4 }

Mình nghĩ giải pháp là thay đổi struct runtime nhưng không biết làm như nào :<

Xài cấu trúc hash-map nha
Bạn sẽ có 2 hash map trong 1 map bự

Map Record {
  [Username]: {
    String RecordName;
    Map Type; // name: string; age:int (string:string)
    Map Data; // name:Chít; age:10 (string:void*)
  }
}
4 Likes

lấy source code Python (viết bằng C) compile ra rồi dùng là được :triumph:

2 Likes

Cách này hợp lý nè, thêm linklist với header để quản lý nữa.

4 Likes

Dùng linkerlist nhé.
Struct C không thay đổi được khi runtime đâu.

2 Likes

Bạn nói rõ ý tưởng được không, mình vẫn chưa hình dung được dùng linklist như nào :<

Còn hashmap thì chưa biết tí gì nên đang đọc về nó và cũng chưa có hình dung được hướng đi ==’

Bạn không define 1 dạng struct cố định, mà dùng 1 general struct giống như ở trên. Struct đó bao gồm tên, loại struct, kích thước struct và con trỏ trỏ tới dữ liệu cần ghi. Khi bạn có dữ liệu mới thì có thể malloc 1 vùng nhớ có kích thước được quy định trong dataSize.
Cụ thể ở đây { name1, company1, 123456, email1, address2 } thì name1 sẽ là 1 struct có dạng như sau:

struct Dat{ 
      char* name;
      void* data; 
      char* dataType; 
      int dataSize; 
}

Node 1 sẽ là 1 danh sách liên kết các Dat.
Ngoài ra còn có thể dùng mảng hoặc danh sách liên kết lỡn hơn để lưu trữ các Node.

NodeHead
|
Node1 -> Dat1.1 -> Dat1.2 -> Dat1.3
|
Node2 -> Dat2.1 -> Dat2.1
3 Likes

Vậy thì code cái tree cho đơn giản :slight_smile: hash thì phải dùng 2, 3 cấu trúc đấy và có quá nhiều lựa chọn.
String dài thì code cái vector :smiley: cỡ này là 1 project nhỏ.

3 Likes

Mình hiểu được ý tưởng rồi. Nhưng vấn đề cấp phát bộ nhớ khi người dùng thêm 1 field thì chương trình làm sao để nhận biết kiểu dữ liệu để cấp phát bộ nhớ và dùng đúng kiểu dữ liệu khi người dùng nhập dữ liệu vào nhỉ. Mình biết chưa nhiều, thông cảm vì hỏi nhiều

Mình để kiểu dữ liệu là char* có lẽ hơi “lố”, nên để là char hoặc int. Vì các kiểu dữ liệu lưu trữ chỉ gọn trong: số, và chuỗi, các kiểu dữ liệu tương ứng được liệt kê là: int, long, float, double, char*. Số lượng không nhiều.

struct Dat{ 
      char* name;
      void* data; 
      char dataType; // <-- hoặc int cũng được
      //int dataSize; // Nếu data có thể ở dạng cấu trúc (struct) khác hoặc dạng chuỗi không có kí tự NUL ở cuối.
}

Sau đó chỉ cần có quy định cho các giá trị tương ứng thôi. Quy định do bạn tự đề ra.
Vd:

1: int
2: long
3: float
4: double
5: char*
Dat d = ...; // lấy dữ liệu
if(d.dataType == 1){ // dữ liệu kiểu int
    int* iVal = (int*)d.data;
}else if(d.dataType == 3){ // float
    float* fVal = (float*)d.data;
}else if(d.dataType == 5){ // chuỗi
    char* sVal = (char*)d.data;
}
...

Từ đây mà bạn có thể biến tấu sao cho phù hợp và hiệu quả hơn cho mục đích của bạn.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?