在这种情况下如何解决“分段错误”

时间:2019-03-25 22:52:35

标签: c struct typedef strtok

我想制作一个程序,该程序读取带有参与者信息的字符串,在“ /”之间分隔信息,然后使用该信息创建对象。

我做了一个柱子,如网上所示。如果我只想打印它,则可以正常工作,但是当我尝试将其分配给变量时,就会发生错误-分段错误

我的结构如下:

typedef struct {
  char description[40];
  int date;
  int time;
  int duration;
  int room;
  char parent[40];
  char kids[3][40]
} Party;

读取字符串的函数是:

void createParty():
  Party p;
  char s[LIMIT] = "John's Birthday/25032019/2230/10/1/Thomas/Anna/Jack/Sarah";
  char c[2] = "c";
  char *token;
  int i=0;

  token = strtok(str, s);

   while( token != NULL ) {
      printf( " %s\n", token );
      token = strtok(NULL, s);

      if (i==0)
        strcpy(p.description,token);
      else if (i==1)
        p.date=atoi(token);
      else if (i==2)
        p.time=atoi(token);
      else if (i==3)
        p.duration=atoi(token):
      else if (i==4)
        p.room=atoi(token);
      else if (i==5)
        strcpy(p.parent,token);
      else
        strcpy(p.kids[j-6],token);

      i++
   }

我希望所有值都可以毫无问题地分配,但是当我尝试分配最后一个孩子时,它给了我分段错误。如果我不尝试分配姓氏,则不会出错。

谢谢!

1 个答案:

答案 0 :(得分:0)

以下建议的代码:

  1. 消除了变量i的多重测试
  2. 消除了对“魔术”数字的使用
  3. 更正逻辑错误
  4. 更正语法错误
  5. 确保char数组不会溢出
  6. 干净地编译
  7. 需要一个“ main()function to call the createParty()`函数
  8. 正确原型化函数:createParty()
  9. 以灵活的方式定义结构
  10. 定义“标签”名称,以便调试器可以在结构中的各个字段处循环
  11. 从结构定义中分离出“ typedef”
  12. 只需将MAX_PARTIES更改为1以外的值,就可以有多个参与方。
  13. 记录为什么包含每个头文件
  14. 使用适当的水平和垂直间距以提高可读性
  15. 在循环的顶部,称为strtok()的OPs代码,因此第一次调用strtok()的结果被打印出来,但从未处理到结构中

现在,建议的代码:

#include <stdio.h>    // printf()
#include <string.h>   // strtok(), strncpy()
#include <stdlib.h>   // atoi()

#define LIMIT          500
#define MAX_PARTIES    1
#define MAX_DESC_LEN   40
#define MAX_PARENT_LEN 40
#define MAX_KIDS       3
#define MAX_KID_LEN    40

struct PARTY
{
  char description[ MAX_DESC_LEN ];
  int date;
  int time;
  int duration;
  int room;
  char parent[ MAX_PARENT_LEN ];
  char kids[ MAX_KIDS ][ MAX_KID_LEN ];  // was missing trailing semicolon 
};
typedef struct PARTY MyParty;

// prototypes
void createParty( void );    //  notice 'void' parameter in prototype


void createParty()           //  removed extranious trailing char
{
    MyParty p[ MAX_PARTIES ]; // Note: a 2 space indent level can be 'lost' with variable width fonts
    char s[LIMIT] = "John's Birthday/25032019/2230/10/1/Thomas/Anna/Jack/Sarah";
    char delimiters[] = "//";  // note using '//' as first slash 'escapes' the second slash
    int i=0;

    char * token = strtok( s, delimiters );

    while( token  && i < 11 ) 
    {
        printf( "%s\n", token );

        switch( i )
        {
            case 0:
                strncpy( p[i].description, token, MAX_DESC_LEN-1 );
                break;

            case 1:
                p[i].date = atoi( token );
                break;

            case 2:
                p[i].time = atoi( token );
                break;

            case 3:
                p[i].date = atoi( token );
                break;

            case 4:
                p[i].duration = atoi( token );
                break;

            case 6:
                p[i].room = atoi( token );
                break;

            case 7:
                strncpy( p[i].parent, token, MAX_PARENT_LEN-1 );
                break;

            case 8:
                strncpy( p[i].kids[0], token, MAX_KID_LEN-1 );
                break;

            case 9:
                strncpy( p[i].kids[1], token, MAX_KID_LEN-1 );
                break;

            case 10:
                strncpy( p[i].kids[2], token, MAX_KID_LEN-1 );
                break;

            default:
                printf( "unexpected field found: %s\n", token );
                break;
        }

        i++;  // was missing trailing semicolon
        token = strtok( NULL, delimiters );  // prep for next loop iteration
    } // end switch
}  // end function: createParty()