【问题标题】:How to save a splitted string in character array contained in structure in C?如何将拆分的字符串保存在C结构中包含的字符数组中?
【发布时间】:2021-04-18 08:40:29
【问题描述】:

正如标题中所说,我想将文本的每一部分保存在我的结构中包含的字符数组中,称为Identity,代码如下:

#include <stdio.h>
#include <string.h>

char strExample[]="Andrew;Smith;18;Wall Street;New York;10011;USA";

typedef struct  Identity{
    char firstName[20];
    char lastName[20];
    char age[5];
    char street[64];
    char city[20];
    char postCode[8];
    char country[20];
}Identity;

void textParse()
{
  char *ptr = strExample; 
  char *token;
  int i = 0;
  while ((token= strsep(&ptr,";")) != NULL)
  {
    printf("%s\n",token);
  }
}

int main(int argc, char **argv) {

    textParse();

    return 0;
}

拆分效果很好,但我不知道如何将每个标记保存在 Identity 结构中。我该怎么做?

【问题讨论】:

  • 请更改措辞:您没有在 typedef 中保存字符串;您将它们保存在结构中包含的字符数组中。 typedef 只是用来命名孩子。你也不能在 type 中存储任何东西;您可以将内容存储在变量中。
  • 进行长度检查以验证每个标记是否适合每个目标字符数组,然后将其存储在那里。
  • 是的,我正在考虑做类似的事情,但是你如何用循环来做呢?

标签: c parsing struct typedef


【解决方案1】:

只需定义一个Identity类型的变量,然后使用strncpy()将每个token复制到struct的相关字段中:

#include <stdio.h>
#include <string.h>

#define STRNCPY_STRUCT_EL(string_field, src) strncpy(string_field, src, sizeof(string_field) - 1 )

char strExample[]="Andrew;Smith;18;Wall Street;New York;10011;USA";

typedef struct  Identity{
    char firstName[20];
    char lastName[20];
    char age[5];
    char street[64];
    char city[20];
    char postCode[8];
    char country[20];
}Identity;

void textParse(Identity *id)
{
  char *ptr = strExample; 
  char *token;
  int i = 0;

  memset(id, 0, sizeof(*id));
  while ((token = strsep(&ptr,";")) != NULL)
  //while ((token = strtok(ptr,";")) != NULL) //I used this in my test
  {
    // ptr = NULL; //I used this in my test, to fit strtok
    switch(i++)
    {
        case 0:
            STRNCPY_STRUCT_EL(id->firstName, token);
            break;
        case 1:
            STRNCPY_STRUCT_EL(id->lastName, token);
            break;
        case 2:
            STRNCPY_STRUCT_EL(id->age, token);
            break;
        case 3:
            STRNCPY_STRUCT_EL(id->street, token);
            break;
        case 4:
            STRNCPY_STRUCT_EL(id->city, token);
            break;
        case 5:
            STRNCPY_STRUCT_EL(id->postCode, token);
            break;
        case 6:
            STRNCPY_STRUCT_EL(id->country, token);
            break;
    }    
  }
}

int main(int argc, char **argv) {
    Identity id;

    textParse(&id);

    printf("Identity:\n%s %s, %s y.o.\nLives in %s, %s (%s - %s)\n",
           id.firstName, id.lastName, id.age, id.street, id.city, id.postCode, id.country);

    return 0;
}
  • 基本上我检查了令牌的位置,然后将其复制到结构的相应位置。我使用了switch-case。不是很优雅,但很有效
  • 我使用自动计算字段大小的宏复制了它。我想复制 size-1 字符,因为我想为字符串终止符 '\0' 留出空间
  • 之所以有效,是因为我之前memseted 整个结构为 0,所以在strncpy 之后,字符串终止符肯定在哪里
  • 我必须更改textParse() 签名才能接受指向Identity 的指针。在里面我跳过了健全性检查(例如对 NULL 指针的检查)。我建议将它们添加到您的最终实现中
  • 此实现会截断比相应 Identity 字段更长的任何标记

输出:

Identity:
Andrew Smith, 18 y.o.
Lives in Wall Street, New York (10011 - USA)

【讨论】:

    【解决方案2】:

    如果你想循环处理它,你需要事先将成员数组的信息——它们的大小和偏移量——累积在一个数组中(数组最方便):

    例子:

    #include <stdio.h>
    #include <string.h>
    #include <stddef.h>
    
    char strExample[]="Andrew;Smith;18;Wall Street;New York;10011;USA";
    
    typedef struct  Identity{
        char firstName[20];
        char lastName[20];
        char age[5];
        char street[64];
        char city[20];
        char postCode[8];
        char country[20];
    }Identity;
    
    void textParse(Identity *Id)
    {
      static size_t const sizes[7]={
          sizeof((Identity){0}.firstName),
          sizeof((Identity){0}.lastName),
          sizeof((Identity){0}.age),
          sizeof((Identity){0}.street),
          sizeof((Identity){0}.city),
          sizeof((Identity){0}.postCode),
          sizeof((Identity){0}.country),
      };
      static size_t const array_offsets[7]={
          offsetof(Identity,firstName),
          offsetof(Identity,lastName),
          offsetof(Identity,age),
          offsetof(Identity,street),
          offsetof(Identity,city),
          offsetof(Identity,postCode),
          offsetof(Identity,country),
      };
    
      char *ptr = strExample;
      char *token;
      for (int i=0; (token= strsep(&ptr,";")) != NULL; i++)
      {
          size_t const size = (size_t)(ptr-token);
          if(size > sizes[i]) return; /*doesn't fit*/
          else memcpy((char*)Id+array_offsets[i], token, size);
      }
    }
    
    int main(int argc, char **argv) {
    
        Identity id; textParse(&id);
        puts("=============");
        puts(id.firstName);
        puts(id.lastName);
        puts(id.age);
        puts(id.street);
        puts(id.city);
        puts(id.postCode);
        puts(id.country);
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-05
      • 2021-11-30
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      相关资源
      最近更新 更多