/*
编写一个程序,请求用户输入日,月,年,月份可以是月份号,月份名或月份缩写,然后程序返回一年中到给
定日子(包括这一天)的总天数
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <windows.h>
#define SIZE 20
#define EASY 3
#define YUE 12
int enteryears();
int leap_year(int year);
int entermonth();
void eatline(void);
struct month {
char month_name[SIZE]; //月份名;
char month_easy[EASY]; //月份简称
int day; //月份的天数
int month_num; //月份号
};
struct month year[YUE]={
{"january","jan",31,1},
{"february","feb",28,2},
{"march","mar",31,3},
{"april","apr",30,4},
{"may","may",31,5},
{"june","jun",30,6},
{"july","jul",31,7},
{"august","aug",31,8},
{"september","sep",30,9},
{"october","oct",31,10},
{"november","nov",30,11},
{"december","dec",31,12}
};
void main()
{
int years,months,days,leap;
system("color 0a");
years = enteryears();
leap = leap_year(years);
eatline();
months = entermonth(&year);
//printf("输入的是%d月\n",months); //此行代码意图做测试,看函数是否返回正常值;
}
int enteryears()
{
int years;
printf("请输入年份:\n");
//公元前和上亿年都不在该程序判断之列;
while ( (1 != scanf("%d",&years)) || (years < 1 || years > 99999999 ) ) {
printf("你的输入有误,请重新输入:\n");
fflush(stdin);
}
return years;
}
int leap_year(int year)
{
if ( year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ) {
return 1;
}
else return 0;
}
void eatline(void) //剔除剩余部分
{
while ( getchar() != '\n' ) {
continue;
}
}
//输入月份,如果输入的是月份名,或月份名缩写,就转换为月份号,便于识别;
int entermonth()
{
char month[SIZE]={0};
char * ptr;
int number=0,i,count=0;
printf("月份可以是月份名,月份缩写,月份号,请输入:\n");
while ( (ptr = fgets(month,SIZE,stdin)) != NULL ) {//当输入的字符串超过限制时循环
for ( i = 0 ; i < YUE; i++ ){
count = stricmp(year[i].month_name,ptr ) ;
if ( count == 0 ) {
number = year[i].month_num;
break;
}
if ( count != 0 ) {
continue;
}
}
}
return number;
}
先说下,此程序没有写完;问题就出在stricmp貌似无法正常识别结构中的数据;
stricmp(year[i].month_name,ptr )就是这句,只要不是结构变量,就可以,不知道为什么,
结构中的month_name也是字符串啊,为什么不行呢?
这个程序我的思路是这样的:把每个功能都写成单独的一个函数,比如,输入年份,月份,日期,都单独的用一个函数,并且判断是否闰年,如果是闰年,并且用户输入的月份是2月,那么就要控制用户在输入日期时不允许输入29天之后的日期,如果不是闰年,就不允许输入2月中的28天之后的日期.
目的很简单,尽可能的使该程序的健壮性提高.请不要用应付题目的思想来解题.
比如让你输入个整数日期,你就scanf("%d",days);就完事了?那是不行的,如果你这样写了,我输入个s ,程序就毕业了,那还有什么意思啊,这题我给高分,只允许最大给100分.必须要按照健壮性尽量高的思想来解题,我写到月份这里,出问题了,目的你帮我解决这个月份这一方面的问题就可以,其他方面我照样ok.
达不到要求的1分不给,达到要求的100分奉上,谢谢
我自学c语言的,不容易,0基础,希望,高手可以给予我指点,最好能留下扣扣.方便日后我请教!衷心感谢.感谢.感谢
请输入日期(空格隔开) : 2013 Jan 20
2013年1月20日到年底还有346天。
请按任意键继续. . .
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <windows.h>
#define SIZE 20
#define EASY 3
#define YUE 12
struct MONTH {
char month_name[SIZE]; //月份名
char month_easy[EASY + 1]; //月份简称
int days; //月份的天数
};
struct MyDATE {
int year;
int month;
int day;
};
int leap_year(int year);
int GetMonth(char month[]);
void GetDate(struct MyDATE *date);
struct MONTH year[YUE] = {
{"january","jan",31},{"february","feb",28},{"march","mar",31},
{"april","apr",30},{"may","may",31},{"june","jun",30},
{"july","jul",31},{"august","aug",31},{"september","sep",30},
{"october","oct",31},{"november","nov",30},{"december","dec",31}
};
int main() {
int mnth,days;
MyDATE mydate;
GetDate(&mydate);
days = (mydate.month <= 1) ? leap_year(mydate.year) : 0;
for(mnth = YUE; mnth >= mydate.month; --mnth)
days += year[mnth - 1].days;
days = days - mydate.day + 1;
printf("%d年%d月%d日到年底还有%d天。\n",mydate.year,mydate.month,mydate.day,days);
fflush(stdin);
system("pause");
return 0;
}
void GetDate(struct MyDATE *date) {
int flag,days,addday;
char mnth[15];
printf("请输入日期(空格隔开) : ");
do {
scanf("%d%s%d",&date->year,mnth,&date->day);
flag = 0;
if(date->year < 1 || date->year > 99999999) {
flag = 1;
printf("你的输入有误(年份应在1 -- 99999999之间)\n");
printf("请重新输入日期(空格隔开) : ");
continue;
}
if(mnth[0] >= '0' && mnth[0] <= '9') date->month = atoi(mnth);
else date->month = GetMonth(mnth);
if(date->month < 1 || date->month > YUE) {
flag = 1;
printf("你的输入有误(月份应在1 -- 12之间, 或英文的全写,或缩写)\n");
printf("请重新输入日期(空格隔开) : ");
continue;
}
addday = (date->month == 2) ? leap_year(date->year) : 0;
days = year[date->month - 1].days + leap_year(date->year) + addday;
if(date->day < 1 || date->day > days) {
flag = 1;
printf("你的输入有误(%d月的日期应在1 -- %d之间)\n",date->month,days);
printf("请重新输入日期(空格隔开) : ");
continue;
}
}while(flag);
}
int leap_year(int year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
int GetMonth(char mnth[]) {
int i,CmpRes1,CmpRes2;
for( i = 0 ; i < YUE; i++ ) {
CmpRes1 = stricmp(year[i].month_name,mnth);
CmpRes2 = stricmp(year[i].month_easy,mnth);
if( CmpRes1 == 0 || CmpRes2 == 0) return i + 1;
}
return 0;
}追问
这位老兄, 首先我想知道你到底用的什么编译器 总体上来讲,你的思路我大概看的懂了,但是请问下你这段代码编译过没有?16项错误.
其中最要命的是 main函数中 MyDATE mydate;这句是啥意思,明显的没声明的标识符. 这是逻辑错误.因为我认为你是想声明结构变量的.MyDATE是结构名,但是你这种声明方法很有问题,为什么不struct MyDATE mydate;但是就算是你想声明结构变量,后面也没有初始化,所以我很搞不懂你这句是干嘛的.
1、该代码已经在VC++ 6.0环境下通过编译,最前端的是运行测试结果。
2、MyDATE mydate;是声明一个MyDate类型的变量mydate,目的是为了GetDate()函数传回的结果。当然在C环境下应在前面加上struct(都是C++惹的祸,C++中是允许的,这里疏忽了,不好意思),即把这句改为: struct MyDATE mydate;,这个变量不需要初始化,如果你觉得心里不踏实,改为 struct MyDATE mydate = {0," ",0};也未尝不可。
嗯,在c中必须要加struct 结构名 结构变量,这种格式才可,不然无法编译.但你的代码还是有问题,我告诉你哪里有问题,在输入年的时候,一旦不按要求去输入数字,如果输入的是非数字字符,,,直接就陷入死循环,程序最好要有容错能力,用户输入错误没关系,要提示用户输入有错误,重新输入,而不是陷入死循环或者程序崩溃,退出,. 输入日期也是,一旦输入英文,就死循环了,你可以改一下,我 打算选择你做答案,你修改下,而且你没有做注释的习惯
追答// 限于字符个数的限制,仅将有改动的函数列表如下。
int main() { int mnth,days,an;
struct MyDATE mydate;
do {
GetDate(&mydate);
days = (mydate.month = mydate.month; --mnth)
days += year[mnth - 1].days;
days = days - mydate.day + 1;
printf("%d年%d月%d日到年底还有%d天。\n",mydate.year,mydate.month,mydate.day,days);
printf("继续(1/0) : ");
scanf("%d",&an);
}while(an);
return 0;
}
void GetDate(struct MyDATE *date) {
int flag,days,addday;
char amonth[SIZE],ayear[SIZE],aday[SIZE];
printf("请输入日期(空格隔开) : ");
while(scanf("%s%s%s",ayear,amonth,aday) == 3) {
flag = 1;
date->year = atoi(ayear);
if(date->year year > 99999999) {
flag = 0;
printf("输入有误(年份应在1 -- 99999999之间)\n");
printf("请重新输入日期(空格隔开) : ");
continue;
}
if(amonth[0] >= '0' && amonth[0] month = atoi(amonth);
else date->month = GetMonth(amonth);
if(date->month month > YUE) {
flag = 0;
printf("输入有误(月份应在1 -- 12之间, 或英文的全写,或缩写)\n");
printf("请重新输入日期(空格隔开) : ");
continue;
}
date->day = atoi(aday);
addday = (date->month == 2) ? leap_year(date->year) : 0;
days = year[date->month - 1].days + addday;
if(date->day day > days) {
flag = 0;
printf("输入有误(%d月的日期应在1 -- %d之间)\n",date->month,days);
printf("请重新输入日期(空格隔开) : ");
}
if(flag) return;
}
}
#include <stdio.h>
const short MonthDay[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
char dict[13][15]={" ","january","february","march",
"april","may","june","july","august","september",
"october","november", "december"};
main(){
int Day=0,Month=0,Year=0,Sum=0,Week=0,n=0;
char m_in[20];
int i,L;
printf("input year\n");
scanf("%d",&Year);
printf("input Month\n");
scanf("%s",m_in);
if ( sscanf(m_in,"%d",&Month) != 1)
{
Month=0;
L = strlen(m_in);
for (i=0;i<L;i++) if (m_in[i]>='A' && m_in[i]<='Z') { m_in[i] = m_in[i]-'A'+'a';}
for (i=1;i<13;i++) if (strncmp(m_in,dict[i],3)==0) {Month=i;break;};
}
if (Month==0) printf("Month error\n");
printf("input Day\n");
scanf("%d",&Day);
Sum=Day;
for (n=1;n<Month;n++) Sum+=MonthDay[n];
if ((Year%4==0)&&(Year%100!=0)||(Year%400==0) && Month>2) Sum++;
printf("%d\n",Sum);
return 0;
}
-------------
月份,只查前3个字母。
允许年份,公元后。追问
拜托,老兄,你这程序第一个scanf一出来,明显的就不合格了.根本没有容错能力.你第一个scanf用了个%d,你要知道,%d只能录入整数,如果用户一不小心键入了个字母或者非数字字符,这程序就崩溃了.根本没有健壮性可言,我写的是复杂了点,但可以容错,你写的是很简单,但没有任何健壮性可言,拜托你一下,拿出点职业精神,如果我像你这么写,早就搞定了,关键你这既不能容错,也没有用到结构体. 而我要求的是要用结构体!
追答这种“健壮”很简单,你让他再输入:
Lab_Y: printf("input year\n");
if ( scanf("%d",&Year) != 1) {fflush(stdin);goto Lab_Y;};
你让他再输入:
Lab_D: printf("input Day\n");
if ( scanf("%d",&Day) != 1) {fflush(stdin);goto Lab_D;};
要结构很简单:
struct dic {char dict[13][15];} Dic ={....};
然后把程序语句里的dict, 改写为 Dic.dict
等于多戴个帽子。
你愿意写得繁杂,给 Dic.dict[i] 初值,(例如用strcpy 一个一个给),也可以。
int Day=0,Month=0,Year=0,Sum=0,Week=0,n=0;
char m_in[20];
int i,L;
printf("input year\n");
scanf("%d",&Year);
printf("input Month\n");
scanf("%s",m_in);
if ( sscanf(m_in,"%d",&Month) != 1)
{
Month=0;
L = strlen(m_in);
for (i=0;i<L;i++) if (m_in[i]>='A' && m_in[i]<='Z') { m_in[i] = m_in[i]-'A'+'a';}
for (i=1;i<13;i++) if (strncmp(m_in,dict[i],3)==0) {Month=i;break;};
}
if (Month==0) printf("Month error\n");
printf("input Day\n");
scanf("%d",&Day);
Sum=Day;
for (n=1;n<Month;n++) Sum+=MonthDay