7

1 行だけが残るか、すべての行が使い果たされるまで、ファイル内の 2 行ごとにスワップすることになっています。その際に別のファイルを使用したくありません。

これが私のコードです:

#include <stdio.h>

int main() {
    FILE *fp = fopen("this.txt", "r+");
    int i = 0;
    char line1[100], line2[100];
    fpos_t pos;
    fgetpos(fp, &pos);

    //to get the total line count
    while (!feof(fp)) {
        fgets(line1, 100, fp);
        i++;
    }

    i /= 2;  //no. of times to run the loop
    rewind(fp);

    while (i-- > 0) {  //trying to use !feof(fp) condition to break the loop results in an infinite loop
        fgets(line1, 100, fp);
        fgets(line2, 100, fp);

        fsetpos(fp, &pos);

        fputs(line2, fp);
        fputs(line1, fp);

        fgetpos(fp, &pos);
    }

    fclose(fp);
    return 0;
}

this.txt の内容:

aaa
b
cc
ddd
ee  
ffff
gg
hhhh
i
jj

プログラム実行後のコンテンツ

b
aaa
ddd
cc
ddd
c
c

c


i
jj

同じ間違った結果を得るためにfseek、代わりに使用してみました。fgetpos

私が考えたところでは、2 番目の while ループが 2 回実行された後(つまり、最初の 4 行が処理された後)、カーソルは 17 番目のバイトにあるはずです(への呼び出しによって返されるftell(fp)) 。 4 行目以降の内容は変更されておらず、ループの 3 回目の実行時に何らかの理由fgetsで呼び出されると、配列 line1 と line2 に読み込まれる内容はそれぞれ "c\n" と "ddd\n" になります。

繰り返しますが、これを達成するために別のファイルを使用したくありません。画面の背後で何が問題になっているのかを正確に把握する必要があるだけです

任意のリードをいただければ幸いです。ありがとうございました。

4

3 に答える 3

2

どちらも同じファイルを指す 2 つのファイル ポインターを使用しないのはなぜでしょうか。1 つは読み取り用、もう 1 つは書き込み用です。ファイルの位置を追跡したり、シークしたり、フラッシュしたりする必要はありません。

このアプローチにより、多くの複雑なものを省くことができます。これらの不必要な努力は、以下のような洗練されたエラー チェック/ログに投資することをお勧めします ;-):

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(void) 
{
  int result = EXIT_SUCCESS;

  size_t blocks = 0;

  int l1_done = 0;
  int l2_done = 0;

  FILE *fpin = fopen("this.txt", "r");
  FILE *fpout = fopen("this.txt", "r+");

  if (NULL == fpin)
  {
    result = EXIT_FAILURE;
    perror("fopen() to for reading failed");
  }    

  if (NULL == fpout)
  {
    result = EXIT_FAILURE;
    perror("fopen() for writing failed");
  }    

  while (EXIT_SUCCESS == result && !l1_done && !l2_done)
  {
    result = EXIT_FAILURE;

    char line1[100];
    char line2[100];

    if ((l1_done = (NULL == fgets(line1, sizeof line1, fpin))))
    {
      if (ferror(fpin))
      {
        fprintf(stderr, "Reading line %zu failed.\n", 2*blocks);
        break;
      }
    }

    if ((l2_done = (NULL == fgets(line2, sizeof line2, fpin))))
    {
      if (ferror(fpin))
      {
        fprintf(stderr, "Reading line %zu failed.\n", 2*blocks + 1);
        break;
      }
    }

    {
      size_t len = strlen(line1);

      if (((sizeof line1 - 1) == len) && ('\n' != line1[len]))
      {
        fprintf(stderr, "Line %zu too long or new-line missing.\n", 2*blocks);
        break;
      } 
    }

    {
      size_t len = strlen(line2);

      if (((sizeof line2 - 1) == len) && ('\n' != line2[len]))
      {
        fprintf(stderr, "Line %zu too long or new-line missing.\n", 2*blocks + 1);
        break;
      }
    } 

    if (!l2_done)
    {
      if (EOF == fputs(line2, fpout))
      {
        fprintf(stderr, "Writing line %zu as line %zu failed.\n", 2*blocks + 1, 2*blocks);
        break;
      }
    } 

    if (!l1_done)
    {
      if (EOF == fputs(line1, fpout))
      {
        fprintf(stderr, "Writing line %zu as line %zu failed.\n", 2*blocks, 2*blocks + 1);
        break;
      } 
    }

    ++blocks;

    result = EXIT_SUCCESS;
  }

  if (EXIT_SUCCESS == result && !ll_done && l2_done)   
  {
    fprintf(stderr, "Odd number of lines.\n");
  }

  fclose(fpin);  /* Perhaps add error checking here as well ... */
  fclose(fpout);  /* Perhaps add error checking here as well ... */

  return result;
}
于 2017-02-05T13:04:38.983 に答える