C言語関係掲示板

過去ログ

No.1318 カレンダーの配列

[戻る] [ホームページ]
No.17481

カレンダーの配列
投稿者---AAA(2004/10/24 13:45:30)


カレンダーの表示の仕方で悩んでいます。
配列の表示の仕方がよく理解できていないのでそこを詳しく教えてください。月を3×4で表示がしたいです。途中まで作ってみましたが・・・

#include <stdio.h>

void print_calendar( int num_days, int youbi )
{
int i;
int d;
int x;
for ( i = 0; i < ( youbi * 3 ); i++ ) {
printf( " " );
}
d = 1;
x = youbi;
do {
printf( "%2d ", d );
d++;
if ( x == 6 ) {
printf( "\n" );
x = 0;
}
else {
x++;
}
} while ( d <= num_days );
return;
}

int num_of_day( int y, int m)
{
int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ( ( m == 2 ) && (((y % 400) == 0) || (((y % 100) != 0) && ((y % 4) == 0)))){
return 29;
}
else {
return num_days[m-1];
}
}

int zeller( int y, int m, int d )
{
if ( ( m == 1 ) || ( m == 2 ) ) {
y = y - 1;
m = m + 12;
}
return (y + (y/4) - (y/100) + (y/400) + ((13 * m + 8 ) / 5)+ d) % 7;
}
int first_day( int y, int m )
{
return zeller( y, m, 1 );
}
main()
{
int t,r,e;
int calendar[12][7][6];//12は月、7は1週間、6は最大の週//
int y;
int m;
printf( "カレンダーを表示する年を入力してください " );
scanf( "%d", &y );
for(t=0;t<12;t++){
for(e=0;e<6;e++){
for(r=0;r<7;r++){
calendar[t][r][e];
}
}
}
printf("%35d年\n\n", y);
for(m=1;m<=12; m += 3){
printf("%10d月%21d月%21d月\n""日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土\n",m,m+1,m+2);
print_calendar( num_of_day(y, m), first_day(y, m) );
printf("\n\n");
}
return 0;
}


No.17482

Re:カレンダーの配列
投稿者---かずま(2004/10/24 17:00:29)


> カレンダーの表示の仕方で悩んでいます。

それ以前に、プログラムの投稿の仕方で悩んでください。
【掲示板ご利用上の注意】を読めば悩むことはないはずですが。


> 配列の表示の仕方がよく理解できていないのでそこを詳しく教えてください。
> 月を3×4で表示がしたいです。途中まで作ってみましたが・・・

この掲示板の過去ログ No.505 でも見て研究してください。


No.17483

Re:カレンダーの配列
投稿者---AAA(2004/10/24 17:37:12)


すみませんでした。読んでいませんでした。
505を見させていただきましたが
どうも配列の出力が理解できないです。
例えばこのプログラムだとどのようになるのでしょうか?
#include <stdio.h>

void print_calendar( int num_days, int youbi )
{
    int i;
    int d; 
    int x;
    for ( i = 0; i < ( youbi * 3 ); i++ ) {
        printf( " " );
    }
    d = 1;
    x = youbi; 
    do { 
        printf( "%2d ", d );
        d++;
        if ( x == 6 ) {
            printf( "\n" );
            x = 0;
        }
        else {
            x++;
        }
    } while ( d <= num_days ); 
    return;
}

int num_of_day( int y, int m)
{
    int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if ( ( m == 2 ) && (((y % 400) == 0) ||  (((y % 100) != 0) && ((y % 4) == 0)))){
        return 29;
    }
    else {
        return num_days[m-1];
    }
}

