dポイントプレゼントキャンペーン実施中!

以下はcalendarを出力するものです。

commandlineで入力します。

出力するとき(例)
./a.exe → 現在のカレンダー出力させる
./a.exe 2015 → 2015年のすべて表示
./a.exe 2015 10 → 2015年10月の表示

上の二つを追加したいです。一番下のは何となくできました。
全て表示は月(12回)をループするのはわかりますが、どこに入れればよいかわかりません。
現在出力はlocaltimeを使うと思うのですが、どのように入れたらよいか、また変換をしなければいけませんので、このプログラムをどう変えれば良いでしょうか?

やるなら、全表示から行うのが楽ですかね?

ご指摘お願いします。







#include <stdio.h>

int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

void calender(int year2, int month2)
{
int days, i;
int wday, year,month,d,a;

year = year2;
month = month2;

wday = year + year / 4 - year / 100 + year / 400 + (26 * month + 16) / 10 + 1;
wday = wday % 7; //チェラーの法則

if (year <= 2) //曜日の計算をする
{
month += 12;
year--;
}

printf(" ---- %d年%d月 ----\n", year2, month2);
printf(" 日 月 火 水 木 金 土\n");

days = mdays[month2 - 1]; //日数を計算する

if (year2 % 4 == 0 && !(year2 % 100 == 0 && year2 % 400 != 0))
{
if (month == 2) // うるう年の処理
{
days++;
}
}
for(i = 0; i < wday; i++) //空白を生成
{
printf(" ");
}
for(d = 1; d <= days; d++) //最終日まで表示
{
printf(" %2d", d);
wday++;

if (wday == 7) //日曜日で改行
{
wday = 0;
printf("\n");
}
}
if (wday != 0)
{
printf("\n");
}
}
int main(int argc, char *argv[])
{
int year2, month2;

if (argc==2)
{
year2=atoi(argv[1]);
//printf("%d年\n", year2);
}
else if (argc==3)
{
year2=atoi(argv[1]);
month2=atoi(argv[2]);
//printf("%d年%d月\n", year2, month2);
}
else
{
printf("エラー\n");
return 0;
}
calender(year2, month2);

return 0;
}

質問者からの補足コメント

  • #プログラム
    #c言語

      補足日時:2015/12/08 19:53
  • エラーでます。

    「大至急お願いします。出力で悩み。」の補足画像2
      補足日時:2015/12/08 22:55

A 回答 (15件中1~10件)

1:マイナスオプション対応


