[英]How do I iterate over a struct array to check if string input is equal to a struct array value
[英]How do I make a variable in a struct equal to any value without a warning? (C)
所以我有一個簡單的結構,看起來像
struct var {
char* name;
int value;
}
而且我不知道如何避免warning: assignment makes integer from [non-int] without a cast [-Wint-conversion]
,我會做很多事情。 我知道我不應該擔心警告,但我真的想擺脫它,那么解決這個問題的最佳方法是什么? 我想做的例子:
int main() {
struct var a[100];
a[0].name = "a";
a[0].value = "c";
a[1].name = "b";
a[1].value = 0;
}
根據您使用的命名約定,我假設struct var
旨在存儲鍵值對,其中值可以是任何類型。 不幸的是, C 是靜態類型的 - 如果您將value
聲明為int
,它只能存儲int
值。 如果您為其分配一個浮點值,該值將轉換為 integer 並且您將丟失小數部分。 您不能使用它來存儲字符串或任何其他聚合類型。
你基本上有兩個選擇。 您可以將value
設為不同類型的聯合:
enum var_type { INTEGER, FLOATING, STRING };
struct var
{
char *name;
enum var_type type;
union {
int i;
double f;
char *s;
} value;
};
然后您可以將不同的類型存儲到聯合的不同成員:
struct var v[3];
v[0].name = "foo";
v[0].type = INTEGER;
v[0].value.i = 1;
v[1].name = "bar";
v[1].type = FLOATING;
v[1].value.f = 3.14;
v[2].name = "bletch";
v[2].type = STRING;
v[2].value.s = "this is a test";
這種方法雖然不涉及動態 memory 以及隨之而來的所有胃灼熱,但卻是一種痛苦。 你必須確保你想要代表的每種類型都有一個聯合成員,如果發生變化,你必須破解類型並重建。 您必須分配給特定的工會成員。
另一種方法是讓value
成為一個簡單的void *
,然后動態分配 memory 給它。 雖然這引入了 memory 管理難題,但它更靈活且更易於抽象。
struct var {
char *name;
void *value;
};
struct var v[3];
v[0].name = "foo";
v[0].value = copy_int( 1 );
v[1].name = "bar";
v[1].value = copy_float( 3.14 );
v[2].name = "bletch";
v[2].value = copy_string( "this is a test" );
其中每個copy_int
、 copy_float
和copy_string
都是抽象出malloc
調用和分配的函數:
void *copy_int( int arg )
{
int *mem = malloc( sizeof *mem );
if ( mem )
*mem = arg;
return mem;
}
void *copy_float( double arg )
{
double *mem = malloc( sizeof *mem );
if ( mem )
*mem = arg;
return mem;
}
void *copy_string( const char *str )
{
char *mem = malloc( sizeof *mem * (strlen( str ) + 1 ));
if ( mem )
strcpy( mem, str );
return mem;
}
這種方法的美妙之處在於,您不必每次想要存儲不同類型的值時都修改struct var
類型 - 您只需實現一個新的copy_*
function。
然而...
當您以后想要使用它時,您仍然需要一些方法來確定value
的類型。 您可以使用上面的enum
方法對其進行顯式標記,也可以添加 function 指針成員並創建函數以返回有關類型的信息,如下所示:
struct var {
char *name;
void *value;
char *(*type)( void );
};
char *int_type( void ) { return "int"; }
char *double_type( void ) { return "double"; }
char *string_type( void ) { return "string"; }
...
struct var v[3];
v[0].name = "foo";
v[0].type = int_type;
v[0].value = copy_int( 1 );
...
if ( strcmp( v[0].type(), "int" ) )
{
printf( "%s = %d\n", v[0].name, *((int *) v[0].value) );
}
同樣,這種方法的美妙之處在於,當您想要添加新的值類型時,您不必修改您的結構或枚舉 - 您只需實現復制和指示類型的函數。
您想要的是在結構內部使用一個union
,其中包含您想要支持的每種類型的字段:
struct var {
char* name;
char type;
union {
int i;
char c;
char *s;
float f;
double d;
} value;
};
type
字段可用於確定 union 的哪個字段處於活動狀態:
struct var a[100];
a[0].name = "a";
a[0].type = 's';
a[0].value.s = "c";
a[1].name = "b";
a[0].type = 'i';
a[1].value.i = 0;
正如@dbush 所說,工會將解決您眼前的問題。 但是,這就像使用火焰噴射器擦除白板一樣。 它有效,但以后會引起更多問題。
C 有一個類型系統。 它可以幫助您檢查您分配給變量的內容是否與變量的類型相同。 說int = "hello" + 1
真的沒有意義。 您的問題中發生了類似的事情。 int value = "c"
是什么意思?
真正的答案是你不會喜歡的。 您可能不應該為數字分配字母。 這就是警告告訴你的。 我們無法真正回答您應該做什么,因為我們需要更多地了解您的代碼。
使用 ASCII 格式,每個字母都有一個等效的數字。 在更高級的程序中,您可能需要將表示字母的數字分配給具有數字類型的變量。 您通常不想這樣做(所以這是一個警告),但有時您真的想這樣做,並且編譯器知道如果您真的想這樣做(這就是為什么它不是錯誤)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.