2016-03-26 4 views
1

すべての整数を取り出して配列に配置しようとしているテキストファイルがあります。整数はさまざまなサイズで、カンマと小数点が含まれます(小数点がある場合は小数点以下を切り捨てます)。 [2, 3, 3, 65000000, 31, 9, 9, 1, 1986]fscanfファイル内のさまざまなサイズの複数の整数を抽出する

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 

私のようなものの配列を作ることができます任意の方法:
は、ここでファイルのテキストですか?

オリジナルコードgetc()を使用しましたが、これは一度に1桁だけを引き出したので機能しませんでした。関数fscanfを使用して

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

なり、より良い方法は?

もしそうなら、誰かが私を少し歩くことができますか?私はこれを最初に持っていましたが、それは最初のものをつかんだだけでした。int。文字列に(ファイルから)行は、あなたがsome_stringにある最初の整数を返し"atoi(some_string)"機能を使用することができます

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

少し緩いようです。 '1e9'の形式で浮動小数点数があるとしますか?そして、 '26.3.2016'の形式の日付があるとしますか? 「64,65品目」という表現があるとします。負の数があるとしますか?私はあなたが数字を満たすまでcharでcharを読むことをお勧めします。そして、あなたのルールによって完了するまで数字を処理します。番号を累積する方法は? '数値=数字* 10 +チャンネル - '0';' –

+0

「さまざまなサイズの整数」とはどういう意味ですか? – Cristy

+0

* fscanfを使用する方が良いでしょうか?* **いいえ**読んでいる行が潜在的に異なる内容のときに 'fscanf'を使うのは*めったにない*、*もっと良い選択肢です。あなたの選択は、各文字が読み込まれるときにそれに反応する*文字指向の*入力( 'fgetc'でやっているように)か、*行指向の*入力(' fgets'や 'getline'など)です。行を一度に読み込み、結果のバッファを 'sscanf'でパースするか、ポインタを文字列の下に移動してください。 'fscanf'のような問題は、正方形の穴に丸めペグを詰め込もうとするようなものです。 –

答えて

-1

まずコピーが....私はそれはあなたが望んでいるとして配列を作るのを助けることができると思います。 ..

+0

ありがとう、入力の束。ほんとうにありがとう。 – TRP

0
  • fgets(strbuff, sizeof(strbuff), fp)
  • スペースですべてのトークン(すなわち/)を交換してください。
  • 全てのコンマ(,)を除去し、/n
  • 使用strtok()
  • がライン毎に各トークン
  • リピートためlong long int
  • リピートとしてatof()
  • ストアatof()結果と、各トークンを解析末尾。
+0

これは '.'と'、 'に必要な処理には対応していません。 – chux

+0

"*すべてのトークン(つまり'/')をスペースで置き換える*"とすると、変換は '65000000'と' 9/1/1986'に失敗し、 '3.1415'は切り捨てられません。デリミタは個別に処理する必要があります。 –

+0

@DavidCRankin '.'はatofによって処理され、intにキャストされます。 '、'は削除する必要があり、スペースで置き換えられません。日付の区切り文字はスペースで置き換えられ、残りはstrtok()で置き換えられます。 – xvan

3

これはあなたが思考するには良い練習ですが、一度に1文字ずつファイルを読む際に遭遇するすべての偶発的な事態を考慮して、段階的に考慮する必要があります。

あなたが取ることができる2つの主なアプローチは、(1)各数字を読み、整数の値を構築するために変換と中間和を実行するか、(おそらくより簡単に)(2) 文字配列に、にヌル終了を入力し、atoiまたはstrtolを使用して文字配列を整数に変換します。私は少し簡単に2番目を見つける。第二のアプローチを取る

(そうでない場合は、あなたが遭遇した各桁の中間和を処理する必要があります)、あなたはに似て、あなたの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プロセスを絞り込むことができます行う。このようなケースの1つは、オリジナルのデータファイルで扱われていない場合は、先頭に'.'の数字が続きます(例:.nnn(たとえば.1234))。元の質問はすべての小数点以下を切り捨てたので、上記の数値は0となりますが、0は有効な整数値です。したがって、小数部分を0.1234のように扱うことができます。元のステートメントでは0になりますが、それでも配列自体には追加されます。

文字配列に数字が追加されていない場合、'.'のテストが必要です。 '.'に遭遇する前に数字が存在するが、すでにif (idx && !isdigit(c))で覆われている場合、あなただけのような何かを追加必要があるので:自分の解析ルーチンを構築することの利点である

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

を、あなたは正確に何を行うには、それを調整することができます対処する必要がある追加のケースが発生したときに、追加して追加する必要があります。

質問がある場合はお知らせください。

+0

コーナーケース: '.123'は' 0'になるべきですか? (それは小数点を含む数字です)または '123'ニースの答えbtw – chux

+0

それにもかかわらず、有効なコーナーケースです。疑問によると、 ''。 ''に続くすべてを切り捨てると '0'が返されますが、 '0'は有効な整数なので、おそらく配列に終わるはずです。良いキャッチ。 –

+0

ありがとう、David。私は本当に助けに感謝します! – TRP

関連する問題