【问题标题】:How to use strtok in text file如何在文本文件中使用strtok
【发布时间】:2018-12-20 04:49:17
【问题描述】:

我有一个如下所示的文本文件:

Jane Smith 1111

Alex John 2222

Joe Bon 1234

我正在尝试解析这些数据并将其放入结构数组中。当我从文件中获取一行并使用 strtok 时,会打印正确的数据,但不会将其复制到结构中。如何复制数据?这是我的代码:

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

#define MAX_NUM 100

struct object {
  char fname[20];
  char lname[20];
  char phoneNum[20];
};

typedef struct object Person;

int main (int argc, char ** argv) {
  FILE *fp;
  int i = 0;
  Person person[MAX_NUM];

  fp = fopen(argv[1], "r");
  char *token;

  char line[256];

  int y = 1;

  while (fgets(line, sizeof(line), fp)) {
    token = strtok(line, " ");
    arr[0] = token;

     while(token != NULL) {
      token = strtok(NULL, " ");
      arr[y] = token;
      y++;
    }
    strcpy(person[i].fname, arr[0]);
    strcpy(person[i].lname, arr[1]);
    strcpy(person[i].phoneNum, arr[2]);
    i++;
  }

  printf("%s\n", person[i].fname); //why does nothing print
  printf("%s\n", person[i].lname);
  printf("%s\n", person[i].phoneNum);

}

【问题讨论】:

  • 读取第二行后y的值是多少?这可能是学习如何使用调试器的好时机,但是您应该能够使用一张纸来模拟计算机来回答我的问题。
  • 寻找arr的神秘起源对我们来说是一个挑战吗?
  • 这里有一个可能的收获:将错误归咎于程序中最神秘的(对你而言)部分总是很诱人。所以当你学习一个新的 API 时,你会倾向于假设问题与此有关。夏洛克福尔摩斯不会犯这个错误。他会告诉你,大多数错误都是愚蠢的小错别字,我们每个人都会时不时犯,而你发现问题的最佳策略是客观地查看实际证据,不要预先判断。正是 tgat 的 习惯 使 福尔摩斯 成为 比 Cpl 更好 的 侦探 .普洛德。
  • 我强烈建议不要使用 strtok(根据 Brian Kernighan 的说法,这是“计算历史上设计最差的函数”)。获取 strsep 的实现,省去你的麻烦。

标签: c arrays pointers token strtok


【解决方案1】:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define MAX_NUM 100

struct object {
  char fname[20];
  char lname[20];
  char phoneNum[20];
};

typedef struct object Person;

int main (int argc, char *argv[])
{
    FILE *fp;
    int i;
    Person person[MAX_NUM];
    char line[256];

    // Check command line arguments
    if (argc != 2)
    {
        printf("Usage: %s <file>\n", argv[0]);
        return -1;
    }

    // Check FILE *
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("FAILED TO OPEN %s\n", argv[1]);
        return -1;
    }

    while (fgets(line, sizeof(line), fp))
    {
        if (sscanf(line, "%s %s %s", person[i].fname, person[i].lname, person[i].phoneNum) < 3)
        {
            printf("ILLEGAL TEXT: <<%s>>\n", line);
        }
        else
        {
            printf("RECORD %s %s %s\n", person[i].fname, person[i].lname, person[i].phoneNum);
            i++;
        }
    }

    // Close file
    fclose(fp);

    printf("%d RECORD(S) HAVE(HAS) BEEN PARSED SUCCESSFULLY\n", i);

    return 0;
}

demo.data:

Jane Smith 1111 
Alex John 2222 
Joe Bon 1234 
Invalid line
 Space  Tab 6666
Joy Allen 2333
Jane Smith 1111 
Alex John 2222 
Joe Bon 1234 
Invalid line
 Space Tab 6666
Joy Allen 2333
Jane Smith 1111 
Alex John 2222 
Joe Bon 1234 
Invalid line
 Space Tab 6666
Joy Allen 2333

运行:

$ ./demo demo.data
RECORD Jane Smith 1111
RECORD Alex John 2222
RECORD Joe Bon 1234
ILLEGAL TEXT: <<Invalid line
>>
RECORD Space Tab 6666
RECORD Joy Allen 2333
RECORD Jane Smith 1111
RECORD Alex John 2222
RECORD Joe Bon 1234
ILLEGAL TEXT: <<Invalid line
>>
RECORD Space Tab 6666
RECORD Joy Allen 2333
RECORD Jane Smith 1111
RECORD Alex John 2222
RECORD Joe Bon 1234
ILLEGAL TEXT: <<Invalid line
>>
RECORD Space Tab 6666
RECORD Joy Allen 2333
15 RECORD(S) HAVE(HAS) BEEN PARSED SUCCESSFULLY

【讨论】:

    【解决方案2】:

    好吧,您应该想知道在打印时i 的值是多少...

    它是你离开的地方,只有一个传递了存储在 person 数组中的最后一个值,所以你没有得到任何值也就不足为奇了。

    修复很简单:只需循环直到i

      for(y=0; y<i; y++) {
        printf("%s\n", person[y].fname);
        printf("%s\n", person[y].lname);
        printf("%s\n", person[y].phoneNum);
      }
    

    【讨论】:

      【解决方案3】:

      如果你想解析这些数据并将其放入一个结构数组中,你可以使用这个函数:

      char  ** split(char string[], int * num, char * sep) 
      {
          char * pch;
          char ** out = 0;
          int i = 0;
          pch = strtok(string, sep);
      
          while (pch != 0) {
              out = realloc(out, (i + 1) * sizeof(char *));
              out[i] = malloc(strlen(pch) + 1);
              strcpy(out[i], pch);
              ++i;
              pch = strtok(NULL, sep);
          }
          *num = i;
          return out;
      }
      

      该函数将字符串拆分为二维数组,您可以将它们放入结构中

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多