2

Windows NT 4.0 dll ファイル内の txt ファイルの読み取りで問題が発生しています。質問する前に、私は現在、これを新しい OS に移行することに興味はありません。この 1 つの問題を修正して、この超レガシー ソフトウェアの移行について他の人に心配してもらいたいだけです。

次のように、fscanf を使用して txt ファイルを読み取ると、問題が発生します。

infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "r");
byteoffset=0;
while(!feof(infile_ptr) )
    {   
        r=0.0; s1=0.0; s2=0.0; e1=0.0; e2=0.0; e3=0.0; d=0.0; f=0.0;
        fseek(infile_ptr, byteoffset, SEEK_SET);
        fscanf(infile_ptr,"%7lf %7lf %7lf %7lf %7lf %7lf %7lf %7lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);

        byteoffset=0; byteoffset = ftell(infile_ptr);
     }
fclose(infile_ptr);  

MATLAB で作成された txt ファイルは、5 つのスペースで区切られた 8 列の 128 行で構成され、MATLAB 内で次のようにフォーマットされます。

fprintf(fid,'%7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f     %7.3f \n', variables);

このコードは私が書いたものではなく、数年間機能しました。しかし、最近、Windows NT 4.0 OS とソフトウェアを再構築/再インストールする必要があり、奇妙なエラーが発生しました。プログラムは、行 123 に到達するまで、上部にあるコードを使用して txt ファイルを正常に読み取ります。この時点で、8 番目の列を 2 回読み取ります。その結果、後続のすべての変数が 1 桁シフトされ、最後の変数が完全に台無しになります。プログラムの数行。興味深いことに、この問題は、最初の 123 行をまとめて新しい txt ファイルに手動でコピー アンド ペーストし、最後の数行を 1 つずつ同じ新しい txt ファイルにコピーして貼り付け、それを入力として使用することで解決できます (コピーが完了しました)。ワードパッド内の NT マシン上)。そうすることで、この二重読み取りの問題が解消されます。どのような問題がこのエラーを引き起こす可能性があるのか​​ わかりませんが、しかし、そのような奇妙で不格好な方法で修正することもできます。問題は新しい入力と古い入力で発生するため、入力ファイルは変更されていないため、問題ではないと思います。

ああ、さらに、txt ファイルの各列間のスペースの数を変更すると、エラーの場所が移動します。スペースを 1 つに減らすと、120 行目あたりでエラーが発生しますが、スペースの数を増やすと (5 ではなく 7 を試行)、エラーが 124 行目まで押し下げられます。

私はプログラミングの専門家ではありません (常に必要に応じて学習する人でした)。ありがとう!

4

2 に答える 2

1

fscanf()あなたのディレクティブに問題があります。の代わりに
お勧めします。%lf%7lf

withは、少なくとも7 文字を使用して浮動小数点数を出力しfprintf()、必要に応じてパディングします。"%7.3f"' '

その後の"%7lf"inの使用は、最大7 文字fscanf()をスキャンすることを示しています。したがって、printf/scanf 999.999 の場合はすべて問題ありませんが、1000.007 などのより大きな数字では、スキャンは「1000.00」を取り込み、次の「7」を残します。"%7lf"

 int main(void) {
  char buf[1000];
  double f1, f2;
  int r;
  sprintf(buf, "%7.3f %7.3f", 1.23, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %g %g\n", buf, r, f1, f2);

  sprintf(buf, "%7.3f %7.3f", 999.999, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);

  sprintf(buf, "%7.3f %7.3f", 1000.007, 4.56);
  r = sscanf(buf, "%7lf %7lf", &f1, &f2);
  printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);

  return 0;
}

Output:  
'  1.230   4.560'  
2 1.23 4.56  
'999.999   4.560'  
2 999.999 4.56  
'1000.007   4.560'  
2 1000 7  

ところで: の場合fscanf()"%lf%lf%lf ..."OK です。間にスペースを追加しても、%lf機能は変わりません。

于 2013-07-20T02:51:49.063 に答える
0

候補の簡素化

問題の原因は見つかりませんでしたが、デバッグを簡素化するためにこれをお勧めします。これにより、PC の行末、ファイル ポインターの過度の操作、不必要な制限が処理%7lfされ、より優れたエラー チェックが提供されます。

FILE *infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "rt");  // PC text file
char buf[1000];
while (fgets(buf, sizeof(buf), infile_ptr)) {  // separate I/O from scanning
  int count = sscanf(buf,"%lf%lf%lf%lf%lf%lf%lf%lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);  
  if (count != 8) { // check for correct scan count
    ; //handle error;
  }
}
if (ferror(infile_ptr)) {
  ; //handle error;
}
fclose(infile_ptr);

[編集] OP は、元のテキスト ファイルを投稿しました。

また、この行をループに追加して、スペースのみで構成される末尾の行を処理します。

  if (count <= 0) continue;

【追記】結論。

との使用はfseek()、通常はバイナリ ファイルで使用されますが、ここでは必要ありませんが、Windows でバイナリ モードで開かれた UNIX テキスト ファイル ()をftell()読み取る Windows のバグです。ライン 123 またはその隣接を問題領域として示すものは何も見つかりませんでした。\n"r"fscanf()"rt"

于 2013-07-22T15:41:21.963 に答える