同じフォルダに入っている連番ファイル(1.txt,2.txt,・・・100.txt)をランダムに読み込ませたいのですが、どうすればいいのでしょうか?
C++またはCで教えていただけないでしょうか?
連番ファイルをランダムに読み込む方法
-
- 記事: 17
- 登録日時: 5年前
Re: 連番ファイルをランダムに読み込む方法
txtファイルの中身が分からないので、とりあえず1.txtから100.txtまでに1.txtなら1、2.txtなら2、100.txtなら100と記入されていることを前提にプログラムを組んでみました。
code:
これに以下のコードを加えて出力させてみます。
additional code: output:
私はそこまでC++の関数(?)等に詳しくないので、ひたすらググってコードを作成しました。もしかするともっと簡潔に書けるのかもしれませんが参考程度になればと思い、投稿させていただきます。
ちなみに、連番ファイルの作成にあたっては以下のサイトを参考にしましたのでリンクを張っておきます。
[備忘録] C++における連番ファイルの作り方
分からないことあれば質問いただけるとこのプログラムに関してはお答え出来ると思いますので、返信は遅いかもしれませんが気軽にどうぞ。
code:
#include <iostream>
#include <random>
#include <vector>
#include <numeric>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
int main() {
random_device rnd; // 非決定的な乱数生成器
mt19937 mt(rnd()); // 疑似乱数(決定的な乱数)生成器
vector<int> filenumber(100); // 乱数置き場
iota(filenumber.begin(), filenumber.end(), 1); // 配列内を 1~100 までの数字で埋める
shuffle(filenumber.begin(), filenumber.end(), mt); // 疑似乱数生成器を用いてシャッフル
string filename; // ファイル名
stringstream receiver; // ファイル内文字列の受け取り場所
vector<string> data(100); // ファイル内文字列の最終保管場所
for (int i = 0; i < 100; i++) {
receiver.str(""); // バッファをクリア
receiver.clear(stringstream::goodbit); // ストリームの状態をクリア
filename = to_string(filenumber[i]) + ".txt"; // ファイル名指定
ifstream fin(filename); // ファイルの読み込み
if (!fin) { return 1; } // ファイルが読み込めなかった場合エラー
receiver << fin.rdbuf(); // ファイル内文字列をコピー
fin.close(); // ファイルを閉じる
receiver >> data[i]; // ファイル内文字列を保管
}
return 0;
}
additional code: output:
14
61
100
38
88
73
81
64
90
1
15
2
71
6
7
20
63
13
91
84
27
41
5
10
51
99
57
65
58
87
77
89
69
50
67
47
74
8
12
72
85
39
49
44
95
40
35
9
94
26
55
32
83
42
75
36
3
92
25
29
24
45
34
37
52
86
31
17
80
97
98
28
33
23
16
79
21
18
19
76
22
48
43
30
53
60
93
78
59
54
4
82
11
66
46
68
62
96
56
70
ちなみに、連番ファイルの作成にあたっては以下のサイトを参考にしましたのでリンクを張っておきます。
[備忘録] C++における連番ファイルの作り方
分からないことあれば質問いただけるとこのプログラムに関してはお答え出来ると思いますので、返信は遅いかもしれませんが気軽にどうぞ。
-
- 記事: 17
- 登録日時: 5年前
Re: 連番ファイルをランダムに読み込む方法
※追記
今回はランダムに読み込みたいとのことでしたので、読み込むファイルを疑似乱数を用いてランダムにしましたが、差し支えないようなら素直に1.txtから100.txtまでをvector配列に入れてシャッフルしても良いと思います。まあ、シャッフルするのが先か後かという違いだけだとは思いますが…。
今回はランダムに読み込みたいとのことでしたので、読み込むファイルを疑似乱数を用いてランダムにしましたが、差し支えないようなら素直に1.txtから100.txtまでをvector配列に入れてシャッフルしても良いと思います。まあ、シャッフルするのが先か後かという違いだけだとは思いますが…。
Re: 連番ファイルをランダムに読み込む方法
単にファイル名を実行時に生成するだけの話ではないのですか?fq47 さんが書きました: ↑5年前同じフォルダに入っている連番ファイル(1.txt,2.txt,・・・100.txt)をランダムに読み込ませたいのですが、どうすればいいのでしょうか?
C++またはCで教えていただけないでしょうか?
Re: 連番ファイルをランダムに読み込む方法
すみません。私の勘違いかもしれません。かずま さんが書きました: ↑5年前単にファイル名を実行時に生成するだけの話ではないのですか?
100個のファイルのうち、ランダムにどれか一つ読み込めばよいのかと
思っていました。
100個のファイル全部をランダムな順番で読み込むということでしょうか?
それなら、
#include <stdio.h> // sprintf, printf, fopen, fclose, fgets, fputs
#include <stdlib.h> // srand, rand
#include <time.h> // time
#define N 100
int main(void)
{
int a[N], i;
srand(time(0));
for (i = 0; i < N; i++) a[i] = i + 1;
while (i > 0) {
char name[16];
int j = rand() % i;
sprintf(name, "%d.txt", a[j]);
a[j] = a[--i];
FILE *fp = fopen(name, "r");
if (!fp) { printf("can't open %s\n", name); return 1; }
printf("=== %s ===\n", name);
char buf[1024];
while (fgets(buf, sizeof buf, fp))
fputs(buf, stdout);
fclose(fp);
}
}
d. 義務行為
"C言語何でも質問掲示板"でのみ適用される事項
・複数の回答者がいた場合、都合の良い、または自分の気が向いた回答者にだけ返信を書かず、回答をくれた人 全員に対して出来る限りの返信を書きましょう。
・回答者のコメントの中に複数質問があった場合、出来る限りその全てに答えるようにしましょう。
Re: 連番ファイルをランダムに読み込む方法
m3908714035 さんが書きました: ↑5年前これでは、ファイル中の単語(空白を含まない文字列)を 1個しか
読み込めません。ファイル内の文字全部を取得したければ、
data[ i] = receiver.str(); としたほうが良いのではありませんか?
Cプログラムで、ファイルの内容をすべてメモリに読み込みたければ、
次のように書けます。ただし、Windows では、ファイル中の改行は '\r' '\n' の 2文字であり、#include <stdio.h> // sprintf, printf, fopen, fclose, fseek, rewind, fread, puts #include <stdlib.h> // srand, rand, malloc, free #include <time.h> // time #define N 100 int main(void) { int a[N], i, k = 0; char *data[N]; srand(time(0)); for (i = 0; i < N; i++) a[i] = i + 1; while (i > 0) { char name[16]; int j = rand() % i; sprintf(name, "%d.txt", a[j]); a[j] = a[--i]; FILE *fp = fopen(name, "r"); if (!fp) { printf("can't open %s\n", name); return 1; } //printf("=== %s ===\n", name); fseek(fp, 0, SEEK_END); long n = ftell(fp); rewind(fp); data[k] = malloc(n + 1); if (!data[k]) return 2; n = fread(data[k], 1, n, fp); data[k++][n] = '\0'; fclose(fp); } for (i = 0; i < N; i++) puts(data[i]); for (i = 0; i < N; i++) free(data[i]); }
fread がこれを '\n' 1文字に変換するので、fread で n の値は
行数分少なくなります。
-
- 記事: 17
- 登録日時: 5年前
Re: 連番ファイルをランダムに読み込む方法
すみません。仰る通りかもしれません。コードの修正等ありがとうございます。
Re: 連番ファイルをランダムに読み込む方法
#6 の Cプログラムを C++ に書き換えてみました。
#include <iostream> // cout
#include <fstream> // ifstream
#include <string> // to_string, getline
#include <random> // randome_device, mt19937, unifortm_int_distribution
int main(void)
{
using namespace std;
mt19937 mt((random_device())());
const int N = 100;
int a[N];
for (int i = 0; i < N; i++) a[i] = i + 1;
string data[N];
for (int j, i = N; --i >= 0; a[j] = a[i]) {
j = uniform_int_distribution<int>(0, i)(mt);
ifstream ifs(to_string(a[j]) + ".txt");
if (!ifs || !getline(ifs, data[i], '\0')) return 1;
}
for (auto& s : data) cout << s;
}
Re: 連番ファイルをランダムに読み込む方法
テキストファイルには '\0' がないと考えてgetline をこのようにかずま さんが書きました: ↑5年前#6 の Cプログラムを C++ に書き換えてみました。
使いましたが、'\0' があったとしても、とにかくファイル全体を
読み込みたいというのなら、次のように書けます。
ifstream ifs(to_string(a[j]) + ".txt");
if (!ifs) return 1;
data[i] = string(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>());
ランダムに読み込むんだから、これでもいいと思うんですが、
順番に読み込ませたければ、for の先頭に k = 0, を追加し、
data[k++] = にすればよいでしょう。