getsとフラッシュ

バッファのフラッシュが必要な場合と、それをしなかった場合との比較例である。

サンプル #include "stdio.h" #include "stdlib.h" int main() { int i; char str[256]; printf( "【scanf 関数の入力】\n" ); printf( "(例) Shinozaki Ai is charming. など。\n" ); for( i = 0; i < 4; i++ ) { scanf( "%s", str ); printf( "%s\n", str ); } printf("\n"); fflush( stdin ); //gets 関数を使う前に入力バッファをフラッシュする必要がある。 //これがなければ実質的に次のgets関数の実行はスキップされる。 //scanf入力後の「改行」残っていて、それがgetsで入力されたことになるからである。 printf( "【gets 関数の入力】\n" ); printf( "(例) Shinozaki Ai is charming. など。\n" ); gets( str ); printf( "%s\n", str ); printf("\n"); return 0; }

実行例 1
バッファをフラッシュしなかった場合、具体的には「fflush( stdin );」を省略した場合である。
scanfでの入力後[Enter]を押すと、次のgets関数での入力の機会は飛ばされてしまう。


実行例 2
バッファをフラッシュした場合、具体的には「fflush( stdin );」を入れた場合である。
scanfでの入力後[Enter]を押すと、次のgets関数での入力になる。


- 2021/05/20 -


時間の処理/日付の差

「VBAでの時間の処理」でやったこと、すなわち、「1997/11/10」から「2000/01/01」まで何日あるかをやってみよう。

サンプル #include "stdio.h" #include "stdlib.h" #include "time.h" int main() { struct tm st_tm1; struct tm st_tm2; time_t tm1; time_t tm2; double ret; double y_sec = 86400; //1日の秒数 double days; st_tm1.tm_year = 97; st_tm1.tm_mon = 10; st_tm1.tm_mday = 10; st_tm1.tm_hour = 0; st_tm1.tm_min = 0; st_tm1.tm_sec = 0; st_tm2.tm_year = 100; st_tm2.tm_mon = 0; st_tm2.tm_mday = 1; st_tm2.tm_hour = 0; st_tm2.tm_min = 0; st_tm2.tm_sec = 0; tm1 = mktime(&st_tm1); tm2 = mktime(&st_tm2); printf("%s \n", asctime(&st_tm1)); printf("%s \n", asctime(&st_tm2)); //printf("%s \n", ctime(&tm1)); //printf("%s \n", ctime(&tm2)); ret = difftime(tm2, tm1); days = ret / y_sec; printf("両者の間は %d 日\n", (int)days); //printf("両者の間は %f 日\n", days); return 0; } ¶time_base5.cpp

実行例


注意点
この場合、「struct tm* st_tm1;」のようにポインターで宣言して、「st_tm1->tm_year = 97;」として設定(代入)していくことはできない。
ポインターで宣言しても、それがどこを指しているのか不明である。したがってそこに値を設定(代入)しても、ワケのわからないところに何かを代入しただけであるから、意味ある結果は出てこない。
- 2021/05/17 -


VBAでの時間の処理

Excel/VBAでの2つの関数の時間に関する処理である。
さすが「オバカ御用達」だけのことはある。やりたいことがストレートに出てくる。
C/C++でこれと同じことをしようとすると、、、かなり遠大なことになるだろう。

サンプル '▼日付の差 '2 つの指定した日付の時間間隔を指定するVariant(Long)を返す。 Public Sub F_DateDiff() Dim dtStart As Date '開始日付 Dim dtEnd As Date '終了日付 Dim nRet As Long '時間間隔(日数に限らない) dtStart = "1997/11/10" dtEnd = "2000/01/01" nRet = DateDiff("d", dtStart, dtEnd) '戻り値の解釈(yyyy=年, d=日, m=月, h=時, n=分, 以下略) MsgBox nRet '782 End Sub ¶Vba_D_01.bas@Vba1.xlsm


サンプル '▼日付の増減 '指定した時間間隔を日付に加算してその日付を含むVariant(Date)を返す。 Public Sub F_DateAdd() Dim dtPoint As Date '指定日付 Dim dwSpan As Double '時間の間隔(日数に限らない) Dim dtRet As Date dtPoint = "2000/01/01" dwSpan = -782 '基準日より前はマイナス、後はプラスで指定。 '基準日より782日前の日付 dtRet = DateAdd("d", dwSpan, dtPoint) '間隔数値の解釈(yyyy=年, d=日, m=月, h=時, n=分, 以下略) MsgBox dtRet '1997/11/10 End Sub ¶Vba_D_01.bas@Vba1.xlsm

- 2021/05/16 -


時間の処理

gmtime関数は、time_t 型から struct tm 型に時間を変換し、tm 型の構造体へのポインタを返す。
返された構造体は、ローカル時刻ではなく、万国標準時(UTC)である。

サンプル #include "stdio.h" #include "stdlib.h" #include "time.h" int main() { struct tm* st_tm; struct tm* st_tm2; time_t now; time(&now); //現在の時間をnowに取得する。 //万国標準時を取得。 st_tm = gmtime(&now); printf("万国標準時 : %s\n", asctime(st_tm)); //★以下は比較のためのものである。 st_tm2 = localtime(&now); //nowデータをローカル時間に変換しtm構造体にセットする。 printf("現在の時間 : %s \n", asctime(st_tm2)); //引数にtm構造体を使う。 return 0; } ¶time_base4.cpp

実行例


- 2021/05/16 -


