• ベストアンサー

曜日を格納する配列の大きさ

細々と半年ほど柴田望洋氏の「明解C言語 入門編」でC言語の勉強をしております。 最近構造体について勉強しはじめ、プログラム実行時の日付を出力するプログラムがテキストに載っていて、以下がその関数です。 void put_date(void) { time_t current; struct tm *local; char wday_name[][3] = { "日", "月", "火", "水", "木", "金", "土" }; /*-- [][3]?? --*/ time(&current); local = localtime(&current); printf("%4d年%02d月%02d日(%s)", local->tm_year + 1900, local->tm_mon + 1, local->tm_mday, wday_name[local->tm_wday]); } これの曜日を格納する配列wday_name[][3]は、どうしてこのような宣言をするのでしょうか? wday_name[][7]にすると何か間違っているのですか? 自分で後者の方で実行してみたところ、特に動作に違いは見られませんでした。 どうぞよろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • yosi_yosi
  • ベストアンサー率35% (165/468)
回答No.1

wday_name[][3] としているのは各曜日をあらわす文字が3つで足りるからです。 漢字1文字でchar2つ分、それに文字列の終わりを示すNULL文字を追加して合計3つです。 wday_name[][7]としても違いが無いのは、7つ分確保して残りの4つ分を利用していないからです。 この宣言を省略せずに書けば、 wday_name[7][3] となります。この場合charが3つ分の領域をもつ配列を7個分確保していることとなります。

whisk
質問者

お礼

素早い回答どうもありがとうございます。 なるほど、3というのは配列の大きさを定義しているのですね。7にしても動作が同じなのは当然ですね。 逆に2以下にした時はちゃんと動作しなかったのもこれで納得がいきました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.6

いっそ char wday_name[][3]= を char *wday_name[]= にする

whisk
質問者

お礼

ポインタの方からアプローチするというやり方もあるんですね。 プログラムとしてはどちらが良いものになるんでしょう? 後者でポインタを駆使してやってみるのも面白そうです。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

質問に対する直接の回答は既に出ていますので、ちょっと異なる視点から書いてみます。 曜日を表す各文字("日"など)が何バイトになるかは処理系に依存します。ですから、より厳密に記述するには、wday_name[][3]ではなく、wday_name[][MB_LEN_MAX+1]としなければなりません。 MB_LEN_MAXは多バイト文字の最大バイト数であり、終端のナル文字のために+1しています。バイト数自体はMB_CUR_MAXでもよいのですが、MB_CUR_MAXは定数式にはならないので配列の要素数には使えません。

whisk
質問者

お礼

なるほど、こちらの方が処理系に依存せずより良いプログラムになりますね。 文字が何バイトになるのかは処理系によって違うというのは驚きました。

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

wday_name[][3]の[3]は、1つの曜日を格納するサイズです。これは、漢字1文字=2バイト+終端NULLの1バイトで、計3バイトとなります。最初の[]は、[7]とかいてもよいですが、要素を宣言された分、コンパイラが確保しますので、[]と記述しても[7][3]と同じ事になります。 たぶん、貴方は、[3]を[7]にしたのは、曜日の数が7だであるからそうしたのでしょうが、[7]にすべきは、 最初の[]であって、2番目の[]ではありません。 もし、[][7]とすると、この場合は、[7][7]と同じ事になります。最初の[7]が要素の数(曜日の数)、2番目の[7]は、最低[3]以上であればよいので、[7]でも正しく動きます。もちろん、[][256]で、問題なく動きます。

whisk
質問者

お礼

はい、どうやら逆に理解をしていたようです。 wday_name[][3]を見た時、「格納する曜日が7つあるのになんで3なんだろう?」と頭をひねっていました。 わかりやすい解説をどうもありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • ddnp009
  • ベストアンサー率25% (15/58)
回答No.3

>char wday_name[][3] この定義は配列の配列。 先頭の[]は、初期化時において配列要素数をコンパイラに数えさせる記述。 後ろの[3]は、本来の型(char)の要素数。 おそらくマルチバイト環境下で曜日を示す漢字(例えば"日")を 格納するのに十分なサイズがchar*2なのでしょう。 2 + 1(0x00) = 3。 つまり、あなたの定義wday_name[][7]は、 3バイトで十分なものを7バイト確保する定義となったに過ぎません。 余分に確保しただけなので動作は変わらないはず。 間違いではないが、無駄。

