連番ファイルをランダムに読み込む方法
Posted: 2018年12月27日(木) 16:51
同じフォルダに入っている連番ファイル(1.txt,2.txt,・・・100.txt)をランダムに読み込ませたいのですが、どうすればいいのでしょうか?
C++またはCで教えていただけないでしょうか?
C++またはCで教えていただけないでしょうか?
#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;
}
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
単にファイル名を実行時に生成するだけの話ではないのですか?fq47 さんが書きました: ↑6年前同じフォルダに入っている連番ファイル(1.txt,2.txt,・・・100.txt)をランダムに読み込ませたいのですが、どうすればいいのでしょうか?
C++またはCで教えていただけないでしょうか?
すみません。私の勘違いかもしれません。かずま さんが書きました: ↑6年前単にファイル名を実行時に生成するだけの話ではないのですか?
#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言語何でも質問掲示板"でのみ適用される事項
・複数の回答者がいた場合、都合の良い、または自分の気が向いた回答者にだけ返信を書かず、回答をくれた人 全員に対して出来る限りの返信を書きましょう。
・回答者のコメントの中に複数質問があった場合、出来る限りその全てに答えるようにしましょう。
m3908714035 さんが書きました: ↑6年前これでは、ファイル中の単語(空白を含まない文字列)を 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 の値は
行数分少なくなります。
すみません。仰る通りかもしれません。コードの修正等ありがとうございます。
#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;
}
テキストファイルには '\0' がないと考えてgetline をこのようにかずま さんが書きました: ↑6年前#6 の Cプログラムを C++ に書き換えてみました。
ifstream ifs(to_string(a[j]) + ".txt");
if (!ifs) return 1;
data[i] = string(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>());