固定長データ
Posted feedbacks - C++
メモリ上の構造≠ファイル上の構造の前提で書きました。 予想以上にstreamの扱いに苦戦。streamと固定長データは相性が良くない…というより、わたしがstreamを使い切れていないというのが正解かも。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <iterator>
struct Menu
{
std::string date;
std::string breakfast;
std::string lunch;
std::string dinner;
};
typedef std::vector<Menu> Menus;
struct Record
{
public:
std::string lastName;
std::string firstName;
std::string sex;
std::string age;
std::string year;
std::string month;
Menus menus;
};
std::istream& operator >> (std::istream& in, Menu& menu)
{
char s[500];
in.read(s, 2); menu.date = std::string(s, 2);
in.read(s, 500); menu.breakfast = std::string(s, 500);
in.read(s, 500); menu.lunch = std::string(s, 500);
in.read(s, 500); menu.dinner = std::string(s, 500);
return in;
}
std::istream& operator >> (std::istream& in, Record& record)
{
char s[500];
in.read(s, 12); record.lastName = std::string(s, 12);
in.read(s, 12); record.firstName = std::string(s, 12);
in.read(s, 1); record.sex = std::string(s, 1);
in.read(s, 3); record.age = std::string(s, 3);
in.read(s, 4); record.year = std::string(s, 4);
in.read(s, 2); record.month = std::string(s, 2);
std::istream_iterator<Menu> itr(in);
for(int i = 0; i < 31; ++i)
{
record.menus.push_back(*itr++);
}
return in;
}
#include <fstream>
void read(const std::string& filename, std::vector<Record>& records)
{
records.clear();
std::ifstream source(filename.c_str(), std::ios::binary);
std::istream_iterator<Record> itr(source);
for(int i = 0; i < 500; ++i)
{
records.push_back(*itr++);
}
}
// 以下はテストデータを作成するためのコードです。
std::ostream& operator << (std::ostream& out, const Menu& menu)
{
std::ios::fmtflags flags = out.flags();
out.setf(std::ios::left);
out << std::setw(2) << menu.date;
out << std::setw(500) << menu.breakfast;
out << std::setw(500) << menu.lunch;
out << std::setw(500) << menu.dinner;
out.flags(flags);
return out;
}
std::ostream& operator << (std::ostream& out, const Record& record)
{
std::ios::fmtflags flags = out.flags();
out.setf(std::ios::left);
out << std::setw(12) << record.lastName;
out << std::setw(12) << record.firstName;
out << std::setw(1) << record.sex;
out << std::setw(3) << record.age;
out << std::setw(4) << record.year;
out << std::setw(2) << record.month;
out.flags(flags);
for(int i = 0; i < 31; ++i)
{
out << record.menus[i];
}
return out;
}
#include <sstream>
std::string toString(int value, int col)
{
std::stringstream s;
s << std::setfill('0') << std::setw(col) << value;
return s.str();
}
void write(const std::string& filename)
{
Record record;
record.lastName = "LASTNAME";
record.firstName = "Firstname";
record.sex = "U";
record.age = " 99";
record.year = "2008";
record.month = "03";
Menu menu;
menu.breakfast = "breakfast";
menu.lunch = "lunch";
menu.dinner = "dinner";
for(int i = 0; i < 31; ++i)
{
menu.date = toString(i + 1, 2);
record.menus.push_back(menu);
}
std::ofstream file(filename.c_str(), std::ios::binary);
for(int i = 0; i < 500; ++i)
{
file << record;
}
}
|


Mymelo #6060() Rating5/7=0.71
固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。
ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。
以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。
この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。
[ reply ]