これはあなたが思考するには良い練習ですが、一度に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;
}
...
を、あなたは正確に何を行うには、それを調整することができます対処する必要がある追加のケースが発生したときに、追加して追加する必要があります。
質問がある場合はお知らせください。
少し緩いようです。 '1e9'の形式で浮動小数点数があるとしますか?そして、 '26.3.2016'の形式の日付があるとしますか? 「64,65品目」という表現があるとします。負の数があるとしますか?私はあなたが数字を満たすまでcharでcharを読むことをお勧めします。そして、あなたのルールによって完了するまで数字を処理します。番号を累積する方法は? '数値=数字* 10 +チャンネル - '0';' –
「さまざまなサイズの整数」とはどういう意味ですか? – Cristy
* fscanfを使用する方が良いでしょうか?* **いいえ**読んでいる行が潜在的に異なる内容のときに 'fscanf'を使うのは*めったにない*、*もっと良い選択肢です。あなたの選択は、各文字が読み込まれるときにそれに反応する*文字指向の*入力( 'fgetc'でやっているように)か、*行指向の*入力(' fgets'や 'getline'など)です。行を一度に読み込み、結果のバッファを 'sscanf'でパースするか、ポインタを文字列の下に移動してください。 'fscanf'のような問題は、正方形の穴に丸めペグを詰め込もうとするようなものです。 –