C Primer Plus 第六章循环控制语句学习笔记

小结

C语言有3种循环:forwhiledo while

循环是一个强大的编程工具。在创建循环时,要特别注意以下3个方面:
1、注意循环的测试条件要能使循环结束;
2、确保循环测试中的值在首次使用之前已初始化;
3、确保循环在每次迭代都更新测试的值。

while语句和for语句提供了入口条件循环(即在循环的每次迭代之前检查测试条件,所以有可能根本不执行循环体中的内容。)。for语句特别适用于需要初始化和更新的循环。使用逗号运算符可以在for循环中初始化和更新多个变量。有些场合也需要使用出口条件循环(即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次。),C为此提供了do while语句

典型的while循环设计的伪代码如下:

获得初值
while (值满足测试条件)
{
        处理该值
        获取下一个值
}

for循环也可以完成相同的任务:
for (获得初值; 值满足测试条件; 获得下一个值)
处理该值

下面是do while循环的通用形式:
do
statement
while ( expression );

在 expression 为假或 0 之前重复执行循环体中的内容,statement部分可是一条简单语句或复合语句。

C通过求值来处理测试条件,结果为0表示假0表示真。带关系运算符的表达式常用于循环测试,它们有些特殊。如果关系表达式为真,其值为1;如果为假,其值为0。这与新类型Bool的值保持一致。

如何选择使用哪一种循环?首先,确定是需要入口条件循环还是出口条件循环。通常,入口条件循环用得比较多。那么,假设需要一个入口条件循环,用for循环还是while循环?这取决于个人喜好,因为二者皆可。一般而言,当循环涉及初始化更新变量时,用for循环比较合适,而在其他情况下用while循环更好。

数组由相邻的内存位置组成,只储存相同类型的数据。记住,数组元素的编号从 0 开始,所有数组最后一个元素的下标一定比元素数目少1。
创建一个有20个元素的数组hippos,其元素从hippos[0]~hippos[19]。我们利用循环可以很方便地操控数组的下标。

double hippos[20];

数组的类型可以是任意数据类型。

int nannies[22]; /* 可储存22个int类型整数的数组 */
char actors[26]; /* 可储存26个字符的数组 */
long big[500];  /* 可储存500个long类型整数的数组 */

可以把字符串储存在char类型的数组中(一般而言,char类型数组的所有元素都储存char类型的值)。如果char类型的数组末尾包含一个表示字符串末尾的空字符\0,则该数组中的内容就构成了一个字符串。

使用函数涉及3个步骤:
1、通过函数原型声明函数
2、在程序中通过函数调用使用函数;
3、定义函数

函数原型是为了方便编译器查看程序中使用的函数是否正确,函数定义描述了函数如何工作。现代的编程习惯是把程序要素分为接口部分和实现部分,例如函数原型和函数定义。接口部分描述了如何使用一个特性,也就是函数原型所做的;实现部分描述了具体的行为,这正是函数定义所做的。

复习题

1.写出执行完下列各行后quack的值是多少。后5行中使用的是第1行quack的值。
int quack = 2;
quack += 5;
quack *= 10;
quack -= 6;
quack /= 8;
quack %= 3;

2,7,70,64,8,2。

2.假设value是int类型,下面循环的输出是什么?
for(value=36;value>0;value/=2)
printf("%3d",value);
如果value是double类型,会出现什么问题?

该循环的输出是:
36 18 9 4 2 1
如果 value 是 double 类型,即使 value 小于1,循环的测试条件仍然为真。循环将一直执行,直到浮点数下溢生成0为止。另外,value是double类型时,%3d转换说明也不正确。

3.用代码表示以下测试条件:
a.x大于5
b.scanf() 读取一个名为x的double类型值且失败
c.X的值等于5

x > 5;
scanf("%lf",&x) != 1;
x == 5;

4.用代码表示以下测试条件:

a.scanf() 成功读入一个整数
b. X不等于
c. X大于或等于20

scanf("%d",&x) == 1;
x != 5;
x >= 20;

5.下面的程序有点问题,请找出问题所在。

