将整数的文本文件解析为数组

时间:2022-05-26 05:07:13

I'm using strtok() to parse each integer and place it into int nums[1000]. The file will always follow the format of:

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

the first line has the numbers for the array, each separated by spaces. No more than 10 numbers will be on the line. Nothing is in the file after the first line.

第一行包含数组的数字,每个数字用空格分隔。不超过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 cannot figure out why I am getting seg fault.

我无法弄清楚为什么我会遇到段故障。

2 个解决方案

#1


3  

There are multiple problems in your code, the main issue is you test token before scanning the next token:

您的代码中存在多个问题,主要问题是您在扫描下一个令牌之前测试令牌:

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

You should instead do this:

你应该这样做:

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

Other issues:

  • You do not check if argc > 1 before accessing argv[1] in strcpy(file_name, args[1]);, potentially invoking undefined behavior.
  • 在strcpy(file_name,args [1]);中访问argv [1]之前,不检查是否argc> 1,可能会调用未定义的行为。

  • You copy the file name into a 100 byte array: if the command line argument is longer than 99 bytes, you are causing a buffer overflow. You do not need to copy the argument, just pass argv[1] to fopen or use a pointer: char *filename = argv[1];
  • 将文件名复制到100字节数组中:如果命令行参数超过99字节,则会导致缓冲区溢出。您不需要复制参数,只需将argv [1]传递给fopen或使用指针:char * filename = argv [1];

  • You check if fopen() failed, but do not exit the function... fgets() has undefined behavior for a null stream pointer.
  • 您检查fopen()是否失败,但不退出函数... fgets()具有空流指针的未定义行为。

  • strtok() can return NULL even for the first call. Always check the return value before passing it to atoi().
  • 即使第一次调用,strtok()也可以返回NULL。在将其传递给atoi()之前,请务必检查返回值。

  • You do not check if i becomes too large. You should stop reading the input file if i reaches 1000.
  • 你不检查我是否变得太大。如果我达到1000,你应该停止读取输入文件。

  • Passing the nums array to printf is incorrect: printf(nums) should not even compile, or at least generate meaningful warnings.
  • 将nums数组传递给printf是不正确的:printf(nums)甚至不应该编译,或者至少生成有意义的警告。

Note that you do not need to use strtok() at all. strtol() can parse a number and update a pointer to point past the number.

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

Here is how to use that:

以下是如何使用它:

#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


0  

You are not checking argc and derefencing args[1] and args[2].

你没有检查argc和derefencing args [1]和args [2]。

You never use number.

你永远不会使用数字。

Try this:

#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;
}

Execution:

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 $ 

#1


3  

There are multiple problems in your code, the main issue is you test token before scanning the next token:

您的代码中存在多个问题,主要问题是您在扫描下一个令牌之前测试令牌:

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

You should instead do this:

你应该这样做:

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

Other issues:

  • You do not check if argc > 1 before accessing argv[1] in strcpy(file_name, args[1]);, potentially invoking undefined behavior.
  • 在strcpy(file_name,args [1]);中访问argv [1]之前,不检查是否argc> 1,可能会调用未定义的行为。

  • You copy the file name into a 100 byte array: if the command line argument is longer than 99 bytes, you are causing a buffer overflow. You do not need to copy the argument, just pass argv[1] to fopen or use a pointer: char *filename = argv[1];
  • 将文件名复制到100字节数组中:如果命令行参数超过99字节,则会导致缓冲区溢出。您不需要复制参数,只需将argv [1]传递给fopen或使用指针:char * filename = argv [1];

  • You check if fopen() failed, but do not exit the function... fgets() has undefined behavior for a null stream pointer.
  • 您检查fopen()是否失败,但不退出函数... fgets()具有空流指针的未定义行为。

  • strtok() can return NULL even for the first call. Always check the return value before passing it to atoi().
  • 即使第一次调用,strtok()也可以返回NULL。在将其传递给atoi()之前,请务必检查返回值。

  • You do not check if i becomes too large. You should stop reading the input file if i reaches 1000.
  • 你不检查我是否变得太大。如果我达到1000,你应该停止读取输入文件。

  • Passing the nums array to printf is incorrect: printf(nums) should not even compile, or at least generate meaningful warnings.
  • 将nums数组传递给printf是不正确的:printf(nums)甚至不应该编译,或者至少生成有意义的警告。

Note that you do not need to use strtok() at all. strtol() can parse a number and update a pointer to point past the number.

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

Here is how to use that:

以下是如何使用它:

#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


0  

You are not checking argc and derefencing args[1] and args[2].

你没有检查argc和derefencing args [1]和args [2]。

You never use number.

你永远不会使用数字。

Try this:

#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;
}

Execution:

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 $