fscanf提取文件中不同大小的多个整数

fscanf提取文件中不同大小的多个整数,c,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

我有一个文本文件,我试图提取所有整数,并将它们放入一个数组中。整数大小不一,可能包括逗号和小数(如果有小数,我会截断小数)。
以下是文件中的文本:

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,11986]

原始代码使用了
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)
首先将行(从文件)复制到字符串中,然后您可以使用
“atoi(some_string)”
函数返回
some_string
中的第一个整数……我认为这有助于按照您的期望制作数组……

  • fgets(strbuff,sizeof(strbuff),fp)
  • 将所有令牌(即
    /
    )替换为空格
  • 删除所有逗号(
    )和尾部的
    /n
  • 使用strtok()
  • 使用
    atof()解析每个令牌
  • atof()
    结果存储为
    long-long-int
  • 对每个令牌重复此操作
  • 每行重复一次

这是一个很好的练习,可以让您仔细思考,但您必须一步一步地进行,并考虑每次读取文件时遇到的所有字符意外情况

您可以采取的两种主要方法是:(1)读取每个字符,如果是数字,则执行转换和中间求和以生成整数的值,或者(可能更容易)(2)将每个数字添加到字符数组中,当到达非数字时,nul使用
atoi
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;
}
示例输出

$ ./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
这就是构建您自己的解析例程的好处,您可以对其进行定制,使其完全满足您的需要,并在遇到需要解决的其他情况时添加到解析例程中


如果您有任何问题,请告诉我。

它似乎有点松散。假设在
1e9
格式中有一个浮点数?假设有一个日期,格式为
26.3.2016
?假设有短语
可以是64,65项
。假设有一个负数?我建议一个字符一个字符地读,直到你遇到一个数字,然后你处理一个数字,直到你的规则完成为止。如何累积一个数字<代码>整数=0然后对于每个数字
数字=数字*10+ch-'0'你所说的“各种大小的整数”是什么意思?使用fscanf是更好的方法吗?不可以。当您正在读取的行具有可能不同的内容时,使用
fscanf
即使是更好的选择,也很少。您的选择是面向字符的输入(正如您使用
fgetc
),在读取每个字符时对其作出反应;或者是面向行的输入(如
fgets
getline
),您一次读取一行,并使用
sscanf
或沿着字符串向下移动指针来解析结果缓冲区<代码>fscanf
对于这样的问题,就像试图在方孔中塞进一个圆销钉一样。角落案例:
.123
应该变成什么:
0
?(这是一个包含小数点的数字)或
123
Nice-response bTwnone无有效角盒。根据这个问题,截断
'.
后面的所有内容将导致
0
,但由于
0
是一个有效的整数,因此可能会在数组中结束。接得好。非常感谢,大卫。我真的很感谢你的帮助!这并不解决
所需的处理。如果“将所有令牌(即
/
)替换为空格”,则转换将失败
65000000
9/1/1986
,并且无法截断
3.1415
。您必须单独处理分隔符。@DavidCRankin
由atof处理并强制转换为int。
需要删除,而不是替换为空格,日期分隔符替换为空格,其余由strtok()完成。已授予,您的
atof
处理,随后对
int
的强制转换将截断小数部分。非常感谢您的输入。我真的很感激。
$ ./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
while ((c = fgetc (fp)) != EOF) {       /* for each char    */
    ...
    if (idx && !isdigit(c)) {           /* if end of digits */
        ...
    }
    /* consider '.nnn' as 0 */
    if (c == '.' && isdigit ((c = fgetc (fp)))) {
        while (isdigit ((c = fgetc (fp)))) {}
        arr[n++] = 0;
    }
    ...