0

配列を含むテキスト ファイルを読み込もうとすると問題が発生します。実行すると、.txt に 5x5 の行列がある場合、コンソールに「Reading 1 numbers from file Numbers.txt」と「Showing 1 numbers from data array」というメッセージが表示され、次の行に番号 2 が表示されます。これを修正する方法についてのアドバイスは大歓迎です。

配列を含むテキスト ファイルを次に示します。

Numbers.txt:

1 2 3 4 5
5 4 3 2 1
1 2 3 4 5
5 4 3 2 1
1 2 3 4 5

ここにcコードがあります:

#include <stdio.h>

/* Routines called. */
int readNums(char *filename, int *data);
void showData(int *data, int len);

void main(void)
{
    char key;
    int len, data[1000];

    printf("Hello TV Land! \n");

    len = readNums("Numbers.txt", data);

    showData(data, len);

    scanf("%c", &key);
}

int readNums(char *filename, int *data)
{
    FILE *in;
    int len;
    int j;

    in = fopen("Numbers.txt", "r");

    if (in == NULL) {
        printf("Could not find file: %s \n", filename);
    }
    else {
        printf("Reading numbers...\n");

        fscanf(in, "%d", &len);

        printf("reading %d numbers from file %s ....\n", len, filename);

        for(j=0;j<len;j++) {
            fscanf(in, "%d", data + j);
        }

        fclose(in);
    }

    return len;
}


void showData(int *data, int len)
{
    int j;

    printf("Showing %d numbers from data array....\n", len);
    for(j=0;j<len;j++) {
        printf("%d ", *(data + j));
    }
    printf("\n");
}
4

2 に答える 2

2

スキャンする最初の数字は各行のアイテム数ですが、ファイルの最初の行は a1であり、そうではない5ため、余分な数字を 1 つだけ読み取ります。

ファイルはおそらく次のようになります。

25
1 2 3 4 5
5 4 3 2 1
1 2 3 4 5
5 4 3 2 1
1 2 3 4 5

または、サイズが固定されている場合、ファイルから数値または項目をまったく読み取る必要はありません。

于 2013-09-12T16:51:16.143 に答える
1

C++ 標準ライブラリを利用して、より簡潔なコードを作成できます。確かに、一度にすべてを学ぶのは簡単ではありません (練習が必要です。これが、私がこのような質問に答える理由の 1 つです)。

次のコードは、あなたが求めていることを実行します。つまり、ファイルから読み取り、内容を画面に出力します。より柔軟にすることができます (たとえば、コマンド ライン引数を介してファイル名を指定する)。例外を処理したり、ファイルを閉じたり (この場合、プログラムの終了時に自動的に行われます) などに拡張する必要があります。

各コンストラクトの役割を知りたい場合は、cppreference.com にアクセスしてください。とても役に立ちました。

// These statements "bring into the program" the "hooks" needed to
// invoque the functionality available in the Standard Library. In C++
// you "only pay for what you use", that is why you should only
// "include" what you need.

// header name        it providest the means to ...
#include<iterator> // "walk through" a thing
#include<iostream> // handle input (i) / output (o) streams
#include<fstream>  // handle file streams
#include<vector>   // handle collections of items

// core entry point to the program
int main() {
  // all data will be read into a collection of integers (in this
  // case, you could have created a collection of any type). Vectors
  // can grow and shrink automatically, and can be traversed
  // (iterated; walked-through) efficiently. There are other
  // "collections" available (list, array, set, queue, stack, etc)
  // each with different capabilities

  std::vector<int> data;

  // create an "input stream" feed from a file called "numbers.txt"
  std::ifstream fp("numbers.txt");

  // copy the contents of the "input stream" to the vector. An
  // "istream_iterator" is simply an "agent" which can "walk through"
  // any "input stream". In this case, "walk through" means "give me
  // integers until there are none". A "back inserter" is an "agent"
  // which can "push back" stuff into a container. In this case it
  // will "push back" integers into a vector; the vector being "data",
  // our container defined above.
  std::copy(std::istream_iterator<int>(fp), // this denotes "start of stream"
            std::istream_iterator<int>(),   // this denodes "end of stream"
            std::back_inserter<std::vector<int>>(data)); // this is
                                                         // where I
                                                         // want to
                                                         // store the
                                                         // copied
                                                         // value

  // now that I have copied all the values of the file into the data
  // vector, I want to copy them again, this time to the screen output
  // (called "cout"). An "ostream iterator" can "walk through"
  // anything that is an "output stream".
  std::copy(data.begin(), // denotes "start of data"
            data.end(),   // denotes "end of data"
            std::ostream_iterator<int>(std::cout, " "));

  // finally --- notice that we do not need the vector at all! We
  // could have copied the input stream directly into the output
  // stream! The statement would be as follows:

  fp.seekg(0); // this tells the "stream" to "go back to the
               // beginning". We need to do this because I already
               // "walked through it", and it is currently at the end.

  std::copy(std::istream_iterator<int>(fp), // this denotes "start of stream"
            std::istream_iterator<int>(),   // this denodes "end of stream"
            std::ostream_iterator<int>(std::cout, " "));

  return 0;
}

コンパイル命令 (gcc 4.8.1 を使用):g++ example.cpp -std=c++11

出力:1 2 3 4 5 5 4 3 2 1 1 2 3 4 5 5 4 3 2 1 1 2 3 4 5

では、ベクトルを使わずにやってみませんか?

#include<iterator>
#include<iostream>
#include<fstream> 

int main() {

  // We can copy the input stream directly into the output stream!  

  std::ifstream fp("numbers.txt");

  std::copy(std::istream_iterator<int>(fp), 
            std::istream_iterator<int>(),
            std::ostream_iterator<int>(std::cout, " "));

  return 0;
}

出力:1 2 3 4 5 5 4 3 2 1 1 2 3 4 5 5 4 3 2 1 1 2 3 4 5

于 2013-09-12T17:19:51.610 に答える