拆分我从文件中读取的字符串

时间:2016-12-10 12:19:16

标签: c arrays file

我有一个像这样的文件

GET /index.html k
GET /docencia.html k
GET /ejemplo.html k

我希望逐行阅读并使用此分隔符" "将其拆分但是却给了我这个错误:segmentation fault(core dumped)我不知道该尝试什么。

这是我的代码:

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

int main(int argc, char *argv[]) {
    char ordenes[150];
    char *orden[3];
    char *token;
    int tok;

    FILE *fp;
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        printf("File error");
        exit(1);
    }

    while (feof(fp) == 0) {
        fgets(ordenes, sizeof(ordenes), fp);
        printf("%s \n", ordenes);
        token = strtok(ordenes, " ");
        tok = 0;
        while (token != NULL) {
            orden[tok] = strdup(token);
            tok++;
            token = strtok(NULL, " ");
        }

        printf("\n%s\n", orden[0]);
        printf("\n%s\n", orden[1]);
        printf("\n%s\n", orden[2]);
    }
    fclose(fp);
}

当我拨打第一个strdup时会显示错误。如果我在调用第一个strtok后尝试打印令牌,它也会失败(相同的segmentation fault core dumped),所以我想问题出在strtok上。

5 个答案:

答案 0 :(得分:5)

您不包含<string.h>,因此编译器会在strtok的签名上应用默认参数提升,特别是它认为strtok返回int

因此,编译器将在作业中将intpointer to char的强制操作符应用于

token = strtok(ordenes, " ");

并且此作业将编译为

token = (int->char*) strtok(ordenes, " ");

答案 1 :(得分:3)

您的代码中存在多个问题:

  • 由于alinsoar被诊断为敏锐的眼睛,因此不包括<string.h>strtok未定义,编译器必须假定它返回int,而不是int,并且此char *会以静默方式转换为gcc -Wall -W。生成的代码调用未定义的行为,很可能会在64位目标上崩溃。您应该编译并启用所有警告,让编译器帮助避免这种愚蠢的错误。 clang -Weverythingfp = fopen(argv[1], "r"); ...

  • 在调用argv[1]之前,不检查命令行参数是否已传递给您的程序。如果没有传递参数,while (feof(fp) == 0)是空指针。

  • while (fgets(ordenes, sizeof(ordenes), fp)) {...不正确,请阅读Why is “while ( !feof (file) )” always wrong?。你应该写tok < 3

  • 在将token存储到orden数组之前,您不会检查是否orden。如果该行超过3个字段,则会导致缓冲区溢出。

  • fgets()打印所有3个条目之前,您不会检查是否确实找到了3个令牌。这也可能会调用未定义的行为,尤其是#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char ordenes[150]; char *orden[3]; char *token; int i, tok; if (argc < 2) { fprintf(stderr, "Missing command line argument\n"); exit(1); } FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { fprintf(stderr, "Cannot open input file %s: %s\n", argv[1], strerror(errno)); exit(1); } while (fgets(ordenes, sizeof(ordenes), fp)) { printf("%s", ordenes); token = strtok(ordenes, " "); for (tok = 0; tok < 3 && token != NULL; tok++) { orden[tok] = strdup(token); token = strtok(NULL, " "); } for (i = 0; i < tok; i++) { printf("%s\n", orden[i]); free(orden[i]); } printf("\n"); } fclose(fp); return 0; } 无法读取您未检查的行时。

以下是改进版本:

str

答案 2 :(得分:0)

您可以执行以下操作:

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

static void play_with_token(char *token, char const *delim)
{
  if (token == NULL)
    return;
  printf(" %s", token);
  play_with_token(strtok(NULL, delim), delim);
}

int main(int argc, char *argv[])
{
    if (argc != 2)
      return 1;
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL)
      return 1;

    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    while ((read = getline(&line, &len, fp)) != -1) {
      printf("parsing line :");
      char const *delim = " ";
      play_with_token(strtok(line, delim), delim);
      printf("\n");
    }
   free(line);
   fclose(fp);
}

答案 3 :(得分:0)

对于初学者,您应该按照以下方式更改外部循环语句中的条件

while ( fgets(ordenes, sizeof(ordenes), fp) != NULL )

内循环中的条件至少应该写为

  while ( tok < 3 && token != NULL) {

令牌应该循环输出,并且必须释放分配的内存。例如

  for ( int i = 0; i < tok; i++ )
  {
      printf("\n%s\n", orden[i]);
      free( orden[i]);
  }

答案 4 :(得分:-1)

试试这个:

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

int main(int argc, char *argv[]){
    char ordenes[150];
    char *orden[3];
    char *token;
    int tok;
    FILE *fp;

    fp = fopen (argv[1], "r");
    if(fp==NULL){
        printf("File error");
        exit(1);
    }
    while(fgets(ordenes, sizeof(ordenes), fp)){
        printf("%s\n",ordenes);
        token = strtok(ordenes, " ");
        tok = 0;
        while (token != NULL){
            orden[tok++] = strdup(token);
            token = strtok(NULL," ");
        }
        printf("\n%s\n",orden[0]);
        printf("\n%s\n",orden[1]);
        printf("\n%s\n",orden[2]);
        free(orden[0]);free(orden[1]);free(orden[2]);
    }
    fclose(fp);
}