まえがき
自分のために作ったのですが、
使ってて結構気持ちいいので記事にしました。
一番下に本体があるのでコピペして使ってください。
どんな感じか
例えばグラフだと、
//N
//An Bn
3
1 2
2 3
1 3
これを読もうとするコードはこんな感じになると思うんですけど結構冗長ですよね。
struct Edge{
long a, b;
}
long N;
readf("%d", N);
Edge[] edges;
foreach(i;0..N){
long x, y;
readf("%d %d", x, y);
edges ~= Edge(x, y);
}
このライブラリを使うとこんな感じで読めます。
struct Edge{
long a, b;
}
auto N = scanElem;
Edge[] edges = scanElem!Edge(N);
機能
空白区切りで1つずつ読んでいきます
改行などもいい感じに処理してくれます
T scanElem!(T=long)
T[] scanElem!(T=long)(long size)
T scanElem(T)()if(is(T==struct))
Tuple!List[] scanElem(List...)(long size)
Tuple!List scanElem(List...)()
テンプレートに型を渡します。
構造体を渡すとメンバーを上から順番に読んでくれます。
構造体が入れ子になっていても再帰的に読んでいきます。
複数渡すとタプルにして返します。
scanElemの引数に読み込む個数を渡すと配列にいれてくれます。
引数なしならそのまま1つです。
例
文字列も取れます
//N
//NAMEn AGEn
3
harusann2 22
nako 3
tako 1
void main(){
struct User{
string name;
long age;
}
long N = scanElem;
User[] users = scanElem!User(N);
}
入れ子にも出来ます
//N
//Xn Yn Rn
2
1.2 2 0.3
3.8 4.2 0.9
void main(){
struct Vector{
real x, y;
}
struct Cicle{
Vector pos;
real r;
}
long N = scanElem;
Cicle[] cicle = scanElem!Cicle(N);
}
タプル
1 2
void main(){
Tuple!(long,long) HW = scanElem!(long,long);
}
本体
コピペして使ってください
T[] scanElem(T=long)(long size)
{
T[] list = new T[size];
foreach(i;0..size)
{
list[i] = scanElem!T;
}
return list;
}
T scanElem(T)()
if(is(T==struct))
{
T res;
foreach(ref field; res.tupleof){
field = scanElem!(typeof(field));
}
return res;
}
Tuple!List[] scanElem(List...)(long size)
{
auto list = new Tuple!List[size];
foreach(i;0..size)
{
list[i] = scanElem!List;
}
return list;
}
Tuple!List scanElem(List...)()
{
List res;
foreach(i, e; List){
res[i] = scanElem!e;
}
return tuple(res);
}
T scanElem(T = long)()
if(isBasicType!T||isSomeString!T)
{
import core.stdc.stdlib;
static auto scanBuf = appender!(char[])([]);
scanBuf.clear;
int c = ' ';
while (isWhite(c) && c != -1)
{
c = getchar;
}
while (!isWhite(c) && c != -1)
{
scanBuf ~= cast(char) c;
c = getchar;
}
return scanBuf.data.to!T;
}