目录
5.1 零碎基础知识
const double SCALE = 0.333;// const变量
用 const 定义的变量的值是不允许改变的,即不允许给它重新赋值,即使是赋相同的值也不可以。所以说它定义的是只读变量。这也就意味着必须在定义的时候就给它赋初值。
const VS define
- define是预编译指令,而const是普通变量的定义。define定义的宏是在预处理阶段展开的,而const定义的只读变量是在编译运行阶段使用的。
- const定义的是变量,而define定义的是常量。define定义的宏在编译后就不存在了,它不占用内存,因为它不是变量,系统只会给变量分配内存。但const定义的常变量本质上仍然是一个变量,具有变量的基本属性,有类型、占用存储单元。可以说,常变量是有名字的不变量,而常量是没有名字的。有名字就便于在程序中被引用,所以从使用的角度看,除了不能作为数组的长度,用const定义的常变量具有宏的优点,而且使用更方便。所以编程时在使用const和define都可以的情况下尽量使用常变量来取代宏。
- const定义的是变量,而宏定义的是常量,所以const定义的对象有数据类型,而宏定义的对象没有数据类型。所以编译器可以对前者进行类型安全检查,而对后者只是机械地进行字符替换,没有类型安全检查。这样就很容易出问题,即“边际问题”或者说是“括号问题”。
pow() 函数用来求 x 的 y 次方的值。
头文件:math.h
语法/原型:
double pow(double x,double y);
sizeof()运算符以字节为单位返回运算对象的大小
C 语言规定,sizeof 返回 size_t 类型的值。
C99 做了进一步调整,新增了%zd 转换说明用于 printf()显示 size_t 类型的值。
whie循环的用法
#include <stdio.h>
#define SEC_PER_MIN 60 //1分钟60秒
int main(void)
{
int sec, min, left;
printf("Convert seconds to minutes and seconds!\n");
printf("Enter the number of seconds (<=0 to quit):\n");
scanf_s("%d", &sec);
while (sec > 0)
{
min = sec / SEC_PER_MIN; //截断分钟数
left = sec % SEC_PER_MIN; //剩下的秒数
printf("%d seconds is %d minutes, %d seconds.\n",
sec, min, left);
printf("Enter next value (<=0 to quit):\n");
scanf_s("%d", &sec);
}
printf("Done!\n");
return 0;
}
运算结果:
强制类型转换运算符
例如:
mice = 1.6 + 1.7;
mice = (int)1.6 + (int)1.7;
小结
// running.c -- A useful program for runners
#include <stdio.h>
const int S_PER_M = 60; //一分钟的秒数
const int S_PER_H = 3600; //一小时的秒数
const double M_PER_K = 0.62137; //一公里的英里数
int main(void)
{
double distk, distm; //跑过的距离(分别以公里和英里为单位)
double rate; //平均速度(以英里、小时为单位)
int min, sec; //跑步用时(以分种和秒为单位)
int time; //跑步用时(以秒为单位)
double mtime; //跑一英里需要用的时间,以秒为单位
int mmin, msec; //跑一英里需要的时间,以秒为单位
printf("This program converts your time for a metric race\n");
printf("to a time for running a mile and to your average\n");
printf("speed in miles per hour,\n");
printf("Please enter, in lilometers, the distance run.\n");
scanf_s("%lf", &distk);
printf("Next enter the time in minutes and seconds.\n");
printf("Begin by entering the minutes.\n");
scanf_s("%d", &min);
printf("Now enter the seconds.\n");
scanf_s("%d", &sec);
time = S_PER_M * min + sec; //把时间转化为秒
distm = M_PER_K * distk; //把公里转换成英里
rate = distm / time * S_PER_H; //英里/秒x秒/小时 = 英里/小时
mtime = (double)time / distm; //时间/距离 = 跑一英里所用的时间
mmin = (int)mtime / S_PER_M; //求出分钟数
msec = (int)mtime % S_PER_M; //求出剩余的秒数
printf("You ran %1.2f km (%1.2f miles) in %d min, %d sec.\n",
distk, distm, min, sec);
printf("That pace corresponds to running a mile in %d min,",
mmin);
printf("%d sec.\n Your average speed was %1.2f mph.\n",
msec, rate);
return 0;
}
运行结果:
5.2 复习题
1.假设所有变量的类型都是int,下列各项变量的值是多少:
a.x = (2 + 3) * 6; 30
b.x = (12 + 6)/2*3; 27
c.y = x = (2 + 3)/4; 1
d.y = 3 + 2*(x = 7/2); 9
2.假设所有变量的类型都是int,下列各项变量的值是多少:
a.x = (int)3.8 + 3.3; 6
b.x = (2 + 3) * 10.5; 52
c.x = 3 / 5 * 22.0; 0
d.x = 22.0 * 3 / 5; 13
3.对下列各表达式求值:
a.30.0 / 4.0 * 5.0; 37.5
b.30.0 / (4.0 * 5.0); 1.5
c.30 / 4 * 5; 35
d.30 * 5 / 4; 37
e.30 / 4.0 * 5; 37.5
f.30 / 4 * 5.0; 35
4.请找出下面的程序中的错误。
int main(void)
{
int i = 1,
float n;
printf("Watch out! Here come a bunch of fractions!\n");
while (i < 30)
n = 1/i;
printf(" %f", n);
printf("That's all, folks!\n");
return;
}
运行结果:
#include<stdio.h>
int main(void)
{
int i = 1;
float n;
printf("Watch out! Here come a bunch of fractions!\n");
while (i++ < 30)
{
n = 1.0 / i;
printf(" %f\n", n);
}
printf("That's all, folks!\n ");
return 0;
}
5.这是程序清单 5.9 的另一个版本。从表面上看,该程序只使用了一条scanf()语句,比程序清单5.9简单。请找出不如原版之处。
#include <stdio.h>
#define S_TO_M 60
int main(void)
{
int sec, min, left;
printf("This program converts seconds to minutes and ");
printf("seconds.\n");
printf("Just enter the number of seconds.\n");
printf("Enter 0 to end the program.\n");
while (sec > 0) {
scanf("%d", &sec);
min = sec/S_TO_M;
left = sec % S_TO_M;
printf("%d sec is %d min, %d sec. \n", sec, min, left);
printf("Next input?\n");
}
printf("Bye!\n");
return 0;
}
这个版本最大的问题是测试条件(sec是否大于0?)和scanf()语句获取sec变量的值之间的关系。具体地说,第一次测试时,程序尚未获得sec的值,用来与0作比较的是正好在sec变量内存位置上的一个垃圾值。一个比较笨拙的方法是初始化 sec(如,初始化为 1)。这样就可通过第一次测试。不过,还有另一个问题。当最后输入0结束程序时,在循环结束之前不会检
查sec,所以0也被打印了出来。因此,更好的方法是在while测试之前使用
scanf()语句。可以这样修改:
scanf("%d", &sec);
while ( sec > 0 ) {
min = sec/S_TO_M;
left = sec % S_TO_M;
printf("%d sec is %d min, %d sec.\n", sec, min, left);
printf("Next input?\n");
scanf("%d", &sec);
}
while循环第一轮迭代使用的是scanf()在循环外面获取的值。因此,在while循环的末尾还要使用一次scanf()语句。这是处理类似问题的常用方法。
6.下面的程序将打印出什么内容?
#include <stdio.h>
#define FORMAT "%s! c is cool!\n"
int main(void)
{
int num = 10;
printf(FORMAT, FORMAT);
printf("%d\n", ++num);
printf("%d\n", num++);
printf("%d\n", num--);
printf("%d\n", num);
return 0;
}
运行结果:
7.下面的程序将打印出什么内容?
#include <stdio.h>
int main(void)
{
char c1, c2;
int diff;
float num;
c1 = 'S';
c2 = 'O';
diff = c1 - c2;
num = diff;
printf("%c%c%c:%d %3.2F\n", c1, c2, c1, diff, num);
return 0;
}
运行结果:
8.下面的程序将打印出什么内容?
#include <stdio.h>
#define TEN 10
int main(void)
{
int n = 0;
while(n++ < TEN)
printf("%5d", n);
printf("\n");
return 0;
}
运行结果:
9.修改上一个程序,使其可以打印字母a~g。
#include <stdio.h>
int main(void)
{
char n = 'a'- 1;
while(n++ < 'g')
printf("%5c", n);
printf("\n");
return 0;
}
运行结果:
10.假设下面是完整程序中的一部分,它们分别打印什么?
a.
int x = 0;
while (++x < 3)
printf("%4d", x);
b.
int x = 100;
while (x++ < 103)
printf("%4d\n",x);
printf("%4d\n",x);
c.
char ch = 's';
while (ch < 'w')
{
printf("%c", ch);
ch++;
}
printf("%c\n",ch);
略(太幼稚了,用脚趾头都能想出来)
11.下面的程序会打印出什么?
#include <stdio.h>
#define MESG "COMPUTER BYTES DOG"
int main(void)
{
int n = 0;
while (n < 5)
printf("%s\n", MESG);
n++;
printf("That's all.\n");
return 0;
}
小陷阱,while() 语句后因为无花括号,所以while() 语句只有后面一条 printf() 由于n++在while() 语句外,程序便一直循环 COMPUTER BYTES DOG
12.分别编写一条语句,完成下列各任务(或者说,使其具有以下副作用):
a.将变量x的值增加10 x = x + 10;
b.将变量x的值增加1 x++;
c.将a与b之和的两倍赋给c c = 2(a + b);
d.将a与b的两倍之和赋给c c = a + 2*b;
13.分别编写一条语句,完成下列各任务:
a.将变量x的值减少1 x--;
b.将n除以k的余数赋给m m = n % k;
c.q除以b减去a,并将结果赋给p p = q / b - a;
d.a与b之和除以c与d的乘积,并将结果赋给x x = (a + b) / (c * d)
5.3 编程练习
1.编写一个程序,把用分钟表示的时间转换成用小时和分钟表示的时间。使用#define或const创建一个表示60的符号常量或const变量。通过while循环让用户重复输入值,直到用户输入小于或等于0的值才停止循环。
#include <stdio.h>
const int H_PER_M = 60;
int main(void)
{
int min;
printf("Please enter a minutes num:\n");
scanf_s("%d", &min);
while (min > 0)
{
printf("%d minutes are %d hours %d minutes\n",
min, min / H_PER_M, min % H_PER_M);
scanf_s("%d", &min);
}
printf("DONE!");
return 0;
}
运行结果:
2.编写一个程序,提示用户输入一个整数,然后打印从该数到比该数大10的所有整数(例如,用户输入5,则打印5~15的所有整数,包括5和15)。要求打印的各值之间用一个空格、制表符或换行符分开。
#include <stdio.h>
int main(void)
{
int num, topnum;
printf("Please enter a number:\n");
scanf_s("%d", &num);
topnum = num + 11;
while (num < topnum)
{
printf("%5d", num);
num++;
}
return 0;
}
运行结果:
3.编写一个程序,提示用户输入天数,然后将其转换成周数和天数。例如,用户输入18,则转换成2周4天。以下面的格式显示结果:
18 days are 2 weeks, 4 days.
通过while循环让用户重复输入天数,当用户输入一个非正值时(如0或-20),循环结束。
#include <stdio.h>
const int DAY_WEEK = 7;
int main(void)
{
int day;
printf("Enter days: ");
while (scanf_s("%d", &day)&&day > 0)
{
printf("%d days are %d weeks, %d days.\n",
day, day / DAY_WEEK, day % DAY_WEEK);
printf("Enter days: ");
}
printf("DONE");
return 0;
}
运行结果:
4.编写一个程序,提示用户输入一个身高(单位:厘米),并分别以厘米和英寸为单位显示该值,允许有小数部分。程序应该能让用户重复输入身高,直到用户输入一个非正值。其输出示例如下:
Enter a height in centimeters: 182
182.0 cm = 5 feet, 11.7 inches
Enter a height in centimeters (<=0 to quit): 168.7
168.0 cm = 5 feet, 6.4 inches
Enter a height in centimeters (<=0 to quit): 0bye
#include <stdio.h>
const float FOOT_INCHE = 30.48;
const float INCHE_CENT = 2.54;
int main(void)
{
float height;
int d_foot;
float d_inche;
printf("Enter a height in centimeters: ");
while (scanf_s("%f", &height)&&height > 0)
{
d_foot = height / FOOT_INCHE;
d_inche = (height - d_foot * FOOT_INCHE) / INCHE_CENT;
printf("%.1f cm = %d feet, %.1f inches\n",
height, d_foot, d_inche);
printf("Enter a height in centimeters(<=0 to quit): ");
}
printf("bye");
return 0;
}
运行结果:
5.修改程序addemup.c(程序清单5.13),你可以认为addemup.c是计算20天里赚多少钱的程序(假设第1天赚$1、第2天赚$2、第3天赚$3,以此类推)。修改程序,使其可以与用户交互,根据用户输入的数进行计算(即,用读入的一个变量来代替20)。
#include <stdio.h>
int main(void)
{
int count, sum, d;
count = 0;
sum = 0;
printf("please enter num:");
scanf_s("%d", &d);
while (count++ < d)
sum = sum + count;
printf("sum = %d\n", sum);
return 0;
}
运行结果:
6.修改编程练习5的程序,使其能计算整数的平方和(可以认为第1天赚$1、第2天赚$4、第3天赚$9,以此类推,这看起来很不错)。C没有平方函数,但是可以用n * n来表示n的平方。
sum = sum + count*count;
7.编写一个程序,提示用户输入一个double类型的数,并打印该数的立方值。自己设计一个函数计算并打印立方值。main()函数要把用户输入的值传递给该函数。
#include <stdio.h>
int aaa(double a);
int main()
{
double num;
printf("Please enter a num: ");
scanf_s("%lf", &num);
aaa(num);
return 0;
}
int aaa(double a)
{
printf("你输入数字的立方根是: %.2f\n", a*a*a);
return 0;
}
运行结果:
8.编写一个程序,显示求模运算的结果。把用户输入的第1个整数作为求模运算符的第2个运算对象,该数在运算过程中保持不变。用户后面输入的数是第1个运算对象。当用户输入一个非正值时,程序结束。其输出示例如下:
This program computes moduli.
Enter an integer to serve as the second operand: 256
Now enter the first operand: 438
438 % 256 is 182
Enter next number for first operand (<= 0 to quit): 1234567
1234567 % 256 is 135
Enter next number for first operand (<= 0 to quit): 0
Done
#include <stdio.h>
int main(void)
{
int a, b;
printf("This program computes moduli.\n");
printf("Enter an integer to serve as the second operand: ");
scanf_s("%d", &b);
printf("Now enter the first operand: ");
while (scanf_s("%d", &a) && a > 0 && b > 0)
{
printf("%d %% %d is %d\n", a, b, a % b);
printf("Enter next number for first operand (<= 0 to quit):");
}
printf("Done");
return 0;
}
运行结果:
9.编写一个程序,要求用户输入一个华氏温度。程序应读取double类型的值作为温度值,并把该值作为参数传递给一个用户自定义的函数Temperatures()。该函数计算摄氏温度和开氏温度,并以小数点后面两位数字的精度显示3种温度。要使用不同的温标来表示这3个温度值。下面是华氏温
度转摄氏温度的公式:
摄氏温度 = 5.0 / 9.0 * (华氏温度 - 32.0)
开氏温标常用于科学研究,0表示绝对零,代表最低的温度。下面是摄氏温度转开氏温度的公式:
开氏温度 = 摄氏温度 + 273.16
Temperatures()函数中用const创建温度转换中使用的变量。在main()函数中使用一个循环让用户重复输入温度,当用户输入 q 或其他非数字时,循环结束。scanf()函数返回读取数据的数量,所以如果读取数字则返回1,如果读取q则不返回1。可以使用==运算符将scanf()的返回值和1作比较,测试两值是否相等。
#include <stdio.h>
int Temperatures(double cht);
int main(void)
{
double chttemp;
printf("请输入一个华氏温度:");
while (scanf_s("%lf", &chttemp) == 1)
{
Temperatures(chttemp);
printf("请输入一个华氏温度:");
}
printf("Done");
return 0;
}
int Temperatures(double cht)
{
const double ct1 = 1.0 / 9.0, ct2 = 32;
const double kt = 273;
printf("华氏温度:%.2lfF\n摄氏温度:%.2lfC\n开氏温度:%.2lfK\n",
cht, ct1 * (cht - ct2), ct1 * (cht - ct2) + 273.16);
return 0;
}
运行结果:
补充:(关系操作符)
这类操作符用于测试操作符之间的各种关系。C提供了所有常见的关系操作符。不过,这组操作符里面存在一个陷阱。这些操作符是:
> >= < <= != ==
前四个操作符的功能一看便知。!=操作符用于测试”不相等“,而==操作符用于测试”相等“。
这些操作符产生的结果都是一个整型,而不是布尔值。如果两端的操作符符合操作符指定的关系,表达式的结果是1,如果不符合,表达式的结果是0. 关系操作符的结果是整型值,所以他可以赋值给整型常量,但通常他们用于if或while语句中,作为测值表达式。
请记住这些语句的工作方式:
表达式的结果如果是0,他被认为是假;表达式的结果如果是任何非零值,他被认为是真。所有关系操作符的工作原理相同,如果操作符两端的的操作符不发了它指定的关系,表达式的结果为0。因此但从功能上说,我们不需要额外的布尔值数据类型。