時間の処理

時間の作成。

サンプル #include "stdio.h" #include "stdlib.h" #include "time.h" int main() { struct tm* st_tm; //ポインターとして宣言する。 time_t now; time_t ret; int days; time(&now); st_tm = localtime(&now); printf("現在の時間 : %s \n", asctime(st_tm)); printf("現在の時間 : %s \n", ctime(&now)); days = 10; st_tm->tm_mday = st_tm->tm_mday + days; ret = mktime( st_tm ); if(ret != (time_t)-1) printf( "%d 日後の時間 : %s\n", days, asctime(st_tm)); return 0; } ¶time_base2.cpp

実行例


問題点
これからみると、たとえばストレートに「今から782日後」などの時間は作れないことになる。


ポインターとオブジェクト

上の例はtm構造体をポインターとして使ったものである。
このtm構造体をオブジェクトと使うと次のようになる。
実行結果は上とまったく同じである(当然)。

サンプル #include "stdio.h" #include "stdlib.h" #include "time.h" int main() { struct tm st_tm; //オブジェクトとして宣言する。 time_t now; time_t ret; int days; time(&now); st_tm = *localtime(&now); printf("現在の時間 : %s \n", asctime(&st_tm)); printf("現在の時間 : %s \n", ctime(&now)); days = 10; st_tm.tm_mday = st_tm.tm_mday + days; ret = mktime(&st_tm); if(ret != (time_t)-1) printf( "%d 日後の時間 : %s\n", days, asctime(&st_tm)); return 0; } ¶time_base3.cpp


よく使う関数

時間関係でよく使う関数のプロトタイプである。
これらの関数の引数はポインターになっているものが多い。
したがって、これらのデータをオブジェクトとして宣言した場合は、その変数にポインター生成演算子の「&」が必要になる。
- 2021/05/16 -


時間の処理

時間処理の基本ルーチン。
行頭のインデント(タブ)は半角スペース4個だが、スマホでは半角スペースが2個以上連続すると2個に圧縮されるようである。

サンプル #include "stdio.h" #include "stdlib.h" #include "time.h" int main() { struct tm* st_tm; time_t now; time(&now); //現在の時間をnowに取得する。 st_tm = localtime(&now); //nowデータをローカル時間に変換しtm構造体にセットする。 printf("現在の時間 : %s \n", asctime(st_tm)); //引数にtm構造体を使う。 printf("現在の時間 : %s \n", ctime(&now)); //引数にtime_tデータを使う。 return 0; } ¶time_base.cpp

実行例


tm構造体

REFER
time_t は long int である。

struct tm
{
    int   tm_sec;
    //秒 (0 - 59) 

    int   tm_min;
    //分 (0 - 59) 

    int   tm_hour;
    //時間 (0~24) 

    int   tm_mday;
    //日 (1~31) これだけ1起算。 

    int   tm_mon;
    //月 (0~11、1月 = 0) 

    int   tm_year;
    //年 (西暦から1900を引いた値) 

    int   tm_wday;
    //曜日 (0~6、日曜日 = 0) 

    int   tm_yday;
    //年初からの通算日数 (0~365、1月1日 = 0) 

    int   tm_isdst;
    //夏時間が有効な場合は 0 以外の正の値、
    //夏時間が無効な場合は 0、
    //夏時間かどうか不明な場合は負の値。
};

- 2021/05/15 -


変数のローカル性

{ }で囲まれたブロック内で宣言された変数はそのブロック内でのローカル変数になる。

サンプル 1 #include <iostream> using namespace std; int main() { int i=100; i++; cout << i << endl; //101 cout << endl; for(int i=1, n=1 ; i<6 ; i++) { //「int i=1, int n=1」とするとエラーになる。 //nに代入した値は使われていなという警告が出る。 cout << i << endl; //1, 2, 3, 4, 5 n = i+10; cout << n << endl; //11, 12, 13, 14, 15 } cout << endl; //cout << n << endl; //ここでnは参照できない。「未定義のシンボル」エラーになる。 i++; cout << i << endl; //102 cout << endl; { int i=200; cout << i << endl; //200 i+=2; cout << i << endl; //202 } cout << endl; i++; cout << i << endl; //103 cout << endl; { int i=300; cout << i << endl; //300 i+=3; cout << i << endl; //303 } cout << endl; i++; cout << i << endl; //104 }

サンプル 2 #include <iostream> using namespace std; int i = 100; //main内で書くと未定義のシンボルエラーになる。 int main() { cout << i << endl; //100 for(int i=1 ; i<6 ; i++) { cout << i << endl; //1, 2, 3, 4, 5 ::i = i + 10; cout << ::i << endl; //11, 12, 13, 14, 15 } cout << i << endl; //100 }

以下のようなパターンではforループ内でその外側にある同名の変数iにはアクセスできないようである。

サンプル 3 //★ループは1回で終わる。 int main() { int i = 100; cout << i << endl; //100 for(int i=1 ; i<6 ; i++) { cout << i << endl; //1 i = i+10; cout << i << endl; //11 } i++; cout << i << endl; //101 } //★コンパイルエラー int main() { int i = 100; cout << i << endl; for(int i=1 ; i<6 ; i++) { cout << i << endl; ::i = i+10; //未定義のシンボル・エラー cout << ::i << endl; //未定義のシンボル・エラー } i++; cout << i << endl; }

- 2021/02/24 -


阿呆の画廊
ゴミガラクタの世界(2021-01)