#include <stdio.h>
int main(void)
{                  /* 第3行 */
int i, j, list(10);       /* 第4行 */
for (i = 1, i <= 10, i++)    /* 第6行 */
{               /* 第7行 */
list[i] = 2*i + 3;     /* 第8行 */
for (j = 1, j > = i, j++)  /* 第9行 */
printf(" %d", list[j]); /* 第10行 */
printf("\n");       /* 第11行 */
}                  /* 第12行 */
/*
第4行:应该是 list[10]。
第6行:逗号改为分号。i的范围应该是0~9,不是1~10。
第9行:逗号改为分号。>=改成<=,否则,当i等于1时,该循环将成为无限循环。
第 10 行:在第 10 行和第 11 行之间少了一个右花括号。该右花括号与第7行的左花括号配对,形成一个 for 循环块。
然后在这个右花括号与最后一个右花括号之间,少了一行return 0;
下面是一个正确的版本:
*/
#include <stdio.h>
int main(void)
{
	int i,j,list[10];
    for (i=1;i<=10; i++)
    {
        list[i] = 2*i + 3;
        for(j =1;j<=i;j++)
            printf(" %d", list[j]);
        printf("\n");
    }
    return 0;
}

]10.考虑下面的声明:
double mint[10];
a.数组名是什么?

mint
b.该数组有多少个元素?

10个元素
c.每个元素可以储存什么类型的值?

double类型的值
d.下面的哪一个scanf()的用法正确?
i.scanf("%lf", mint[2])
ii.scanf("%lf", &mint[2])
iii.scanf("%lf", &mint)

d.第 ii 行正确,mint[2]是 double 类型的值,&mingt[2]是它在内存中的位置

11.Noah先生喜欢以2计数,所以编写了下面的程序,创建了一个储存
2、4、6、8等数字的数组。这个程序是否有错误之处?如果有,请指出。

#include <stdio.h>
#define SIZE 8
int main(void)
{
    int by_twos[SIZE];
    int index;
    for(index=0; index<SIZE; index++)
        by_twos[index]=2*(index+1);
    for(index=0;index<SIZE;index++)
        printf("%d ",by_twos);
    printf("\n");
    return 0;
}
/*
因为第1个元素的索引是0,所以循环的范围应该是0~SIZE-1,而不是1~SIZE。但是,.如果只是这样更改会导致赋给第1个元素的值是0,不是2。所以,应重写这个循环:
for (index=0:index<SIZE;index++)
by twos[index]=2*(index+ 1);
与此类似,第2个循环的范围也要更改。另外,应该在数组名后面使用数组索引:
for(index=0:index< SIZE;index++)
printf("号d ",by twos[index]);
*/
#include<stdio.h>
#define SIZE 8
int main(void)
{
    int by_twos[SIZE];
    int index;
    for(index=0; index<SIZE; index++)
    	by_twos[index]=2*(index+1);
    for(index=0;index<SIZE;index++)
    	printf("%d ",by_twos[index]);
    printf("\n");
    return 0;
}

12.假设要编写一个返回long类型值的函数,函数定义中应包含什么?

该函数应声明为返回类型为 long,并包含一个返回 long 类型值的 return 语句。

13.定义一个函数,接受一个int类型的参数,并以long类型返回参数的平方值。

把 num 的类型强制转换成 1ong 类型,确保计算使用 1ong 类型而不是 int 类型。在 int 为16位的系统中,两个 int 类型值的乘积在返回之前会被截断为一个 int 类型的值,这可能会丢失数据。

long square(int num)
{
    return ((long)num)*num;
}

编程练习

1.编写一个程序,创建一个包含26个元素的数组,并在其中储存26个小写字母。然后打印数组的所有内容。

#include <stdio.h>
#define SIZE 26
int main( void )
{
	char lcase[SIZE];
	int i;
	for (i = 0; i < SIZE; i++)
		lcase[i] = 'a' + i;
	for (i = 0; i < SIZE; i++)
		printf("%c", lcase[i]);
	printf("\n");
	return 0;
}

