【问题标题】:Parsing a text file of integers into an array将整数文本文件解析为数组
【发布时间】:2017-02-08 21:57:46
【问题描述】:

我使用strtok() 解析每个整数并将其放入int nums[1000]。该文件将始终遵循以下格式:

第一行是数组的数字,每个数字用空格分隔。不超过 10 个号码将在线上。第一行之后的文件中没有任何内容。

printf("Starting program\n");
char file_name[100];
strcpy(file_name, args[1]);
char number[100];
strcpy(number, args[2]);
FILE *fp;
fp = fopen(file_name, "r");
if (fp == NULL) {
    printf("Error opening file\n");
}
char int_array[1000];//
int nums[1000]; //storing the integers without spaces
int i = 0; //for indexing the array to save the integers
while (fgets(int_array, 1000, fp) != NULL) {
    printf("%s\n", "test");
    puts(int_array); // prints out `1 2 3 4 5...`
    char *token;
    token = strtok(int_array, " ");
    nums[i] = atoi(token);
    while (token != NULL) {
        token = strtok(NULL, " ");
        nums[i] = atoi(token);
        //puts(token); Token gets printed out correctly.
    }
}

printf("%i\n", nums[i]); // this gives segmentation fault
printf(nums) // also gives seg fault

我不知道为什么会出现段错误。

【问题讨论】:

  • 你真的没有增加i 还是你把它忽略了?如果i 真的是0,那么我不相信printf("%i\n", nums[i]) 会出现段错误。这是不可能的。但是下一行肯定会成为一个问题,因为它完全无效 - 你不能随便打电话给printf。阅读手册页并检查它需要哪些参数。使用调试器准确找出哪一行出现了段错误并检查变量值。
  • 当你这样做时,底部的i 的值是多少:printf("%i\n", nums[i]);?如果超过 999,则可能是 seg 故障的线索
  • aaah 是的,我修改了代码并意外遗漏了 ++i。我仍在努力找出段错误。感谢您指出这一点

标签: c arrays file fgets strtok


【解决方案1】:

你的代码有多个问题,主要问题是你测试token扫描下一个令牌之前:

while (token != NULL) {
    token = strtok(NULL, " ");
    nums[i] = atoi(token);
}

你应该这样做:

while ((token = strtok(NULL, " ")) != NULL) {
    nums[i] = atoi(token);
}

其他问题:

  • strcpy(file_name, args[1]); 中访问argv[1] 之前没有检查argc > 1,可能会调用未定义的行为。
  • 您将文件名复制到一个 100 字节的数组中:如果命令行参数超过 99 字节,则会导致缓冲区溢出。您不需要复制参数,只需将argv[1] 传递给fopen 或使用指针:char *filename = argv[1];
  • 您检查fopen() 是否失败,但不要退出函数...fgets() 对空流指针有未定义的行为。
  • strtok() 可以返回 NULL 即使是第一次通话。在将返回值传递给 atoi() 之前,请务必检查返回值。
  • 您不检查i 是否变得太大。如果i 到达1000,您应该停止读取输入文件。
  • nums 数组传递给printf 是不正确的:printf(nums) 甚至不应该编译,或者至少生成有意义的警告。

请注意,您根本不需要使用strtok()strtol() 可以解析数字并更新指针以指向该数字。

这里是如何使用它:

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

int main(int argc, char *argv[]) {
    printf("Starting program\n");
    if (argc < 2) {
        fprintf(stderr, "missing command line argument\n");
        return 1;
    }
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", argv[1], strerror(errno));
        return 1;
    }
    char buf[1000];
    int nums[1000];
    int i = 0; 

    while (fgets(buf, sizeof buf, fp)) {
        char *p = buf;
        char *q;
        for (; i < 1000; i++) {
            nums[i] = strtol(p, &q, 0);
            if (q == p) {
                /* no more numbers */
                break;
            }
            p = q;
        }
    }
    fclose(fp);
    for (int j = 0; j < i; j++) {
        printf("%d ", nums[j]);
    }
    printf("\n");
    return 0;
}

【讨论】:

  • 你提到的改变令牌的使用得到了段错误所以停止。非常感谢。您介意解释一下与您的实现和我的实现的确切区别吗?
【解决方案2】:

您没有检查 argc 并取消引用 args[1]args[2]

你从不使用number

试试这个:

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

int main( int argc, char * argv[] ) {
   printf("Starting program\n");
   if( argc < 2 ) {
      return 1;
   }
   FILE * fp = fopen( argv[1], "r");
   if( fp == NULL ) {
      perror( argv[1] );
      return 1;
   }
   char int_array[1000];
   if( fgets( int_array, 1000, fp )) {
      int nums[1000];
      int    i = 0; 
      char * token = strtok(int_array, " ");
      while( token ) {
         nums[i++] = atoi(token);
         token = strtok(NULL, " ");
      }
      printf("0: %i\n", nums[0]);
      printf("1: %i\n", nums[1]);
      printf("%d: %i\n", i-1, nums[i-1]);
   }
   return 0;
}

执行:

aubin@Breizh-Atao ~/Dev/C $ gcc parsing.c -o parsing
aubin@Breizh-Atao ~/Dev/C $ echo 1 2 3 4 5 6 7 8 9 10 11 >parsing.txt
aubin@Breizh-Atao ~/Dev/C $ ./parsing parsing.txt 
Starting program
0: 1
1: 2
10: 11
aubin@Breizh-Atao ~/Dev/C $ 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    相关资源
    最近更新 更多