全文を見る
すると、全ての回答が全文表示されます。
  • PrintScree
  • ベストアンサー率25% (538/2091)
回答No.2

曜日を格納する配列のサイズを3バイトで定義しています。 3を7に変えても変化がないのは、7バイトの領域に曜日が格納されるため動作に変化がないのです。 定義する内容がハッキリしているのなら wday_name[6][3] /* 0~6の7要素 */ としても言いわけです。

whisk
質問者

お礼

そうですね、この場合曜日を格納すると目的がはっきりしているので 最初からwday_name[7][3]という風に定義しても良いですね。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • localtime() 関数についての質問

    C言語の勉強をして間もない者です。 time_t = current; struct tm = *local; time(&current); local = localtime(&current); こんなのがlocaltime関数を使った一般的なプログラムだと思いますが、なぜlocaltimeの引数がcurrentのポインタなのでしょうか? 別にcurrentには値を代入しないのだから、localtime(current)でもいいとおもうのですが、ポインタにした必然的理由があるのでしょうか?

  • Perlでの Timeの足し算

    時間の足し算をやりたい。訳あってライブラリが使えません。 方法は無いでしょうか? 仮にライブラリが使えるなら、下記のようでうまく行っています。 --------------------------------------------------- use Time::Local; $year=2008; $mon =10; $mday=24; $hours = 23; $min = 0; $sec = 0; $time = timelocal($sec, $min, $hours, $mday, $mon - 1, $year); $a1=($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time ); $mytimeORG= sprintf("%04d/%02d/%02d %2d:%2d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytimeORG\n"; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time + 32400); #9H加算 $mytime9H= sprintf("%04d/%02d/%02d %02d:%02d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytime9H\n"; ---------------------------------------------

    • ベストアンサー
    • Perl
  • 時刻取得について

    C言語において時刻取得を以下のようにプログラムしたら、プログラムを3回目以上実行すると前回時間内容が常に1回目が表示されてしまいます。どこを直せばちゃんと前回の時刻が正しく表示されるようになるのでしょうか。put()のfopenの"a"の部分は"w"に変えるだけで正しく実行されるのですが、これを"a"にした場合について正しく表示されるようにするということです。 #include <time.h> #include <stdio.h> void get(void); void put(void); char data_file[] = "time.dat"; int main(void) { get(); put(); return(0); } /* 前回の日付・時刻を読込む   */ void get(void) { FILE *fp; time_t t; struct tm *local; time(&t); local = localtime(&t); if ((fp = fopen(data_file, "r")) == NULL){ printf("\a本プログラムを実行するのは初めて\n"); }else { int year, month, day, h, m, s; fscanf(fp, "%d %d %d", &h, &m, &s); printf("前回は%d時%d分%d秒\n", h, m, s); fclose(fp); } } /* 今回の日付・時刻を書き込む   */ void put(void) { FILE *fp; time_t t; struct tm *local; time(&t); local = localtime(&t); if ((fp = fopen(data_file, "a")) == NULL) printf("\aファイルをオープンできません。\n"); else { printf("現在の日付・時刻を書き出しました。\n"); fprintf(fp, "%d %d %d\n", local->tm_hour, local->tm_min, local->tm_sec ); fclose(fp); } }

  • 勉強しています。力をかしてください。

    #include <stdio.h> #include <string.h> #define MAX_NUMBER 999 /* 最大登録件数 */ #define NAME 20 /* 氏名の文字数 */ #define DATE 9 /* 生年月日の桁数 */ #define ID 4 /* IDの桁数 */ #define INT 8 /* 登録・修正日の桁数 */ typedef struct { /* 社員名簿 */ char ID[NUM]; /* 社員番号 */ char name[NAME]; /* 氏名 */ char birth[DATE]; /* 生年月日 */ int touroku; /* 登録日 */ }syain_data; このような構造体で、 001 abc 20000101 20070911 と、画面表示し、S_data.txtファイルに書き込むようにしようとおもうのですが、以下のところで悩んでます。教えてください。 /* 実行時の日付の表示 */ void put_data(void) { FILE *fp; time_t t; struct tm *local; time(&t); local = localtime(&t); fprintf(fp, "%2d%2d%2d%2d\n", local->tm_year + 1900, local->tm_mon + 1, local->tm_mday); 20070911←の表示のことですが、これをファイルに書き、構造体に書くにはどうすればいいのでしょうか?

  • エラーがわかりません、、

    以下のプログラムを入力したときに以下のえらーがでます。 List13-4.c: In function ‘get_data’: List13-4.c:18: error: expected expression before ‘)’ token 18行目を探すのですが、自力では見つけられません。もしかしたら 別のところが間違っていて18行目がエラーと出ているのかなと思っています。ならいたてですぐにわかるようなミスかもしれないですが、よろしくお願いします。 #include <stdio.h> #include <time.h> char data_file[] = "datetime.data"; void get_data(void) { FILE *fp; if((fp = fopen(data_file,"r")) == NULL){ printf("本プログラムを実行するのは初めてですね\n"); } else{ int year,month,day,h,m,s; fscanf(fp,"%d %d %d %d %d %d",&year,&month,&day,&h,&m,&s); printf("前回は%d年%d月%d日%d時%d分%d秒でした\n",year,month,day,h,m,s,); fclose(fp); } } void put_data(void) { FILE *fp; time_t t; struct tm *local; time(&t); local = localtime(&t); if((fp = fopen(data_file,"w")) == NULL) printf("\aファイルをオープンできません\n"); else{ fprintf(fp,"%d %d %d %d %d %d\n", local->tm_year + 1900,local->tm_mon + 1 ,local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec); fclose(fp); } } int main(void) { get_data(); put_data(); return(0); }

  • Run-Timeエラーの原因に関して教えてください。

    皆様、いつもありがとうございます。 C言語で教えてください。 プログラムを実行すると、下記内容のエラーが発生します。 Run-Time Check Failure #2 - Stack arround the variable 'wk_date' was corrupted 発生場所までは、突き止めましたが、原因が釈然としません。 wk_dateとwk_timeをstaticをつけて定義すると、このエラーが 出ないことから、strcpyの関数でのポインターのトラブル?だと 思うのですが、下記のロジックでおかしい箇所はあるでしょうか? ロジックは、現在の日付と時刻をudateに入れて返すだけです。 static char udate[15]; : : init() { char wk_date[9]; char wk_time[7]; time_t current; struct tm *local; time(&curren;t); /* 現在の時刻を取得 */ local = localtime(&curren;t); /* 地方時の構造体に変換 */ local->tm_year +=1900; local->tm_mon +=1; memset((char*)wk_date, NULL, sizeof(wk_date)); memset((char*)wk_time, NULL, sizeof(wk_time)); sprintf((char*)wk_date, "%04d%02d%02d", local->tm_year, local->tm_mon, local->tm_mday); printf("%s\n", wk_date); sprintf((char*)wk_time, "%02d%02d%02d", local->tm_hour, local->tm_min, local->tm_sec); printf("%s\n", wk_time); memset((char*)udate, NULL, sizeof(udate)); strcpy((char*)udate, strcat((char*)wk_date, (char*)wk_time)); return(0); } 納得のいく、説明を頂ければ幸いです。宜しくお願いいたします。

  • 現在時刻をミリ秒まで取得

    お疲れ様です 現在時刻をミリ秒まで取得がしたいです。 今はtime_tを使って秒までは取得したのですがミリ秒は構造体にないらしく同じようにとってはこれないのでしょうか? また別のやり方だとどんなのがあるか教えてください。 現在は下記のように取得してyyyymmddhhmmssの形を作ってます。 これをyyyymmddhhmmsssssのようにミリ秒を増やしたたいのです。 長くなってしまいましたがよろしくお願いします time_t timer; time(&timer);/* 現在の時刻を取得 */ struct tm *local; local =localtime(&timer);/* 地方時の構造体に変換 */ CString time; //CString用の時間 time.Format("%4d%02d%02d%02d%02d%02d" ,local->tm_year + 1900,/* 年 */ local->tm_mon+1,/*月は0から始まるので1を+*/ local->tm_mday,/* 日 */ local->tm_hour,/* 時 */ local->tm_min,/* 分 */ local->tm_sec);/* 秒 */

  • newとdeleteでのアサート

    C++とViasulC++2003にて、 現在時刻を取得する関数を作成しているのですが、 以下のようなアサートが表示され強制終了してしまいます。 > _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) おそらくnewとdeleteあたりで発生しているのは確かなのですが、 その原因が解らずにこまっています。 どうか、アドバイスをよろしくお願いします。 プログラムのソースは以下の通りです。 #include <time.h> void get_date( int *year, int *mon, int *day, int *week ){ tm *mytime = new tm(); time_t long_time; time( &long_time ); mytime = localtime( &long_time ); *year = mytime->tm_year + 1900; *mon = mytime->tm_mon + 1; *day = mytime->tm_mday; *week = mytime->tm_wday; delete mytime; mytime = NULL; } int main(){ int y, m, d, w; get_date( &y, &m, &d, &w ); }

  • C言語のtime_tに関して

    こんにちは。 今現在、C言語にてプログラミングを行っております。time_tを用いましたが、4月などの2桁目が0のは巧く取得できたのですが、日にちの2桁目が0にならず、空白となってしまいます。 一応、ソースを載せておきますが見辛いのが申し訳ないです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> time_t timer; struct tm *local; struct tm *utc; extern char today[20]; extern char today2[20]; extern char today_year[10]; extern char today_month[2]; extern char today_day[2]; void day(){ char *ptr; /* 現在時刻を取得 */ timer = time(NULL); local = localtime(&timer); /* 地方時に変換 */ /* 地方時 変換後表示 */ printf("地方時: "); printf("%4d/", local->tm_year + 1900); printf("%2d/", local->tm_mon + 1); printf("%2d ", local->tm_mday); if(local->tm_mday<10) //system("pause"); // printf("%2d:", local->tm_hour); // printf("%2d:", local->tm_min); // printf("%2d", local->tm_sec); // printf(" %d\n", local->tm_isdst); /*****************************/ sprintf(today_year,"%4d", local->tm_year + 1900); sprintf(today_month,"%2d", local->tm_mon + 1); sprintf(today_day,"%2d", local->tm_mday); if((local->tm_mon+1)<=9) today_month[0]='0'; if((local->tm_mday+1)<=9) today_day[0]='0'; sprintf(today, "%s-%s-%s", today_year, today_month, today_day); sprintf(today2, "%s/%s/%s", today_year, today_month, today_day); //printf("%s",today); /*****************************/ // utc = gmtime(&timer); /* 協定世界時(UTC)に変換 */ /* 協定世界時 変換後表示 */ // printf("\n\n\n\n協定世界時: "); // printf("%4d/", utc->tm_year + 1900); // printf("%2d/", utc->tm_mon + 1); // printf("%2d ", utc->tm_mday); // printf("%2d:", utc->tm_hour); // printf("%2d:", utc->tm_min); // printf("%2d", utc->tm_sec); // printf(" %d\n", utc->tm_isdst); return; } どなたかご教示下さい。

  • いつもお世話になっております。以下のようなプログラムで現在時刻の表示を

    いつもお世話になっております。以下のようなプログラムで現在時刻の表示をしているわけですが、 #include <stdio.h> #include <time.h> int main(void) { //日付 time_t tmp; struct tm date; time(&tmp); date = *(localtime(&tmp)); printf("現在の時刻:%d-%d-%d %d:%d\n", date.tm_year + 1900 , date.tm_mon + 1 , date.tm_mday , date.tm_hour , date.tm_min); return 0; } このプログラムで動いているので問題は無いのですが、 例えば月・日・時・分が1桁の場合に出力画面が「2010-5-20 14:7」となってしまいます。 個人的には「2010-05-20 14:07」とYYYY-MM-DD HH:MM←(この書き方であってるか不安…) 方式にしたいのですがどのようにすれば良いでしょうか?