因爲枚舉常量是整數的名稱,而不是結構成員的名稱,所以不能直接像顯示的那樣去做。您不能使用任何類型的變量直接編寫對結構成員的引用來標識成員名稱 - 您必須明確指定成員(因此它是結構中的硬連接偏移量)。然而,假設你的編譯器對匿名聯合和結構成員有C11支持,並且假設你可以重新定義結構類型(它不是完全固定和不可移動的,而是由某種外部力量預先規定的,例如導師或標準),你可以選擇你想要像這樣的代碼是什麼讓相當接近:
#include <stdio.h>
#include <stdbool.h>
typedef struct user
{
bool empty;
int lineNumber;
char *errMessage;
union
{
struct
{
char *username;
char *password;
char *uid;
char *gid;
char *gecos;
char *dir;
char *shell;
};
char *field[7];
};
} user;
typedef enum {username, password, uid, gid, gecos, dir, shell} userValue;
static void parseHelper(user *u, userValue enumParam, char *value)
{
u->field[enumParam] = value;
}
int main(void)
{
user u;
u.empty = false;
u.lineNumber = 1;
u.errMessage = "no error";
parseHelper(&u, password, "secret");
parseHelper(&u, username, "me");
parseHelper(&u, uid, "0");
parseHelper(&u, gid, "1");
parseHelper(&u, gecos, "Yours Truly");
parseHelper(&u, dir, "/home/me");
parseHelper(&u, shell, "/bin/sea");
printf("%s:%s:%s:%s:%s:%s:%s\n", u.username,
u.password, u.uid, u.gid, u.gecos, u.dir, u.shell);
return 0;
}
運行時,它產生的輸出:
me:secret:0:1:Yours Truly:/home/me:/bin/sea
有幾個因素使這個工作。
- 結構成員名稱位於單獨的名稱空間中,因此枚舉元素名稱不會影響結構成員名稱。
- 您嘗試處理的所有字段都是相同類型(
char *
)。
- 在結構中有匿名聯合時,可以按名稱訪問聯合的元素。
- 在聯合中有一個匿名結構時,可以按名稱訪問結構中的元素。
如果你堅持C90或C99,則可以達到類似的效果,但它是更冗長:
#include <stdio.h>
#include <stdbool.h>
typedef struct user
{
bool empty;
int lineNumber;
char *errMessage;
union
{
struct
{
char *username;
char *password;
char *uid;
char *gid;
char *gecos;
char *dir;
char *shell;
} f;
char *field[7];
} u;
} user;
typedef enum {username, password, uid, gid, gecos, dir, shell} userValue;
static void parseHelper(user *u, userValue enumParam, char *value)
{
u->u.field[enumParam] = value;
}
int main(void)
{
user u;
u.empty = false;
u.lineNumber = 1;
u.errMessage = "no error";
parseHelper(&u, password, "secret");
parseHelper(&u, username, "me");
parseHelper(&u, uid, "0");
parseHelper(&u, gid, "1");
parseHelper(&u, gecos, "Yours Truly");
parseHelper(&u, dir, "/home/me");
parseHelper(&u, shell, "/bin/sea");
printf("%s:%s:%s:%s:%s:%s:%s\n", u.u.f.username, u.u.f.password,
u.u.f.uid, u.u.f.gid, u.u.f.gecos, u.u.f.dir, u.u.f.shell);
return 0;
}
這將產生相同的輸出,當然。
你可以使用開關st爲每個枚舉值做一些不同的事情。這個功能可能很長很醜,但它可能會讓你需要稱之爲更清潔的地方。這不像你在寫完它後總要看看它。 –
奶牛42,檢查我的答案,以防萬一。 – pablo1977