2:「チェラーの法則」があてにならないので止め。(笑

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

int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

void getwday(int * year, int * month, int * wday)
{
time_t timep;
struct tm *time_inf;
struct tm time_clc;
int oyear, omonth;

oyear = *year;
omonth = *month;
// 年が無効なら、今日の年月を求める
if( *year <= 0 ) {
timep = time(NULL);
time_inf = localtime(&timep);
*year = time_inf->tm_year + 1900;
*month = time_inf->tm_mon + 1;
}
// -オプションの時、月を引く
if( oyear < 0 ) {
*month += oyear + 1;
}
// 月がマイナスのなった場合の処理
if( *month <= 0 ) {
*year -= 1;
*month += 12;
}
// 月が12を超えた場合の処理
if( *month > 12 ) {
*year += 1;
*month -= 12;
}

// 曜日を求める
memset((void *)&time_clc, '\0', sizeof(time_clc));
time_clc.tm_year = *year - 1900;
time_clc.tm_mon = *month - 1;
time_clc.tm_mday = 1;
mktime( &time_clc );
*wday = time_clc.tm_wday;
}

void calender(int year2, int month2, int wday)
{
int days, i, d;

// wday2 = year2 + year2 / 4 - year2 / 100 + year2 / 400 + (26 * month2 + 16) / 10 + 1;
// wday2 = wday2 % 7; //チェラーの法則

printf(" ---- %d年%d月 ----\n", year2, month2);
printf(" 日 月 火 水 木 金 土\n");

days = mdays[month2 - 1]; //日数を計算する

// うるう年の処理
if (month2 == 2)
{
if (year2 % 4 == 0 && !(year2 % 100 == 0 && year2 % 400 != 0)) days++;
}

//空白を生成
for(i = 0; i < wday; i++) printf(" ");
//最終日まで表示
for(d = 1; d <= days; d++)
{
if (wday == 6) //土曜日で改行
{
wday = 0;
printf(" %2d\n", d);
} else {
wday++;
printf(" %2d", d);
}
}
if (wday != 0) printf("\n");
}

int main(int argc, char *argv[])
{
int year2 = 0, month2 = 0, wday;
int wmonth;

if(argc == 3) {
year2 = atoi(argv[1]);
month2 = atoi(argv[2]);
} else if(argc == 2) {
year2 = atoi(argv[1]);
}

if(month2 != 0) {
// 引数:月のエラー判定
}
if(year2 != 0) {
// 引数:年のエラー判定
}

if(year2 < 0) {
for( wmonth = year2; wmonth < 0; wmonth++ ) {
getwday(&year2, &month2, &wday);
calender(year2, month2, wday);
month2++;
}
} else if(year2 != 0 && month2 == 0) {
for(month2 = 1; month2 <= 12; month2++ ) {
getwday(&year2, &month2, &wday);
calender(year2, month2, wday);
}
} else {
getwday(&year2, &month2, &wday);
calender(year2, month2, wday);
}

return 0;
}
    • good
    • 0
この回答へのお礼

ありがとうございます。
1つ前のエラー判定の質問をしたときに実行したら、全てにエラーがでて、./a.exe 2015 ではエラーと曜日のみ出力になってしまいます。
else
現在時間を求めるやつ。

移行は
if(month2 != 0) {
// 引数:月のエラー判定
}
if(year2 != 0) {
// 引数:年のエラー判定
}

if(year2 != 0 && month2 == 0) {
for(month2 = 1; month2 <= 12; month2++ ) {
calender(atoi(argv[1]), month2);
}
} else {
calender(year2, month2);
そのまま書きました。

お礼日時:2015/12/10 21:39

https://ja.wikipedia.org/wiki/%E3%83%84%E3%82%A7 …
> ただし、1月と2月は、前年のそれぞれ13月・14月として扱う。
> たとえば、2015年1月1日・2月1日は、2014年13月1日・14月1日とする。

計算は、プログラムの通りの順番に行なわれます。
wdayを 計算したあとで、year,monthを変更しても、プログラムを遡ってwdayを計算しなおしたりはしません。

> if (year <= 2) //曜日の計算をする

○ yearが2以下になることは、ほとんど無いし、上記のツェラーの公式用の計算なら「年」ではありません。
○ コメントの書き方もプログラミング技術の一つです。
 ここは、「曜日の計算をする」場所ではなく、その「準備をする」場所。
 具体的には 「1月と2月は、前年のそれぞれ13月・14月として扱う」ための場所です。

if (year <= 2) //1月と2月は、前年のそれぞれ13月・14月として扱う
だったら、 year がおかしいし、計算順番もおかしいことがわかったのでは。
    • good
    • 0
この回答へのお礼

monthですかね?

お礼日時:2015/12/10 23:36

//空白を生成


for(i = 0; i < wday; i++) printf(" ");

このprintfの中が、スペース1つになっていませんか?
ここは、スペース3つです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
確認不足でした。

因みに、この前のソースの1月と2月がツェラーの法則に問題があり、あってない。のが治せません。

あと、このソースのエラーはどうやって出力しますか?

お礼日時:2015/12/10 22:49

すみません。


色々と修正しているので、修正した一部分をアップしてしまったかもしれないです。
No.12
が、全ソースなのでこれを使ってください。
    • good
    • 0
この回答へのお礼

出力すると1とか2とかが主に1桁がずれてしまっています。

お礼日時:2015/12/10 22:22

>カレンダーのオプションって、どのように作成するものですか?


オプション?って何のことをいってます?
    • good
    • 0
この回答へのお礼

私も詳しくは分かりませんが、-3 入力で現在から3ヶ月前まで出力
とかって、オプションて言うんですかね?

お礼日時:2015/12/10 19:36

「1月と2月がずれてしまう」ってのは, 単純にツェラーの公式 (#1 などでは「チェラー」と書いてあるが Zeller というドイツ人なのでドイツ語的に発音すれば「ツェラー」の方がより近い) を間違えているからです.



正しい形は, 例えば Wikipedia にあります.
    • good
    • 0
この回答へのお礼

1月と2月は特殊ですよね?
考え方が。

お礼日時:2015/12/10 21:14

例えば、こんな形でエラー判定出来ます。



int main(int argc, char *argv[])
{
int year2 = 0, month2 = 0;

if(argc == 3) {
year2 = atoi(argv[1]);
month2 = atoi(argv[2]);
} else if(argc == 2) {
year2 = atoi(argv[1]);
}

if(month2 != 0) {
// 引数:月のエラー判定
}
if(year2 != 0) {
// 引数:年のエラー判定
}

if(year2 != 0 && month2 == 0) {
for(month2 = 1; month2 <= 12; month2++ ) {
calender(atoi(argv[1]), month2);
}
} else {
calender(year2, month2);
}

return 0;
}
    • good
    • 0
この回答へのお礼

ありがとうございます。
カレンダーのオプションって、どのように作成するものですか?

度々、すみません。

お礼日時:2015/12/10 17:16

wday = year2 + year2 / 4 - year2 / 100 + year2 / 400 + (26 * month2 + 16) / 10 + 1;


wday = wday % 7; //チェラーの法則

多少変更はしましたが、ここの計算の問題だと思いますよ。
    • good
    • 0
この回答へのお礼

エラー判定は関数でやるべきですよね?

お礼日時:2015/12/09 22:56

>エラー判定はmain内で行えば大丈夫ですよね?


そうですね。
判定する必要があるとしたら、引数が年月か?くらいかと思いますが?

>あと、strftimeをメンバーにアクセスとはなんですかね?
time_inf = localtime(&timep);
ここで使用している、
struct tm *time_inf;
この構造体は、
struct tm {
int tm_sec;/* 秒[0-61]閏秒考慮 */
int tm_min;/* 分[0-59] */
int tm_hour;/* 時[0-23] */
int tm_mday;/* 日[1-31] */
int tm_mon;/* 月[0-11] */
int tm_year;/* 年[1900年から起算] */
int tm_wday;/*曜日[0-6] 0:日曜日 */
int tm_yday;/*年内の経過日数[0-365] */
int tm_isdst;/*日本では0 */
};
と定義されています。
なので、
year2 = time_inf->tm_year + 1900;
month2 = time_inf->tm_mon + 1;
で取得出来るのです。
tm_yearやtm_monはtm構造体のメンバーなので、
メンバーにアクセスということです。

if(argc == 3) {
month2=atoi(argv[2]);
year2=atoi(argv[1]);
} else if(argc == 2) {
year2=atoi(argv[1]);
} else {
timep = time(NULL);
time_inf = localtime(&timep);
year2 = time_inf->tm_year + 1900;
month2 = time_inf->tm_mon + 1;
}
※char buff[100]; が不要になります。
    • good
    • 0
この回答へのお礼

ありがとうございます。
あと、1月と2月がずれてしまうのはどうしてですか?

お礼日時:2015/12/09 22:40

なんで strftime なんて使うんだろう. 素直にメンバーにアクセスすればいいのに.

    • good
    • 0
この回答へのお礼

どうすればよいですかね?

お礼日時:2015/12/09 15:13

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!