C言語で現在時刻の取得方法を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Verse(UEFN), Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
time関数
1 |
time_t time(time_t *tloc); |
time関数とは,現在時刻を秒単位で返す関数です.
返す値は,紀元(Epoch; 1970-01-01 00:00:00()UTC))からの秒数です.
もし引数tlocがNULLでない場合,返り値はtlocが挿すアドレスにも格納されます.
time_t型は,主にlong型(64ビット)をtypedefで定義される型です.
time関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> int main(void) { time_t t; time(&t); printf("%ld\n", t); return 0; } |
実行結果は以下になります.
1631144670と表示されましたが,現在時刻がいつなのかよくわからないですね...
1 2 3 |
$ gcc time.c $ a.out 1631144670 |
そこで,time関数の派生関数を利用すると時刻をユーザにわかりやすく表示できるので,それぞれ紹介していきます.
ctime関数
1 |
char *ctime(const time_t *timep); |
ctime関数は,time_t型のカレンダー時刻timepを引数にとります.
ctime関数の返り値は,静的に確保された文字列へのポインタとなります.
返り値の文字列の最後に改行が挿入されています.
ctime関数の返り値は,日付・時刻関数のいずれかが呼び出されると上書きされる可能性があることに注意して下さい.
ctime関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> int main(void) { time_t t; time(&t); printf("%ld\n", t); printf("%s", ctime(&t)); return 0; } |
実行結果は以下になります.
1631145196の現在時刻が,2021年9月9日(木)の午前8時53分16秒だとわかります.
1 2 3 4 |
$ gcc ctime.c $ a.out 1631145196 Thu Sep 9 08:53:16 2021 |
asctime/localtime/gmtime関数
1 2 3 |
char *asctime(const struct tm *tm); struct tm *localtime(const time_t *timep); struct tm *gmtime(const time_t *timep); |
asctime/localtime/gmtime関数は,ctime関数と同様に時刻に関連する関数です.
asctime関数は,引数tmをctime関数と同じ形式の文字列に変換します.
localtime関数は,カレンダー時刻timepをユーザが指定したタイムゾーン(実行環境のタイムゾーン)での時刻要素別の表現に変換します.
gmtime関数は,カレンダー時刻timepを協定世界時(UTC)での要素別の時刻へ変換します.
asctime関数の返り値は静的に割り当てられた文字列へのポインタ,localtime/gmtime関数の返り値は静的に確保された構造体です.
これらの関数の返り値は,日付・時刻関数のいずれかが呼び出されると上書きされる可能性があることに注意して下さい.
これらの関数で利用されるstruct tm構造体の定義は以下になります.
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 |
struct tm { /* Seconds (0-60). 60 is for leap second. */ int tm_sec; /* Minutes (0-59). */ int tm_min; /* Hours (0-23). */ int tm_hour; /* Day of the month (1-31). */ int tm_mday; /* Month (0-11). */ int tm_mon; /* Year - 1900. */ int tm_year; /* Day of the week (0-6, Sunday = 0). */ int tm_wday; /* Day in the year (0-365, 1 Jan = 0). */ int tm_yday; /* Daylight saving time. * enable if positive, disable if 0; otherwise not available. */ int tm_isdst; }; |
asctime/localtime/gmtime関数のコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> int main(void) { time_t t; time(&t); printf("%ld\n", t); printf("%s", ctime(&t)); printf("%s", asctime(localtime(&t))); printf("%s", asctime(gmtime(&t))); return 0; } |
実行結果は以下になります.
ctime(&t)とasctime(localtime(&t))の結果が同じことがわかります.
また,asctime(gmtime(&t))の結果は 協定世界時(UTC)ですので,私の実行環境の日本標準時(UTC+9)の9時間前になっていることがわかります.
1 2 3 4 5 6 |
$ gcc asctime_localtime_gmtime.c $ a.out 1631157502 Thu Sep 9 12:18:22 2021 Thu Sep 9 12:18:22 2021 Thu Sep 9 03:18:22 2021 |
ctime/asctime/localtime/gmtime関数の返り値の上書き
ctime/asctime/localtime/gmtime関数の返り値が上書きされる可能性があることを説明しましたが,実際に上書きされるのか確認してみましょう.
説明を簡単にするため,ctime/localtime関数のみをピックアップして説明します.
ctime/localtime関数で返り値が上書きされることを確認するコードは以下になります.
まず,25~30行目でtime/ctime/localtime関数を呼び出して値を表示します.
32行目のsleep関数で1秒スリープします.
その後,34~41行目でtime/ctime/localtime関数を再度呼び出しています.
ここで,27,29行目に返り値を代入した変数sとtm,36,39行目に返り値を代入した変数s2とtm2は別物であることに注意して下さい.
つまり,s,tmは返り値を代入した後は更新していません.
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 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> #include <unistd.h> void print_tm(struct tm *tm) { printf("tm->tm_sec = %d, tm->tm_min = %d tm->tm_hour = %d\n", tm->tm_sec, tm->tm_min, tm->tm_hour); printf("tm>tm_mday = %d, tm->tm_mon = %d, 1900 + tm->tm_year = %d\n", tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); printf("tm->tm_wday = %d, tm->tm_yday = %d, tm->tm_isdst = %d\n", tm->tm_wday, tm->tm_yday, tm->tm_isdst); } int main(void) { time_t t, t2; char *s, *s2; struct tm *tm, *tm2; time(&t); printf("t = %ld\n", t); s = ctime(&t); printf("s = %s", s); tm = localtime(&t); print_tm(tm); sleep(1); time(&t2); printf("t2 = %ld\n", t2); s2 = ctime(&t2); printf("s2 = %s", s2); printf("s = %s", s); tm2 = localtime(&t2); print_tm(tm2); print_tm(tm); return 0; } |
実行結果は以下になります.
4行目のsの値と10行目のsの値が異なることがわかります.10行目のsの値は9行目のs2の値と同じく1秒後になっています.
print_tm関数の表示結果も同様です.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ gcc time_overwrite.c $ a.out t = 1631165471 s = Thu Sep 9 14:31:11 2021 tm->tm_sec = 11, tm->tm_min = 31 tm->tm_hour = 14 tm>tm_mday = 9, tm->tm_mon = 8, 1900 + tm->tm_year = 2021 tm->tm_wday = 4, tm->tm_yday = 251, tm->tm_isdst = 0 t2 = 1631165472 s2 = Thu Sep 9 14:31:12 2021 s = Thu Sep 9 14:31:12 2021 tm->tm_sec = 12, tm->tm_min = 31 tm->tm_hour = 14 tm>tm_mday = 9, tm->tm_mon = 8, 1900 + tm->tm_year = 2021 tm->tm_wday = 4, tm->tm_yday = 251, tm->tm_isdst = 0 tm->tm_sec = 12, tm->tm_min = 31 tm->tm_hour = 14 tm>tm_mday = 9, tm->tm_mon = 8, 1900 + tm->tm_year = 2021 tm->tm_wday = 4, tm->tm_yday = 251, tm->tm_isdst = 0 |
ctime_r/asctime_r/localtime_r/gmtime_r関数
1 2 3 4 |
char *ctime_r(const time_t *timep, char *buf); char *asctime_r(const struct tm *tm, char *buf); struct tm *localtime_r(const time_t *timep, struct tm *result); struct tm *gmtime_r(const time_t *timep, struct tm *result); |
ctime_r/asctime_r/localtime_r/gmtime_r関数は,第2引数のbuf/result(ユーザが確保したバッファや構造体)に結果を格納するリエントラント関数です.
※bufのサイズは26バイト以上が必要なことに注意して下さい.
これらの関数により,ctime/asctime/localtime/gmtime関数の返り値を上書きされないようにすることが可能になります.
結果として,デバッグしやすいコードを書くことができますので,基本的にはこれらの関数を利用しましょう.
ctime_r/asctime_r/localtime_r/gmtime_r関数を利用するコードは以下になります.
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 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> #define BUFSIZE 32 void print_tm(struct tm *tm) { printf("tm->tm_sec = %d, tm->tm_min = %d tm->tm_hour = %d\n", tm->tm_sec, tm->tm_min, tm->tm_hour); printf("tm>tm_mday = %d, tm->tm_mon = %d, 1900 + tm->tm_year = %d\n", tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); printf("tm->tm_wday = %d, tm->tm_yday = %d, tm->tm_isdst = %d\n", tm->tm_wday, tm->tm_yday, tm->tm_isdst); } int main(void) { time_t t; char s[BUFSIZE]; struct tm tm; time(&t); printf("%ld\n", t); ctime_r(&t, s); printf("%s", s); localtime_r(&t, &tm); print_tm(&tm); gmtime_r(&t, &tm); print_tm(&tm); return 0; } |
実行結果は以下になります.
1 2 3 4 5 6 7 8 9 10 |
$ gcc time_r.c $ a.out 1631166934 Thu Sep 9 14:55:34 2021 tm->tm_sec = 34, tm->tm_min = 55 tm->tm_hour = 14 tm>tm_mday = 9, tm->tm_mon = 8, 1900 + tm->tm_year = 2021 tm->tm_wday = 4, tm->tm_yday = 251, tm->tm_isdst = 0 tm->tm_sec = 34, tm->tm_min = 55 tm->tm_hour = 5 tm>tm_mday = 9, tm->tm_mon = 8, 1900 + tm->tm_year = 2021 tm->tm_wday = 4, tm->tm_yday = 251, tm->tm_isdst = 0 |
mktime関数
1 |
time_t mktime(struct tm *tm); |
mktime関数は,引数で指定したtmの(ローカルタイムで記述されている)要素別の時刻をカレンダー時刻に変換する関数です.
ここで,tm_wdayとtm_ydayで指定された値は無視されるので注意して下さい.
mktime関数を利用するコードは以下になります.
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 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> void print_tm(struct tm *tm) { printf("tm->tm_sec = %d, tm->tm_min = %d tm->tm_hour = %d\n", tm->tm_sec, tm->tm_min, tm->tm_hour); printf("tm>tm_mday = %d, tm->tm_mon = %d, 1900 + tm->tm_year = %d\n", tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); printf("tm->tm_wday = %d, tm->tm_yday = %d, tm->tm_isdst = %d\n", tm->tm_wday, tm->tm_yday, tm->tm_isdst); } int main(void) { time_t t; struct tm *tm; time(&t); printf("%ld\n", t); tm = localtime(&t); print_tm(tm); t = mktime(tm); printf("%ld\n", t); return 0; } |
実行結果は以下になります.
1 2 3 4 5 6 7 |
$ gcc mktime.c $ a.out 1631162732 tm->tm_sec = 32, tm->tm_min = 45 tm->tm_hour = 13 tm>tm_mday = 9, tm->tm_mon = 8, 1900 + tm->tm_year = 2021 tm->tm_wday = 4, tm->tm_yday = 251, tm->tm_isdst = 0 1631162732 |
strftime関数
1 |
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm); |
strftime関数は,要素別の時刻tmの内容をformatで指定された書式指定子で変換し,長さmaxの文字列sに書き込む関数です.
例えば,RFC 2822準拠の日付形式は以下になります.
1 |
"%a, %d %b %Y %T %z" |
strftime関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <time.h> #define BUFSIZE 32 #define RFC_2822 "%a, %d %b %Y %T %z" int main(void) { time_t t; struct tm *tm; char s[BUFSIZE]; time(&t); tm = localtime(&t); strftime(s, sizeof(s), RFC_2822, tm); printf("%s\n", s); return 0; } |
実行結果は以下になります.
1 2 3 |
$ gcc strftime.c $ a.out Thu, 09 Sep 2021 15:31:43 +0900 |
dateコマンドでRFC 2822準拠のオプション(--rfc-2822)を設定した結果と同じになることがわかります.
1 2 |
$ date --rfc-2822 Thu, 09 Sep 2021 15:32:06 +0900 |
廃止予定:gettimeofday/settimeofday関数
1 2 |
int gettimeofday(struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv, const struct timezone *tz); |
gettimeofday/settimeofday関数は,時刻を取得/設定する関数です.
struct timeval/struct timezone構造体の定義は以下になります.
※struct timezone構造体の利用は廃止予定とされています.
1 2 3 4 5 6 7 8 9 |
struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of DST correction */ }; |
settimeofday関数を実行するためには,管理者権限が必要なことに注意して下さい.
POSIX.1-2008ではgettimeofday関数は廃止予定ですので(settimeofday関数もおそらく同様),代わりにclock_gettime/clock_settme関数の利用が推奨されています.
つまり,getimeofday/settimeofday関数は使わない方が良いですが,古いコードで利用されていることがありますので,簡単な使い方を紹介していきます.
gettimeofday関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> #include <sys/time.h> int main(void) { struct timeval tv; gettimeofday(&tv, NULL); printf("tv.tv_sec = %ld, tv.tv_usec = %ld\n", tv.tv_sec, tv.tv_usec); printf("localtime() = %s", asctime(localtime(&tv.tv_sec))); return 0; } |
実行結果は以下になります.
正しく時刻を取得できていることがわかります.
1 2 3 4 |
$ gcc gettimeofday.c $ a.out tv.tv_sec = 1631173137, tv.tv_usec = 618467 localtime() = Thu Sep 9 16:38:57 2021 |
settimeofday関数を利用するコードは以下になります.
14行目のgettimeofday関数で現在時刻を取得し,16行目で60 * 60秒(=3,600秒=60分=1時間)を足します.
18行目のsettimeofday関数で1時間後に時刻を設定します.
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 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/time.h> int main(void) { struct timeval tv; gettimeofday(&tv, NULL); printf("tv.tv_sec = %ld, tv.tv_usec = %ld\n", tv.tv_sec, tv.tv_usec); printf("localtime() = %s", asctime(localtime(&tv.tv_sec))); tv.tv_sec += 60 * 60; printf("tv.tv_sec = %ld, tv.tv_usec = %ld\n", tv.tv_sec, tv.tv_usec); if (settimeofday(&tv, NULL) != 0) { perror("settimeofday"); exit(1); } gettimeofday(&tv, NULL); printf("tv.tv_sec = %ld, tv.tv_usec = %ld\n", tv.tv_sec, tv.tv_usec); printf("localtime() = %s", asctime(localtime(&tv.tv_sec))); return 0; } |
管理者権限なしでの実行結果は以下になります.
settimeofday.cの20行目のperror関数が呼び出されて,「settimeofday: Operation not permitted」が表示されていることがわかります.
1 2 3 4 5 6 |
$ gcc settimeofday.c $ a.out tv.tv_sec = 1631173166, tv.tv_usec = 98276 localtime() = Thu Sep 9 16:39:26 2021 tv.tv_sec = 1631176766, tv.tv_usec = 98276 settimeofday: Operation not permitted |
管理者権限あり(sudoコマンドを利用)の実行結果は以下になります.
日付が1時間後に設定されていることがわかります.
この更新された日付はプログラム中では有効ですが,プログラムが終了した後は元の日付に戻ることに注意して下さい.
1 2 3 4 5 6 7 |
$ gcc settimeofday.c $ sudo ./a.out tv.tv_sec = 1631173182, tv.tv_usec = 927611 localtime() = Thu Sep 9 16:39:42 2021 tv.tv_sec = 1631176782, tv.tv_usec = 927611 tv.tv_sec = 1631176782, tv.tv_usec = 928181 localtime() = Thu Sep 9 17:39:42 2021 |
clock_gettime/clock_settime関数
1 2 |
int clock_gettime(clockid_t clk_id, struct timespec *tp); int clock_settime(clockid_t clk_id, const struct timespec *tp); |
clock_gettime/clock_settime関数は,指定されたクロックの時間を取得/設定する関数で,gettimeofday/settimeofday関数の代わりとして推奨されています.
時刻を取得/設定する場合は,clk_idにCLOCK_REALTIMEを設定します.
struct timespec構造体の定義は以下になります.
struct timespec構造体とstruct timeval構造体との違いは,ナノ秒を管理するtv_nsecとマイクロ秒を管理するtv_usecをそれぞれ持つことです.
1 2 3 4 |
struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; |
clock_gettime関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <time.h> int main(void) { struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); printf("tp.tv_sec = %ld, tp.tv_nsec = %ld\n", tp.tv_sec, tp.tv_nsec); printf("localtime() = %s", asctime(localtime(&tp.tv_sec))); return 0; } |
実行結果は以下になります.
gettimeofday関数の場合と同様です.
1 2 3 4 |
$ gcc clock_gettime.c $ a.out tp.tv_sec = 1631173241, tp.tv_nsec = 226164108 localtime() = Thu Sep 9 16:40:41 2021 |
clock_settime関数を利用するコードは以下になります.
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 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); printf("tp.tv_sec = %ld, tp.tv_nsec = %ld\n", tp.tv_sec, tp.tv_nsec); printf("localtime() = %s", asctime(localtime(&tp.tv_sec))); tp.tv_sec += 60 * 60; printf("tp.tv_sec = %ld, tp.tv_nsec = %ld\n", tp.tv_sec, tp.tv_nsec); if (clock_settime(CLOCK_REALTIME, &tp) != 0) { perror("clock_settime"); exit(1); } clock_gettime(CLOCK_REALTIME, &tp); printf("tp.tv_sec = %ld, tp.tv_nsec = %ld\n", tp.tv_sec, tp.tv_nsec); printf("localtime() = %s", asctime(localtime(&tp.tv_sec))); return 0; } |
管理者権限なしでの実行結果は以下になります.
settimeofday関数の場合と同様です.
1 2 3 4 5 6 |
$ gcc clock_settime.c $ a.out tp.tv_sec = 1631173312, tp.tv_nsec = 849864051 localtime() = Thu Sep 9 16:41:52 2021 tp.tv_sec = 1631176912, tp.tv_nsec = 849864051 clock_settime: Operation not permitted |
管理者権限あり(sudoコマンドを利用)の実行結果は以下になります.
こちらも同様です.
1 2 3 4 5 6 7 |
$ gcc clock_settime.c $ sudo ./a.out tp.tv_sec = 1631173342, tp.tv_nsec = 570797494 localtime() = Thu Sep 9 16:42:22 2021 tp.tv_sec = 1631176942, tp.tv_nsec = 570797494 tp.tv_sec = 1631176942, tp.tv_nsec = 571265814 localtime() = Thu Sep 9 17:42:22 2021 |
まとめ
C言語のtime関数で現在時刻の取得方法を紹介しました.
time関数には様々な派生関数がありますので,使いこなせるようにしましょう.
プログラムの実行時間の計測方法を学びたいあなたは,こちらの記事を読みましょう.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!