3.使用嵌套循环,按下面的格式打印字母:
F
FE
FED
FEDC
FEDCB
FEDCBA
注意:如果你的系统不使用ASCII或其他以数字顺序编码的代码,可以把字符数组初始化为字母表中的字母:
char lets[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

然后用数组下标选择单独的字母,例如lets[0]是‘A’,等等。

#include <stdio.h>
int main( void )
{
	char let = 'F';
	char start;
	char end;
	for (end = let; end >= 'A'; end--)
	{
		for (start = let; start >= end; start--)
		printf("%c", start);
		printf("\n");
	}
	return 0;
}

6.编写一个程序打印一个表格,每一行打印一个整数、该数的平方、该数的立方。要求用户输入表格的上下限。使用一个for循环。

#include <stdio.h>
int main( void )
{
	int lower, upper, index;
	int square, cube;
	printf("Enter starting integer: ");
	scanf("%d", &lower);
	printf("Enter ending integer: ");
	scanf("%d", &upper);
	printf("%5s %10s %15s\n", "num", "square", "cube");
	for (index = lower; index <= upper; index++)
	{
		square = index * index;
		cube = index * square;
		printf("%5d %10d %15d\n", index, square, cube);
	}
	return 0;
}

8.编写一个程序,要求用户输入两个浮点数,并打印两数之差除以两数乘积的结果。在用户输入非数字之前,程序应循环处理用户输入的每对值。

#include <stdio.h>
int main( void )
{
    double n, m;
    double res;
    printf("Enter a pair of numbers: ");
    while (scanf("%lf %lf", &n, &m) == 2)
    {
        res = (n - m) / (n * m);
        printf("(%.3g - %.3g)/(%.3g*%.3g) = %.5g\n", n, m, n, m, res);
        printf("Enter next pair (non-numeric to quit): ");
    }
    return 0;
}

11.编写一个程序,在数组中读入8个整数,然后按倒序打印这8个整数。

#include <stdio.h>
#define SIZE 8
int main( void )
{
    int vals[SIZE];
    int i;

    printf("Please enter %d integers.\n", SIZE);
    for (i = 0; i < SIZE; i++)
        scanf("%d", &vals[i]);
    printf("Here, in reverse order, are the values you entered:\n");
    for (i = SIZE - 1; i >= 0; i--)
        printf("%d ", vals[i]);
    printf("\n");
    return 0;
}

13.编写一个程序,创建一个包含8个元素的int类型数组,分别把数组元素设置为2的前8次幂。使用for循环设置数组元素的值,使用do while循环显示数组元素的值。

#include <stdio.h>
#define SIZE 8
int main( void )
{
    int twopows[SIZE];
    int i;
    int value = 1; /* 2 to the 0 */
    for (i = 0; i < SIZE; i++)
    {
        twopows[i] = value;
        value *= 2;
    }
    i = 0;
    do
    {
        printf("%d ", twopows[i]);
        i++;
    } while (i < SIZE);
    printf("\n");
    return 0;
}

14.编写一个程序,创建两个包含8个元素的double类型数组,使用循环提示用户为第一个数组输入8 个值。第二个数组元素的值设置为第一个数组对应元素的累积之和。例如,第二个数组的第 4个元素的值是第一个数组前4个元素之和,第二个数组的第5个元素的值是第一个数组前5个元素之和
(用嵌套循环可以完成,但是利用第二个数组的第5个元素是第二个数组的第4个元素与第一个数组的第5个元素之和,只用一个循环就能完成任务,不需要使用嵌套循环)。最后,使用循环显示两个数组的内容,第一个数组显示成一行,第二个数组显示在第一个数组的下一行,而且每个元素都与第一个数组各元素相对应。

#include <stdio.h>
#define SIZE 8
int main(void)
{
    double arr[SIZE];
    double arr_cumul[SIZE];
    int i;
    printf("Enter %d numbers:\n", SIZE);

    for (i = 0; i < SIZE; i++)
    {
        printf("value #%d: ", i + 1);
        scanf("%lf", &arr[i]);
        /* or scanf("%lf", arr + i); */
    }
    arr_cumul[0] = arr[0]; /* set first element */
    for (i = 1; i < SIZE; i++)
        arr_cumul[i] = arr_cumul[i-1] + arr[i];
    for (i = 0; i < SIZE; i++)
        printf("%8g ", arr[i]);
    printf("\n");
    for (i = 0; i < SIZE; i++)
        printf("%8g ", arr_cumul[i]);
    printf("\n");
    return 0;
}

16.Daphne以10%的单利息投资了100美元(也就是说,每年投资获利相当于原始投资的10%)。Deirdre以 5%的复合利息投资了 100 美元(也就是说,利息是当前余额的 5%,包含之前的利息)。编写一个程序,计算需要多少年Deirdre的投资额才会超过Daphne,并显示那时两人的投资额。

#include <stdio.h>
#define RATE_SIMP 0.10
#define RATE_COMP 0.05
#define INIT_AMT 100.0
int main( void )
{
    double daphne = INIT_AMT;
    double deidre = INIT_AMT;
    int years = 0;
    while (deidre <= daphne)
    {
        daphne += RATE_SIMP * INIT_AMT;
        deidre += RATE_COMP * deidre;
        ++years;
    }
    printf("Investment values after %d years:\n", years);
    printf("Daphne: $%.2f\n", daphne);
    printf("Deidre: $%.2f\n", deidre);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值