あなたはそれを変換するかどうかを知っている(と読む)はありませんので、あなたは、fscanf()
からのデータかどうかを戻り値をチェックしません。
さらに、printf()
ためdouble
ための指定子は(あなたが希望する形式に応じて、または%f
または%g
)%e
です。 %le
はC言語の有効な指定子ではないため、コンパイラまたはCライブラリが%le
を受け入れているため、プログラムによって何かが出力される場合があります。 (それはとしてそれを理解してどのような形式で、しかし、おそらくdouble
ではありません。)ここで
あなたはダブルスを読むべきかです:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#define COUNT 4
int main(void)
{
const char *filename = "hola.rtf";
FILE *input;
double v1[COUNT], v2[COUNT];
int i;
input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Cannot open %s: %s.\n", filename, strerror(errno));
return EXIT_FAILURE;
}
for (i = 0; i < COUNT; i++) {
if (fscanf(input, " %le %le", &(v1[i]), &(v2[i])) != 2) {
fprintf(stderr, "Invalid data in %s.\n", filename);
fclose(input);
return EXIT_FAILURE;
}
printf("Read %e and %e from %s.\n", v1[i], v2[i], filename);
}
if (ferror(input)) {
fclose(input);
fprintf(stderr, "Error reading %s.\n", filename);
return EXIT_FAILURE;
}
if (fclose(input)) {
fprintf(stderr, "Error closing %s.\n", filename);
return EXIT_FAILURE;
}
printf("All %d pairs of doubles read successfully.\n");
return EXIT_SUCCESS;
}
多くのプログラマは、彼らが後で戻ってエラーチェックを追加することができると信じてこれは実用的ではありません。彼らは通常、最終的には、エラーチェックがないか、またはごくわずかしかないコードです。しかし、ユーザーとして、あなたはプログラムが誤動作するのを知りたいのではなく、まともな結果の代わりにガーベッジを作り出したいのですか?私は間違いなく、実際の作業を行うためにコードを使用するすべての人と同様にします。あなたがそれをしないことを学ぶならば、後でそれをすることを学ぶことは非常に難しいので、入り込むことは重要な習慣です。
もちろん、エラーチェックのレベルについても説明できます。ここでは多くのメンバーがferror()
をチェックし、fclose()
の結果を「不要」とチェックしていると思います。通常の通常の操作ではが失敗しないことは事実です。プログラマにとって、どちらかが失敗することは決してありません。しかし、それらが失敗すると、誰かがコードをFUSEファイルシステム上で実行して、近いうちにエラーを報告することができます。チェックは、ゴミのトンと何かが間違っているという早期警告の違いを意味します。
あなたが私の感想に同情した場合(セミパナソイドのエラーチェックは害がなく、時にはユーザにとって非常に便利です)、コマンドで指定されたファイルからすべてのダブルペアを読み込む次のコードの変種を検討してください
:2Dベクトルが非常に簡単であるように、標準入力からすべての二重ペアを読み出すために、上記の機能を使用して
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
typedef struct {
double x;
double y;
} vec2d;
/* Read all 2D vectors from stream 'input',
into a dynamically allocated array.
(Similar to POSIX.1 getline(), but with double vectors.)
If *dataptr is not NULL, and *sizeptr > 0,
it will initially be used (but reallocated if needed).
Returns the number of vectors read,
or 0 with errno set if an error occurs.
*/
size_t vec2d_readall(FILE *input, vec2d **dataptr, size_t *sizeptr)
{
vec2d *data;
size_t size;
size_t used = 0;
if (!input || !dataptr || !sizeptr) {
/* At least one of the parameters is NULL. */
errno = EINVAL;
return 0;
}
if (ferror(input)) {
/* input stream is already in error state. */
errno = EIO;
return 0;
}
if (!*dataptr || !*sizeptr) {
/* *dataptr is NULL, or *sizeptr == 0,
so we initialize them to empty. */
*dataptr = NULL;
*sizeptr = 0;
}
data = *dataptr;
size = *sizeptr;
while (1) {
if (used >= size) {
/* We need to grow the data array. */
/* Simple allocation policy:
allocate in sets of roughly 1024 vectors. */
size = (used | 1023) + 1021;
data = realloc(data, size * sizeof *data);
if (!data) {
/* Realloc failed! */
errno = ENOMEM;
return 0;
}
*dataptr = data;
*sizeptr = size;
}
if (fscanf(input, " %lf %lf", &(data[used].x), &(data[used].y)) != 2)
break;
/* One more vector read successfully. */
used++;
}
/* If there was an actual I/O error, or
the file contains unread data, set errno
to EIO, otherwise set it to 0. */
if (ferror(input) || !feof(input))
errno = EIO;
else
errno = 0;
return used;
}
(エラーが発生しなかった場合0
に)vec2d_readall()
関数は常にerrno
を設定しているため、動的に割り当てられた配列に行
int main(void)
{
vec2d *vectors = NULL;
size_t num_vectors = 0;
size_t max_vectors = 0;
size_t i;
num_vectors = vec2d_readall(stdin, &vectors, &max_vectors);
if (errno) {
fprintf(stderr, "Standard input: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Read %zu vectors from standard input,\n", num_vectors);
printf("with memory allocated for up to %zu vectors.\n", max_vectors);
for (i = 0u; i < num_vectors; i++)
printf("%f %f\n", vectors[i].x, vectors[i].y);
return EXIT_SUCCESS;
}
書面で少しの努力を費やしてvec2d_readall()
main()
を簡略化しました。さらに、3Dベクトルを読み取るために同様の関数が必要な場合は、typedef struct { double x; double y; double z } vec3d;
を追加し、vec2d_readall()
に少し変更を加えてvec3d_readall()
にする必要があります。
最も重要なことに、vec2d_readall()
〜は、データに問題がある場合は、に頼ることができます。ループの外にちょうどbreak;
の代わりに、エラー報告を加えることができます。
コメントに記載されているgetline()
について不思議であれば、これはPOSIX.1システムのCプログラマーが無制限の入力行を読むことを可能にするPOSIX.1-2008標準関数です。 fgets()
に似ていますが、動的メモリ管理があります。
これはRTFファイルですか? (リッチテキスト形式)。 RTFを解析する必要があるので、これはうまくいきません。ファイルをバイナリ形式でダンプ/表示して形式を確認します。 –
'hola.rtf'の最初の3-4行を表示してください。 –
そして 'scanf'の戻り値を調べて、doubleの読み込みに成功したかどうかを判断してください。 –