int zeller( int y, int m, int d )
{
    if ( ( m == 1 ) || ( m == 2 ) ) {
        y = y - 1; 
        m = m + 12;
    }
    return (y + (y/4) - (y/100) + (y/400) + ((13 * m + 8 ) / 5)+ d) % 7; 
}
int first_day( int y, int m )
{
    return zeller( y, m, 1 );
}
main()
{
    int t,r,e,w;
    int calendar[12][7][6];//12は月、7は1週間、6は最大の週//
    int y;
    int m;
    printf( "カレンダーを表示する年を入力してください. " );
    scanf( "%d", &y );
    for(t=0;t<12; t++){
        for(e=0;e<6;e++){
            for(r=0;r<7;r++){
                calendar[t][r][e];
                }
        }
    }

    printf("%35d年\n\n", y);
    for(m=1;m<=12; m += 3){
    printf("%10d月%21d月%21d月\n""日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土\n",m,m+1,m+2);
    for (e = 0; e < 6; e++)
            for (w = -1; w < 2; w++) {
                for (r = 0; r < 7; r++)
                    printf(calendar[m+w][r][e] ? "%3d" : "   ", calendar[m+w][r][e]);
                printf(w==1 ? "\n" : "   ");
            }
    print_calendar( num_of_day(y, m), first_day(y, m) );
    printf("\n\n");
    }
    return 0;
}



No.17485

Re:カレンダーの配列
投稿者---AAA(2004/10/24 18:08:46)


間違えてました。こちらを変化させてほしいです。
カレンダー表示なのでやはり配列の表示がよくわからないです。
#include <stdio.h>

void print_calendar( int num_days, int youbi )
{
    int i;
    int d; 
    int x;
    for ( i = 0; i < ( youbi * 3 ); i++ ) {
        printf( " " );
    }
    d = 1;
    x = youbi; 
    do { 
        printf( "%2d ", d );
        d++;
        if ( x == 6 ) {
            printf( "\n" );
            x = 0;
        }
        else {
            x++;
        }
    } while ( d <= num_days ); 
    return;
}

int num_of_day( int y, int m)
{
    int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if ( ( m == 2 ) && (((y % 400) == 0) ||  (((y % 100) != 0) && ((y % 4) == 0)))){
        return 29;
    }
    else {
        return num_days[m-1];
    }
}

int zeller( int y, int m, int d )
{
    if ( ( m == 1 ) || ( m == 2 ) ) {
        y = y - 1; 
        m = m + 12;
    }
    return (y + (y/4) - (y/100) + (y/400) + ((13 * m + 8 ) / 5)+ d) % 7; 
}
int first_day( int y, int m )
{
    return zeller( y, m, 1 );
}
main()
{
    int t,r,e,w;
    int calendar[12][7][6];//12は月、7は1週間、6は最大の週//
    int y;
    int m;
    printf( "カレンダーを表示する年を入力してください. " );
    scanf( "%d", &y );
    for(t=0;t<12; t++){
        for(e=0;e<6;e++){
            for(r=0;r<7;r++){
                calendar[t][r][e];
                }
        }
    }

    printf("%35d年\n\n", y);
    for(m=1;m<=12; m += 3){
    printf("%10d月%21d月%21d月\n""日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土\n",m,m+1,m+2);
    print_calendar( num_of_day(y, m), first_day(y, m) );
    printf("\n\n");
    }
    return 0;
}



No.17486

Re:カレンダーの配列
投稿者---かずま(2004/10/24 19:09:28)


> カレンダー表示なのでやはり配列の表示がよくわからないです。

配列の内容を表示するには、まず、配列 calendar[12][6][7] にカレンダーの
データを作らないといけません。質問のプログラムではそれを作っていません。

次に表示ですが、作った配列を print_calendar に渡さないと表示できません。
3か月まとめて表示するのですから、3か月の先頭のアドレスを渡してやります。
#include <stdio.h>

void print_calendar(int calendar[][6][7])
{
    int e, t, r;

    for (e = 0; e < 6; e++) {
        for (t = 0; t < 3; t++) {
            for (r = 0; r < 7; r++)
                if (calendar[t][e][r])
                    printf("%2d ", calendar[t][e][r]);
                else
                    printf("   ");
            printf("   ");
        }
        printf("\n");
    }
    printf("\n");
}

