【问题标题】:How can Store MultiData Value in a Struct and work with Them?如何将 MultiData 值存储在结构中并使用它们?
【发布时间】:2017-09-15 13:57:29
【问题描述】:

我当前的代码:

#include <stdio.h>
#include <string.h>
/*
    struct Value {
       int typ;
       unsigned char vstring;
       int   vint;
       float  vfloat;
    };
*/
struct Value {
   int typ;
   /*
   type=1  ==> get vstring
   type=2  ==> get int
   type=3  ==> get float
   */
   union{
      struct{
         unsigned char *vstring;
      };
      struct{
         int   vint;
      };
      struct{
         float  vfloat;
      };
   }
};

void clear(Value vall){
   if(vall.typ == 1){
      delete(vall.vstring);
   }else if(vall.typ == 2){
      delete(vall.vint);
   }else{
      delete(vall.vfloat);
   }
}
int main()
{
   struct Value v;
   /////////////////////////////////////////////
   v.typ=1;
   strcpy( v.vstring,"C Programming/may this a very big utf-8 string!");
   /*
   strcpy( v.vint,4); 
   strcpy( v.vfloat,4.5);
   */
   /////////////////////////////////////////////
   printf( "ValueType : %d\n", v.typ);
   printf( "ValueString : %s\n", v.vstring);
   printf( "ValueInt : %d\n", v.vint);
   printf( "ValueFloat : %f\n", v.vfloat);
   return 0;
   Value copy=v;
   clear(copy);
   copy.typ=2;
   copy.vint=5;
}

但这有错误,我不知道如何解决这个问题。

这有一个Value 结构。在这个有 (vstring,vint,vfloat) 和typ 中的值存储类型以加快速度。

请帮我修复此代码。

我希望将此结构存储在数组/映射/哈希映射中...... 坦克你。

【问题讨论】:

  • unsigned char vstring 应该是unsigned char *vstring,你需要先分配内存来复制字符串。
  • 如果一次只能是一种类型,您可以使用union
  • 改了,但也再次出现错误。
  • 什么是delete()???以及如何“删除” int 或 float?
  • delete() 表示清除并从内存中删除,我认为可以使用memset(&lt;variable_name&gt;, 0, MEMORY_BLOCK); 是吗?或#define CLEAR(x) memset(x,'\0',1000); CLEAR(&lt;variable_name&gt;);?

标签: c struct


【解决方案1】:

您的代码的正确版本(但请注意 cmets!)是:

struct Value {
   int typ;
   /*
   type=1  ==> get vstring
   type=2  ==> get int
   type=3  ==> get float
   */
   union{
     unsigned char *vstring;
     int   vint;
     float  vfloat;
   } u;
};

void clear(struct Value *vall){
   if(vall->typ == 1){
      {free(vall->u.vstring); vall->u.vstring= 0;}
   }else if(vall->typ == 2){
      vall->u.vint=0;
   }else{
      vall->u.vfloat=0.0;
   }
}
int main()
{
   struct Value v;
   /////////////////////////////////////////////
   v.typ=1;
   v.u.vstring= malloc(strlen("C Programming/may this a very big utf-8 string!")+1);
   strcpy( v.u.vstring,"C Programming/may this a very big utf-8 string!");
   /////////////////////////////////////////////
   printf( "ValueType : %d\n", v.typ);
   printf( "ValueString : %s\n", v.u.vstring);
   printf( "ValueInt : %d\n", v.u.vint);        // <== there is no int in u
   printf( "ValueFloat : %f\n", v.u.vfloat);    // <== there is no float in u
   return 0;
   struct Value copy=v; // <== you cannot do this as you now use the memory of the vstring
   clear(&copy);    // <== this now releases the memory of vstring in both 'copy' and 'v'
   copy.typ=2;
   copy.u.vint=5;
}

【讨论】:

  • 坦克你,但在 gcc 中也有错误。 paste.ubuntu.com/24413365
  • #include &lt;stdlib.h&gt; 并在Value 之前添加关键字struct(它是struct Value)。我会用后者更新解决方案。
【解决方案2】:

首先,您可以考虑使用union。这不是必需的,但会节省一些字节:

struct Value {
   int typ;
   /*
   type=1  ==> get vstring
   type=2  ==> get int
   type=3  ==> get float
   */
   union {
    unsigned char *vstring;  // Changed to char pointer!!
    int   vint;
    float  vfloat;
   };
};

接下来,复制字符串时,需要分配空间:

const char *msg = "C Programming/may this a very big utf-8 string!";
struct Value v;
v.typ = 1;
v.vstring = malloc(strlen(msg) + 1);
strcpy(v.vstring, msg);
// strdup() does the same thing

当你清除时,你需要free那个内存:

void clear(struct Value* vall){
   if (vall->typ == 1) {
      free(vall->vstring);
   }
   memset(vall, 0, sizeof(*vall));
}

最后,您可以使用枚举作为类型,而不是“幻数”:

enum VTYPE {VSTRING, VINT, VFLOAT};
typedef enum VTYPE vtype;

另外,这里有一个打印辅助函数:

void print_value(struct Value *v)
{
    static const char *types[] = {"VSTRING", "VINT", "VFLOAT"};
    printf( "ValueType : %s\n", v->typ >= 0 && v->typ < 3 ? types[v->typ] : "ERROR");
    if (VSTRING == v->typ) {
        printf( "ValueString : %s\n", v->vstring);
    }
    else if (VINT == v->typ) {
        printf( "ValueInt : %d\n", v->vint);
    }
    else if (VFLOAT == v->typ) {
        printf( "ValueFloat : %f\n", v->vfloat);
    }
}

这是整个内容的链接:http://ideone.com/ecy3qa

复制时,一定要复制字符串:

void copy_value(struct Value *source, struct Value *dest) {
    if (VSTRING == source->typ) {
        dest->vstring = malloc(strlen(source->vstring) + 1);
        strcpy(dest->vstring, source->vstring);
    }
    else if (VINT == source->typ) {
        dest->vint = source->vint;
    }
    else if (VFLOAT == source->typ) {
        dest->vfloat = source->vfloat;
    }
    dest->typ = source->typ;
}

【讨论】:

  • 完美,坦克你。 :喜欢:
  • 坦克你@johnny-mopp ,也可以添加v 的副本? paste.ubuntu.com/24413409,清除v后,也复制删除!这太糟糕了。
  • 复制时要小心。如果类型是VSTRING,则需要复制该字符串。使用复制功能更新答案。
  • 我在paste.ubuntu.com/24413473 中制作了struct Value coppy(),请检查一下。
  • 您没有在此处复制字符串:v_r.vstring=v-&gt;vstring; 这样您将有 2 个不同的对象指向同一个字符串。所以当你clear(&amp;v),copy会有一个无效的指针。
猜你喜欢
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 2020-01-30
  • 2013-07-22
  • 2021-05-27
相关资源
最近更新 更多