1、分数的四则运算
在小学时我们就学习了分数的四则运算,即对两个分数进行加、减、乘、除等运算,现在我们尝试下用C语言来实现。
输入:
分数1 操作符 分数2
输出:
计算结果
要求:
计算结果使用分数表示,并且为最简化。例如结果为2/6,则被简化为1/3
#include <stdio.h>
int main()
{
int x1, x2, y1, y2, b, c,i; //b为结果的分子,c为结果的分母
char a;//a表示加减乘除符号,b表示分子,c表示分母
scanf("%d/%d %c %d/%d", &x1, &x2, &a, &y1, &y2);
switch (a)
{
case '+':
b = x1 * y2 + x2 * y1;
c = x2 * y2;
break;
case '-':
b = x1 * y2 - x2 * y1;
c = x2 * y2;
break;
case '*':
b = x1 * y1;
c = x2 * y2;
break;
case '/':
b = x1 * y2;
c = x2 * y1;
break;
}
for(i=b;i>=1;i--) //判断分子分母是否能够化简
{
if((b%i==0)&&(c%i==0))
{
b=b/i;
c=c/i;
}
}
if(b==0)
{
printf("%d/%d %c %d/%d = 0\n", x1, x2, a, y1, y2);
}
else if(c==1)
{
printf("%d/%d %c %d/%d = %d\n", x1, x2, a, y1, y2, b);
}
else
{
printf("%d/%d %c %d/%d = %d/%d\n", x1, x2, a, y1, y2, b, c);
}
return 0;
}
小提醒:在switch里面的每个case结束后最好都带个break~
------------------------------------------------这里是无情的切割线------------------------------------------------------
2、【中学】计算时钟的夹角
背景:
钟面上的时针和分针之间的夹角总是在 0 ~180之间 ( 包括 0 和180 ) 。举例来说,在十二点的时候两针之间的夹角为 0 ,而在六点的时候夹角为180 ,在三点的时候为90 。本题要解决的是计算 12:00 到 11:59 之间任意一个时间的夹角。
输入:
每组测试数据包含两个数字:第一个数字代表小时 ( 大于 0 小于等于 12) ,第二个数字代表分 ( 在区间 [0, 59] 上 ) 。
输出:
对应每组测试数据,用常用格式显示时间以及这个时候时针和分针间的最小夹角,精确到小数点后一位。输出格式如下所示。
再看一看,想一想:是否可以不用if 语句,只使用 printf 函数来简化你的程序?
首先是考虑使用if语句的情况:
#include <stdio.h>
int main()//计算时针与分针的角度
{
int x,y,z;
double a,b;//x表示小时数,y表示分钟数,a表示时针转过角度,b表示分针转过角度
scanf("%d %d",&x,&y);
if(x<=6) z=x;
else z=(12-x);
a=y*0.5+z*30.0;
b=y*6.0;
if(a>b)
printf("At %d:%02d the angle is %.1f degrees.\n", x,y,a-b);
else
printf("At %d:%02d the angle is %.1f degrees.\n", x,y,b-a);
return 0;
}
根据课上所学的,若是想要把if语句省略掉,我自己的想法就是用三目式来替代:
#include <stdio.h>
int main()//计算时针与分针的角度
{
int x,y,z;
double a,b;//x表示小时数,y表示分钟数,a表示时针转过角度,b表示分针转过角度
scanf("%d %d",&x,&y);
z=(x<=6)?x:12-x;
a=y*0.5+z*30.0;
b=y*6.0;
printf("At %d:%02d the angle is %.1f degrees.\n", x,y,(a>b)?a-b:b-a);
return 0;
}
------------------------------------------------这里是无情的切割线------------------------------------------------------
3、【中学】求解一元二次方程
初中的小明已经开始学习求解一元二次方程了,下面让我们来教计算机如何求解。输入 a,b,c ,求一元二次方程 ax²+bx+c=0 的根。
输入:
假设 a,b,c均int。
输出:
要求输出的根为 double 型,保留 6 位小数。
我先贴一下我第一次做这道题的代码,纯纯就是硬干,但是显然看起来很麻烦:
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c,delta;//一元二次方程为ax^2+bx+c=0; delta为方程的根 ;
scanf("%lf %lf %lf",&a,&b,&c);
delta=b*b-4*a*c;
if(a==0&&b==0) //当该方程式只有常数项,即形式为c=0时:
printf("Input error!\n");
else if(a==0&&b!=0) //当该方程式的二次项为零,即形式为bx+c=0时:
{
if(-c/b==0)
printf("x=%.6f\n",0);
else
printf("x=%.6f\n",-c/b);
}
else if(a!=0&&b==0) //当该方程式的一次项为零,即形式为ax^2+c=0时:
{
if(-c/a>0)
printf("x1=%.6f\nx2=%.6f\n",sqrt(-c/a),-sqrt(-c/a));
else if(-c/a==0)
printf("x1=x2=%.6f\n",0);
else if(-c/a<0)
{
double x=fabs(-c/a);//x表示c/a的绝对值,方便之后的开根号
printf("x1=%.6fi\nx2=%.6fi\n",sqrt(x),-sqrt(x));
}
}
else if(a!=0&&b!=0) //为标准的一元二次方程时:
{
if(delta==0)
printf("x1=x2=%.6f\n",(-b)/(2*a));
else if(delta>0)
{
printf("x1=%.6f\n",(-b+sqrt(delta))/(2*a));
printf("x2=%.6f\n",(-b-sqrt(delta))/(2*a));
}
else //当情况属于复数时:
{
double y=fabs(delta);
printf("x1=%.6f+%.6fi\n",-b/(2*a), sqrt(y)/(2*a));
printf("x2=%.6f%.6fi\n",-b/(2*a), -sqrt(y)/(2*a));
}
}
return 0;
}
再来做这道题,重新捋一下思路,首先是a=0且b=0时单独讨论,然后根据判别式来开干(
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c,delta;//一元二次方程为ax^2+bx+c=0; delta为方程的根 ;
scanf("%lf %lf %lf",&a,&b,&c);
delta=b*b-4*a*c;
if(a==0&&b==0) //当该方程式只有常数项,即形式为c=0时:
printf("Input error!\n");
else if(a==0&&b!=0) //当该方程式为一次函数时:
{
if(-c/b==0)
printf("x=%.6f\n",0);
else
printf("x=%.6f\n",-c/b);
}
else
{
if(delta==0) //判别式=0时:
{
if((-b)/(2*a)==0)
printf("x1=x2=%.6f\n",0);
else
printf("x1=x2=%.6f\n",(-b)/(2*a));
}
else if(delta>0) //判别式>0时:
printf("x1=%.6f\nx2=%.6f\n",(-b+sqrt(delta))/(2*a),(-b-sqrt(delta))/(2*a));
else //判别式<0时:
{
if(-b/(2*a)==0)
{
printf("x1=%.6fi\n", sqrt(fabs(delta))/(2*a));
printf("x2=%.6fi\n",-sqrt(fabs(delta))/(2*a));
}
else
{
printf("x1=%.6f+%.6fi\n",-b/(2*a), sqrt(fabs(delta))/(2*a));
printf("x2=%.6f%.6fi\n",-b/(2*a), -sqrt(fabs(delta))/(2*a));
}
}
}
return 0;
}
------------------------------------------------这里是无情的切割线------------------------------------------------------
4、【入门】大小写字母转换
我们知道,英文字母是分大小写的,下面我们需要编写一个简单的程序,将输入的全部小写字母变换为大写字母,大写字母变换为小写字母,非写字母保持不变。
输入:
一个字符
输出:
变换后的字符
先贴一个最朴实无华的根据ascii码的方法:
#include <stdio.h>
int main()
{
char x;//x表示一个字母
scanf("%c",&x);
if(x>='A'&&x<='Z')
{
x+=32;
printf("%c\n",x);
}
else if(x>='a'&&x<='z')
{
x-=32;
printf("%c\n",x);
}
else
{
printf("%c\n",x);
}
return 0;
}
高级一丢丢的可以用:
#include <stdio.h>
#include <ctype.h>
int main()
{
char x;//x表示一个字母
scanf("%c",&x);
if(isalpha(x)) //判断是否为大小写
{
if(islower(x))
printf("%c\n",toupper(x)); //小写转大写
else
printf("%c\n",tolower(x)); //大写转小写
}
else //原封不动输出
printf("%c\n",x);
return 0;
}
------------------------------------------------这里是无情的切割线------------------------------------------------------
5、【日期】根据日期求星期
任意给出一个年月日,求出是星期几。
输入:
年 月 日
输出:
0~6。
星期日用 0 表示,星期一用 1 表示,星期二用 2 表示......星期六用 6 表示。
假设年份大于1900。先想一想:我们现在只会使用 if 语句,该如何建立数学模型?找到数学模型是解决本题的关键。
按照惯例先贴出我第一次做的时候的代码,只能说那时候满脑子都是硬干,加上对C的理解还很浅薄,导致整个代码看起来就很繁琐……
#include <stdio.h>
int caculate1(int i);
int main()
{
int year=0, month=0, day=0;//x代表输入年份,y表示输入月份,z表示输入的日份
scanf("%d %d %d", &year, &month, &day);
/*解决年的问题*/
int i = year - 1;//i表示输入年份的前一年
int x = 0;//x表示输入年份的前一年距离1900年1月1日的日子数
x=caculate1(i);
/*解决月的问题*/
int y = 0;//y表示输入月份的前一月距离本年1月1日的日子数
int m;//用于解决2月份是否为闰月的方法
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
m = 29;
}
else {
m = 28;
}
switch (month)
{
case 1: y = 0;break;
case 2: y = 31;break;
case 3: y = 31 + m;break;
case 4: y = 62 + m;break;
case 5: y = 92 + m;break;
case 6: y = 123 + m;break;
case 7: y = 153 + m;break;
case 8: y = 184 + m;break;
case 9: y = 215 + m;break;
case 10:y = 245 + m;break;
case 11:y = 276 + m;break;
case 12:y = 306 + m;break;
}
/*解决日的问题*/
int z = day;//x表示输入日份距离本月1日的日子数
int all = x + y + z;//表示总日子数
int answer = all % 7;//表示周几
printf("%d\n", answer);
return 0;
}
int caculate1(int i)
{
int x1 = 0;//x1表示闰年个数
int x2 = 0;//x2表示平年个数
int x3 = 0;//x3表示x-1年距离1900年总共的天数
if (i < 1900)
{
x3 = 0;
return x3;
}
else
{
do
{
if (i % 4 == 0 && i % 100 != 0)
{
x1++;
}
else if (i % 400 == 0)
{
x1++;
}
else {
x2++;
}
i--;
} while (i >= 1900);
x3 = 366 * x1 + 365 * x2;
return x3;
}
}
后面重新做一做这道题,优化一些不必要的步骤:
#include <stdio.h>
int caculate1(int year) //计算当前年份的前一年的最后一天距离1900.1.1总计多少天数
{
int sum=0,i;
for(i=1900;i<=year-1;i++)
{
if((i%4==0&&i%100!=0)||i%400==0)
sum+=366;
else
sum+=365;
}
return sum;
}
int main()
{
int year,month,day,sum,i,j,x;
scanf("%d %d %d",&year,&month,&day);
sum=caculate1(year);
int everymonth[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的各月份的天数
if((year%4==0&&year%100!=0)||year%400==0)//闰年修改2月份的天数
everymonth[1]=29;
for(i=0;i<month-1;i++)
sum+=everymonth[i];
sum+=day;
printf("%d\n",sum%7);
}
------------------------------------------------这里是无情的切割线------------------------------------------------------
以上。