int num_of_day(int y, int m)
{
    int num_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    if (m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
        return 29;
    return num_days[m - 1];
}

int zeller(int y, int m, int d)
{
    if (m <= 2) {
        y--;
        m += 12;
    }
    return (y + y/4 - y/100 + y/400 + (13*m + 8)/5 + d) % 7;
}

int first_day(int y, int m)
{
    return zeller(y, m, 1);
}

int main(void)
{
    int calendar[12][6][7] = { 0 };    //12は月、6は最大の週、7は 1週間
    int y, m, d, e, num_days, youbi;

    printf("カレンダーを表示する年を入力してください. ");
    scanf("%d", &y);

    for (m = 1; m <= 12; m++) {
        num_days = num_of_day(y, m);
        youbi = first_day(y, m);
        e = 0;
        for (d = 1; d <= num_days; d++) {
            calendar[m-1][e][youbi] = d;
            if (++youbi == 7) {
                youbi = 0;
                e++;
            }
        }
    }

    printf("%35d年\n\n", y);
    for (m = 1; m <= 12; m += 3) {
        printf("%10d月%21d月%21d月\n"     "日 月 火 水 木 金 土  "
               "日 月 火 水 木 金 土  " "日 月 火 水 木 金 土\n",
            m, m + 1, m + 2);
        print_calendar(&calendar[m-1]);
    }
    return 0;
}



No.17487

Re:カレンダーの配列
投稿者---AAA(2004/10/24 19:34:22)


丁寧な解説ありがとうございます。
確認なんですが
 for (e = 0; e < 6; e++) {
        for (t = 0; t < 3; t++) {
            for (r = 0; r < 7; r++)
                if (calendar[t][e][r])
                    printf("%2d ", calendar[t][e][r]);
                else
                    printf("   ");
            printf("   ");
        }
        printf("\n");
    }


このプログラムは表示する時に3ヶ月ごとにするためtがt = 0; t < 3; t++になるんですよね?



 for (m = 1; m <= 12; m++) {
        num_days = num_of_day(y, m);
        youbi = first_day(y, m);
        e = 0;
        for (d = 1; d <= num_days; d++) {
            calendar[m-1][e][youbi] = d;
            if (++youbi == 7) {
                youbi = 0;
                e++;
            }
        }
    }



あとこのプログラムはdが1からその月の最後まで表示するプログラムで
youbiが7になったらyoubiを0にしてeを1繰上げるプログラムですよね?
それと3次元関数のところでなぜm-1になるのかがわからないのですが・・・どういうことでしょう?



No.17574

Re:カレンダーの配列
投稿者---かずま(2004/10/27 22:45:14)


> このプログラムは表示する時に3ヶ月ごとにするためtがt = 0; t < 3; t++になるんですよね?

そうです。


> あとこのプログラムはdが1からその月の最後まで表示するプログラムで

いいえ、表示はしません。配列 calendar に値を設定しているだけです。


> youbiが7になったらyoubiを0にしてeを1繰上げるプログラムですよね?

そうです。


> それと3次元関数のところでなぜm-1になるのかがわからないのですが・・・
> どういうことでしょう?

3次元関数ではなく、3次元配列ですね。m は、月ですから、1〜12 です。
1月のデータは calendar[0] に、12月のデータは calendar[11] に入ります。


No.17701

Re:カレンダーの配列
投稿者---AAA(2004/11/01 22:16:25)


ありがとうございました。
今回はカレンダー&スケジュールにしようと思ってます。
一ヶ月の予定を入れてそれを出力するプログラムを。
例えば1日に飲み会、5日に会議とかを。
それと毎週確実な行事は曜日指定で出力したいのですが、
その方法が思いつきません。
やり方は上のプログラムを変化して2次元配列で
数字と文字を交互に出力したいのですが・・・
アドバイスをお願いします。


No.17708

Re:カレンダーの配列
投稿者---AAA(2004/11/02 02:21:25)


このプログラムを変化させようと思います。
日付の間にスペースはできたのですが行事をいれる事が全然思いつきません。アドバイスお願いします。
#include <stdio.h>

void print(int ca[12][24][7])        
{
    int a,b,c;

    for(a=0;a<24;a++){
        for(b=0;b<1;b++){                       
            for(c=0;c<7;c++){
                if(ca[b][a][c]){
                    printf("%9d ", ca[b][a][c]);    //配列に関係するときその数字を入力
                }
                else{
                    printf("          ");                       //それ以外の時はスペース
                }
            }
                printf("   ");
        }
            printf("\n");
    }
        printf("\n");
}
int number(int y,int m){
        int days[]={31,28,31,30,31,30,31,31,30,31,30,31};

        if(m==2 && y%4==0 && (y%100 != 0 || y%400==0)){          //うるう年の計算
            return 29;
        }
        else{
            return days[m-1];                               //うるう年以外の2月の表示28
        }
}
int nissu(int y,int m,int d){
        if(m<=2){
            y--;
            m +=12;
        }
            return (y+y/4-y/100+y/400+(13*m+8)/5+d)%7;
}
int first(int y,int m){
        return nissu(y,m,1);
}

int main(void)
{
        int ca[12][24][7]={0};
        int y,m,d,e,days,youbi;
        printf("カレンダーを表示する年を入力 :  ");
        scanf("%d",&y);
        printf("カレンダーを表示する月を入力 : ");
        scanf("%d",&m);
            days=number(y,m);
            youbi = first(y,m);
            e=0;                                       //最初の数値を0とし、日数は1からその月の最大
            for(d=1;d<=days;d++){                  //までいき、それを配列と連結させて、youbiが7に
                ca[m-1][e][youbi] = d;           //なったらyoubiを0に戻し、eを追加する
                if(++youbi == 7){
                    youbi =0;
                    e +=4;
                }
            }
            
        printf("%30d月\n""       日     月     火     水     木     金     土\n",m);
            print(&ca[m-1]);
        
        return 0;
}








No.17742

Re:カレンダーの配列
投稿者---かずま(2004/11/03 16:57:19)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define SCHEDULE_FILE  "schedule.txt"

int  cal[6][7];
char *msg[12][31+1];
char *w_msg[7];

int dayofweek(int y, int m, int d)
{
    static int t[] = { 0, 3, 2, 5, 7, 3, 5, 1, 4, 6, 2, 4 };
    y -= m < 3;
    return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}

int days(int y, int m)
{
    static int t[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    return t[m-1] + (m==2 && y/4==0 && (y/100!=0 || y/400==0));
}

void read_schedule(int year)
{
    char buf[256], dow[256], c, *p;
    int y = year, m, d, n;
    FILE *fp = fopen(SCHEDULE_FILE, "r");
    if (fp == NULL) return;

    while (fgets(buf, sizeof buf, fp)) {
        if (p = strchr(buf, '\n')) *p = '\0';
        if (sscanf(buf, "%d %c", &m, &c) == 1)
            y = m;
        else if (sscanf(buf, "%d%*c%d %n%c", &m, &d, &n, &c) == 3) {
            if (y == year && m>=1 && m<=12 && d>=1 && d<=31)
                msg[m-1][d] = strdup(buf + n);
        }
        else if (sscanf(buf, "%s %n%c", dow, &n, &c) == 2) {
            static char w[] = "日月火水木金土";
            dow[2] = '\0';
            p = strstr(w, dow);
            if (p) w_msg[(p - w)/2] = strdup(buf + n);
        }
    }
    fclose(fp);
}

void print(int y, int m)
{
     int row, w, d;  char *s;

    printf("%35d 年  %2d 月\n\n 日         月         火         水"
           "         木         金         土\n\n", y, m);
    for (row = 0; row < 6; row++) {
        for (w = 0; w < 7; w++) {
            d = cal[row][w];
            printf(d ? "%3d        " : "           ", d);
        }
        putchar('\n');
        for (w = 0; w < 7; w++) {
            d = cal[row][w];
            s = msg[m-1][d] ? msg[m-1][d] : d && w_msg[w] ? w_msg[w] : "";
            printf(" %-10.10s", s);
        }
        puts("\n");
    }
}

int main(int argc, char *argv[])
{
    time_t t = time(0);
    struct tm *p = localtime(&t);
    int y = p->tm_year + 1900;
    int m = p->tm_mon + 1;
    int d, w, n, row = 0;

    if (argc == 3) y = atoi(argv[1]), m = atoi(argv[2]);
    else if (argc == 2) m = atoi(argv[1]);

    read_schedule(y);

    if (m < 1 || m > 12) return 1;
    w = dayofweek(y, m, 1);
    n = days(y, m);
    for (d = 1; d <= n; d++) {
        cal[row][w] = d;
        if (++w == 7) w = 0, row++;
    }
    print(y, m);
    return 0;
}

---- SCHEDULE_FILE ----
2003
11/3  文化の日
2004
10/11 体育の日
11/3  文化の日
11/23 勤労感謝の日
水   定例会議

文字列が全角5文字を超える場合どうするかは自分で考えてください。