将整数文本文件解析为数组
Parsing a text file of integers into an array
我正在使用 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
我不明白为什么会出现段错误。
您没有检查 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 $
您的代码中存在多个问题,主要问题是您在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()
可以 return NULL
即使是第一次调用。在将 return 值传递给 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;
}
我正在使用 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
我不明白为什么会出现段错误。
您没有检查 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 $
您的代码中存在多个问题,主要问题是您在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()
可以 returnNULL
即使是第一次调用。在将 return 值传递给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;
}