2012-05-04 59 views
5

Hãy xem xét ví dụ sau:Làm thế nào để có được thành viên struct với một chuỗi sử dụng Macros C++

struct MyStruct { 
    int a; 
    int b; 
}; 

tôi có thể sử dụng các macro để thiết lập một thành viên từ một thể hiện của các cấu trúc bằng cách làm này:

#define setVar(x,y) instance.x = y 

sau đó trong bất kỳ chức năng nào tôi có thể nói:

setVar(a, 4) 

Làm cách nào để gửi chuỗi dưới dạng macro? Điều đó cũng có thể?

setVar("a", 4) 

CHỈNH SỬA: Có một loạt các cấu trúc được xác định trước với các thành viên thuộc loại gấp đôi. Tôi chỉ biết cấu trúc mà tôi đang sử dụng bởi một tệp cấu hình XML được truyền vào. Sau khi phân tích cú pháp, tôi có một chuỗi các chuỗi là danh sách tất cả các thành viên dữ liệu và các giá trị cần được thiết lập. Tôi cần sử dụng danh sách này để đặt giá trị cho từng thành viên trong cấu trúc.

+7

Tại sao bạn sẽ muốn sử dụng các macro như thế này? – crashmstr

+1

Bạn có muốn lập trình vào thời gian chạy xây dựng tên các trường không? Điều này là không thể. – liori

+0

Không, có một loạt các cấu trúc được xác định trước mà tôi cần truy cập dữ liệu và tôi chỉ có thể truy cập nó bằng cách sử dụng tệp xml với danh sách các biến của nó. Có một cách khác để làm điều này? Ngoài ra, x sẽ luôn có kiểu double – ulu5

Trả lời

6

Nó chỉ có thể nếu bạn xác định các cấu trúc riêng của mình sử dụng một số vĩ mô, ví dụ:

#define MY_STRUCT_STRUCTURE FIELD(a) FIELD(b) FIELD(d) FIELD(e) FIELD(f) 

struct MyStruct { 

# define FIELD(name) int name; 
    MY_STRUCT_STRUCTURE 
# undef FIELD 

    bool setVar(char* fieldname, int val) 
    { 
# define FIELD(name) if(strcmp(#name,fieldname)==0){name=val; return true;}; 
    MY_STRUCT_STRUCTURE 
# undef FIELD 
    return false; // name not found 
    } 
}; 


int main() 
{ 
    MyStruct s; 
    s.setVar("a",1); 
    s.setVar("b",2); 
    s.setVar("f",100); 
} 
+2

Tôi cho rằng công trình, nhưng, kính bảo hộ, chúng không che giấu sự ghê tởm! Aarrrggghhhh. – Skizz

+0

Đủ công bằng. Đó là cơ bản những gì tôi đã nghe, nhưng một vài người nói với tôi tôi có thể làm điều đó với các macro sử dụng stringification và một vài thủ thuật khác. Tôi chỉ không thấy làm thế nào. – ulu5

0

Tôi đã mã hóa một số mã nhanh chóng và dơ bẩn, nhưng có thể cung cấp cho bạn một số ý tưởng, hy vọng rằng sẽ giúp. Bí quyết chính ở đây là quá sử dụng công đoàn.

struct MyStruct 
{ 
int a; 
double b; 

MyStruct() 
    : a(0), b(0) {} 
}; 

MyStruct instance; 

union value 
{ 
    long value_a; 
    double value_d; 
} myvalue; 


void blah_a(value v) 
{ 
    instance.a = v.value_a; 
} 

void blah_b(value v) 
{ 
    instance.b = v.value_d; 
} 

struct 
{ 
    (void)(*fn)(value); 
    const char* key; 
} 

lookup_table[] = 
{ 
    { &blah_a, "a" }, 
    { &blah_b, "b" } 
}; 

void setVar(const char* c, value v) 
{ 
    for (int i = 0; lookup_table[i].fn; i++) 
      if (c == lookup_table[i].key) 
       (*(lookup_table[i].fn))(v); 
} 

int main(int argc, char* argv[]) 
{ 
    value v; 
    v.value_a = 6; 
    setVar("a", v); 
    return 0; 
} 
0

Có thể không là những gì bạn đang tìm kiếm nhưng một giải pháp thay thế cho các macro vv .. chỉ có thể có một số đóng gói và OO thiết kế. Bạn có thể thay đổi lớp Field thành một mẫu sau này và bạn sẽ có thể đại diện cho bất cứ điều gì về cơ bản.

Bạn có thể tạo ra một lớp

class Field 
{ 
public: 
    Field(const std::string& name, const std::string& type); 
    virtual ~Field(void); 
    std::string toString() const; 
    std::string getName() const; 
    int getValue() const { return value }; 
private: 
    std::string name; 
    std::string type; 
    int value; 
}; 

Và sau đó một lớp cấu trúc

#pragma once 
#include <boost/ptr_container/ptr_deque.hpp> 
#include <string> 

class Field; 

class MyStructure 
{ 
public: 
    typedef boost::ptr_deque<Field> FieldList; 
    typedef FieldList::iterator FieldListIter; 
    typedef FieldList::auto_type AutoField; 

    MyStructure(void); 
    MyStructure(const std::string& name); 
    virtual ~MyStructure(void); 

    void setName(const std::string& name); 
    std::string getName() const; 
    void addField(std::auto_ptr<Field> field); 
    std::string getFieldValue(const std::string& name) const; 
    MyStructure::AutoField removeField(const std::string& name); 
    std::string toString(void) const; 

private: 
    std::string struct_name; 
    FieldList fields; 
}; 

Và sau đó sử dụng nó:

auto_ptr<MySructure> struct_a(new MySructure("StructName1",0)); 
struct_a->addField(auto_ptr<Field> (new Field("Field1", 1))); 
struct_a->addField(auto_ptr<Field> (new Field(var_str1, 2))); 
struct_a->addField(auto_ptr<Field> (new Field(getName(), getVal()))); 
Các vấn đề liên quan