fscanf在文件中提取各种大小的多个整数

时间:2016-03-26 18:47:40

标签: c

我有一个文本文件,我正在尝试提取所有整数并将它们放入数组中。整数的大小各不相同,可能包括逗号和小数(如果存在小数,我会截断小数)。
这是文件中的文字:

This is a test text file...
This is line 2.
This could be line 3.
Ben Franklin was here.
Blah!
Pi is 3.1415
The dinosaurs died 65,000,000 years ago.
I am 31 years old.
Our baby's due date is the 9th of April.
Tom's bday is 9/1/1986

我可以用任何方式制作类似的数组: [2, 3, 3, 65000000, 31, 9, 9, 1, 1986]

原始代码使用getc(),但这不起作用,因为它一次只能取出一位数字。

int find_ints(FILE *fp, int arr[])
{
  int ch, num = 0;

  while((ch = getc(fp)) != EOF) {
    if(isdigit(ch)) {
      *arr++ = ch - '0';
      num++;
    }
  }

  return num;
}
  

使用fscanf会更好吗?

如果是这样,有人可以帮我一点走吗?我一开始就有这个,但它只抓住了第一个int

fscanf(fp, "%*[0123456789,]%d", arr)

3 个答案:

答案 0 :(得分:3)

这是一个很好的练习,你需要思考,但你必须一步一步地考虑它,并考虑到你一次阅读文件中所遇到的所有角色突发事件。

您可以采取的两种主要方法是(1)读取每个字符,如果是数字,则执行转换和中间和来构建整数的值,或者(可能更容易)(2)将每个数字添加到字符数组,当您到达非数字时, nul-terminate 并使用atoi或{{1}将字符数组转换为整数}。我发现第二个更容易一些。 (否则,您需要处理遇到的每个数字的中间和)

采用第二种方法,您可以编写类似于strtol的内容:

findints

您可以进行改进,但需要花时间逐步完成逐行逐个字符以了解所完成的测试如何构建,转换和重置字符数组,如何对包含int findints (FILE *fp, int *arr, size_t sz) { int c, n = 0, idx = 0; char tmp[MAXD] = ""; while ((c = fgetc (fp)) != EOF) { /* for each char */ if (c == ',') /* get next if , */ continue; if (idx && !isdigit(c)) { /* if end of digits */ tmp[idx] = 0; /* nul-terminate */ arr[n++] = (int) strtol (tmp, NULL, BASE); /* convert to int */ idx = 0; /* reset idx */ memset (tmp, 0, sizeof tmp); /* reset tmp */ if (n == (int)sz) { /* validate sz < MAXSZ */ fprintf (stderr, "warning: MAXSZ reached.\n"); break; } if (c == '.') /* truncate after '.' */ while (isdigit ((c = fgetc (fp)))) {} } if (isdigit (c)) /* add digit to char array */ tmp[idx++] = c; } return n; } 的数字进行十进制截断等。

您可以使用调用'.'的短程序测试数据文件中的代码。 注意:代码作为第一个参数从文件中读取(如果默认情况下没有提供文件名,则来自findints。)

stdin

示例输出

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

enum { BASE = 10, MAXD = 21, MAXSZ = 128 };

int findints (FILE *fp, int *arr, size_t sz);

int main (int argc, char **argv) {

    int a[MAXSZ] = {0}, i, n = 0;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    n = findints (fp, a, MAXSZ);    /* call findints */

    printf ("\n the array has '%d' elements.\n\n", n);
    for (i = 0; i < n; i++)
        printf ("  array[%2d] : %d\n", i, a[i]);
    putchar ('\n');

    if (fp != stdin)
        fclose (fp);

    return 0;
}

int findints (FILE *fp, int *arr, size_t sz)
{
    int c, n = 0, idx = 0;
    char tmp[MAXD] = "";

    while ((c = fgetc (fp)) != EOF) {       /* for each char    */
        if (c == ',')                       /* get next if ,    */
            continue;
        if (idx && !isdigit(c)) {           /* if end of digits */
            tmp[idx] = 0;                   /* nul-terminate    */
            arr[n++] = (int) strtol (tmp, NULL, BASE);  /* convert to int */
            idx = 0;                        /* reset idx */
            memset (tmp, 0, sizeof tmp);    /* reset tmp */
            if (n == (int)sz) {             /* validate sz < MAXSZ */
                fprintf (stderr, "warning: MAXSZ reached.\n");
                break;
            }
            if (c == '.')   /* truncate after '.' */
                while (isdigit ((c = fgetc (fp)))) {}
        }
        if (isdigit (c))    /* add digit to char array */
            tmp[idx++] = c;
    }

    return n;
}

当您发现或遇到其他情况时(如评论中所述),您可以优化$ ./bin/txt2array <dat/getint.txt the array has '9' elements. array[ 0] : 2 array[ 1] : 3 array[ 2] : 3 array[ 3] : 65000000 array[ 4] : 31 array[ 5] : 9 array[ 6] : 9 array[ 7] : 1 array[ 8] : 1986 进程以执行您希望它执行的操作。原始数据文件中未解决的一个此类情况是,前导findints后跟数字(例如'.'(比如.nnn))。由于您的原始问题会截断所有小数,因此上面应评估为.1234,但0是有效的整数值。因此,您可以决定将任何小数部分视为原始语句中0 0.1234,但仍然可以将其自身添加到数组中。

因此,当您的字符数组中没有添加任何数字时,您需要对0进行测试。遇到'.'之前存在数字的情况已由'.'涵盖,因此您只需添加以下内容:

if (idx && !isdigit(c))

这是构建您自己的解析例程的好处,您可以定制它以完成您需要它做的事情,并在遇到需要解决的其他案例时添加它。

如果您有任何问题,请与我们联系。

答案 1 :(得分:0)

  • fgets(strbuff, sizeof(strbuff), fp)
  • 用空格替换所有标记(即/)。
  • 删除所有逗号(,)并尾随/n
  • 使用strtok()
  • 使用atof()
  • 解析每个令牌
  • atof()结果存储为long long int
  • 重复每个令牌
  • 重复每一行。

答案 2 :(得分:-1)

首先将行(从文件)复制到字符串中然后您可以使用"atoi(some_string)"函数返回位于some_string的第一个整数....我认为它可以帮助使数组成为你希望......