第六章 C控制语句:循环

GitHub地址,欢迎 star

6.1 再探 while 循环

经过上一章的学习,读者已经熟悉了 while 循环。这里,我们用一个程序来回顾一下。

/* 根据用户输入的整数求和 */
#include <stdio.h>
int main(void)
{
    long num;
    long sum = 0L; /* 把 sum 初始化为0 */
    int status;

    printf("Please enter an integer to be summed ");
    printf("(q to quit): ");
    status = scanf("%ld", &num);
    while(status == 1) /* == 的意思是“等于” */
    {
        sum = sum + num;
        printf("Please enter next integer (q to quit): ");
        status = scanf("%ld", &num);
    }
    printf("Those integers sum to %ld.\n", sum);
    return 0;
}

Please enter an integer to be summed (q to quit): 44
Please enter next integer (q to quit): 33
Please enter next integer (q to quit): 88
Please enter next integer (q to quit): 121
Please enter next integer (q to quit): q
Those integers sum to 286.

6.1.1 程序注释

先看 while 循环,该循环的测试条件是如下表达式:
status == 1
== 运算符是C的相等运算符(equality operator),该表达式判断 status 是否等于 1。

现在,我们来看看该程序的结构。总结如下:
把 sum 初始化为 0
提示用户输入数据
读取用户输入的数据
当输入的数据为整数时,
——输入添加给 sum,
——提示用户进行输入,
——然后读取下一个输入
输入完成后,打印 sum 的值
这叫作 伪代码(pseudocode) ,是一个用简单的句子表示程序思路的方法,它与计算机语言的形式相对应。伪代码有助于设计程序的逻辑。确定程序的逻辑无误之后,再把伪代码翻译成实际的编程代码。

6.2 while 语句

while 循环的通用形式如下:

while(expression)
	statement

statement 部分可以是以分号结尾的简单语句,也可以是用花括号括起来的复合语句。

6.2.1 终止 while 循环

while 循环有一点非常重要:在构建 while 循环时,必须让测试表达式的值有变化,表达式最终要为假。否则,循环就不会终止。

6.2.2 何时终止循环

要明确一点:只有在对测试条件求值时,才决定时终止还是继续循环。

6.2.3 while :入口条件循环

while 循环是使用入口条件的有条件循环。所谓 “有条件” 指的是语句部分的执行取决于测试表达式描述的条件。该表达式是一个 入口条件(entry condition),因为必须满足条件才能进入循环体。

6.2.4 语法要点

使用 while 时,要牢记一点:只有在测试条件后面的单独语句(简单语句或复合语句)才是循环部分。如果入口条件一直为真,这循环会一直执行下去,除非强行关闭程序。这是一个 无限循环(infinite loop)

#include <stdio.h>
int main(void)
{
    int n = 0;
    while(n++ < 3);
    printf("n is %d\n", n);
    printf("That's all this program does.\n");
    return 0;
}

n is 4
That’s all this program does.

在该例中,测试条件后面的单独分号是 空语句(null statement),它什么也不做。在C语言中,单独的分号表示空语句。

注意,为了提高代码的可读性,应该让这个分号独占一行,不要直接把它放在测试表达式同行。这样做一方面让读者更容易看到空语句,一方面也提醒自己和读者空语句是有意而为之。

6.3 用关系运算符和表达式比较大小

while 循环经常依赖测试表达式作比较,这样的表达式被称为 *关系表达式(relational expression)*出现在关系表达式中间的运算符叫做 关系运算符(relational operator)

6.3.1 新的 _Bool 类型

在编程中,表示真或假的变量被称为 布尔变量(Boolean variable) .

#include <stdio.h>
int main(void)
{
    long num;
    long sum = 0L;
    _Bool input_is_good;

    printf("Please enter an integer to be summed ");
    printf("(q to quit): ");
    input_is_good = (scanf("%ld", &num) == 1);
    while(input_is_good)
    {
        sum = sum + num;
        printf("Please enter next integer (q to quit): ");
        input_is_good = (scanf("%ld", &sum) == 1);
    }
    printf("Those integers sum to %ld.\n", sum);
    return 0;
}

注意程序中把比较的结果赋值给 _Bool 类型的变量 input_is_good:
input_is_good = (scanf("%ld", &sum) == 1);
这样做没问题,因为 == 运算符返回的值不是 1 就是 0。顺带一提,从优先级方面考虑的话,并不需要用圆括号把 scanf("%ld", &sum) == 1 括起来。但是,这样做可以提高代码可读性。还要注意,如何为变量命名才能让 while 循环的测试简单易懂:
while(input_is_good)

C99 提供了 stdbool.h 头文件,该头文件让 bool 成为 _Bool 的别名,而且还把 true 和 false 分别定义为 1 和 0 的符号常量。包含该头文件后,写出的代码可以与 C++ 兼容,因为 C++ 把 bool、true、false 定义为关键字。

如果系统不支持 _Bool 类型,导致无法运行该程序,可以把 _Bool 替换成 int 即可。

6.3.2 优先级和关系运算符

关系运算符的优先级比算术运算符(包括 + 和 -)低,比赋值运算符高。这意味着 x > y + 2 和 x > (y + 2) 相同,x = y > 2 和 x = (y > 2) 相同。换言之,如果 y 大于 2,则给 x 赋值 1,否则赋值 0,y 的值不会赋给 x。

关系运算符比赋值运算符的优先级高,因此,x_bigger = x > y; 相当于 x_bigger = (x > y); 。关系运算符之间有两种不同的优先级。
高优先级组: <<= >>=
低优先级组: == !=
与其他大多数运算符一样,关系运算符的结合律也是从左往右。

小结:while 语句

关键字: while
一般注解:
while 语句创建了一个循环,重复执行直到测试表达式为假或 0。while 语句是一种入口条件循环,也就是说,在执行多次循环之前已决定是否执行循环。因此,循环有可能不被执行。循环体可以是简单语句,也可以是复合语句。
形式:

while(expression)
	statement

在 expression 部分为假或 0 之前,重复执行 statement 部分。
示例:

while(n++ < 100)
	printf(" %d %d\n", n, 2 * n + 1); //简单语句
while(fargo < 1000)
{ // 复合语句
	fargo = fargo + step;
	step = 2 * step;
}
小结:关系运算符和表达式

关系运算符:
每个关系运算符都把它左侧的值和右侧的值进行比较。

<	小于
<=	小于或等于
==	 等于
>=	大于或等于
>	大于
!=	不等于

关系表达式:
简单的关系表达式由关系运算符及其运算对象组成。如果关系为真,关系表达式的值为 1;如果关系为假,关系表达式的值为 0;
示例:
5 > 2 为真,关系表达式的值为 1
(2 + a) == a 为假,关系表达式的值为 0

6.4 不确定循环和计数循环

一些 while 循环是 不确定循环(indefinite loop)。所谓不确定循环,指在测试表达式为假之前,预先不知道要执行多少次循环。例如,下面程序通过与用户交互获得数据来计算整数之和。我们事先并不知道用户会输入什么整数。另外,还有一类是 计数循环(counting loop)。这类循环在执行循环之前就知道要重复执行多少次。

// 一个技术循环
#include <stdio.h>
int main(void)
{
    const int NUMBER = 22;
    int count = 1; // 初始化
    
    while(count <= NUMBER) // 测试
    {
        printf("Be my Valentine!\n"); // 行为
        count++; // 更新计数
    }
    return 0;
}

虽然程序运行情况良好,但是定义循环的行为并未阻止在一起,程序的编排并不是很理想。

在创建一个重复执行固定次数的循环中涉及了 3 个行为:
1、必须初始化计数器;
2、计数器与有限的值作比较;
3、每次循环时递增计数器。

while 循环的测试条件执行比较,递增运算执行递增。递增发生在循环的末尾,这可以防止不小心漏掉递增。因此,这样做比将测试和更新组合放在一起(即使用 count++ <= NUMBER)要好,但是计数器的初始化放在循环外,就有可能忘记初始化。实践告诉我们可能会发生的事前终究会发生,所以我们来学习另一种控制语句,可以避免这些问题。

6.5 for 循环

for 循环把上述 3 个行为(初始化、测试和更新)组合在一处。如下程序:

// 使用 for 循环的技术循环
#include <stdio.h>
int main(void)
{
    const int NUMBER = 22;
    int count;

    for(count = 1; count <= NUMBER; count++)
        printf("Be my Valentine!\n");
    return 0;
}

关键字 for 后面的圆括号中有 3 个表达式,分别用两个分号隔开。第 1 个表达式是初始化,只会在 for 循环开始时执行一次。第 2 个表达式是测试条件,在执行循环之前对表达式求值。如果表达式为假(本例中,count 大于 NUMBER 时),循环结束。第 3 个表达式执行更新,在每次循环结束时求值。完整的 for 语句还包括后面的简单语句或复合语句。for 圆括号中的表达式也叫做控制表达式,它们都是完整表达式,所以每个表达式的副作用(如,递增变量)都发生在对下一个表达式求值之前。

6.6 其他赋值运算符:+=、-=、*=、/=、%=

C有许多赋值运算符。最基本、最常见的是 =,它把右侧表达式的值赋给左侧的变量。其他赋值运算符都用于更新变量,其用法都是左侧是一个变量,右侧是一个表达式。赋给变量的新值是根据右侧表达式的值调整后的值。确切的调整方案取决于具体的运算符。例如:

scores += 20	与	scores = scores + 20	相同
dimes -= 2	与	dimes = dimes - 2	相同
bunnies *= 2	与	bunnies = bunnies * 2	相同
time /= 2.73	与	time = time / 2.73	相同
reduce %= 3	与	reduce = reduce % 3	相同
x *= 3 * y + 12	与	x  = x * (3 * y + 12)	相同

6.7 逗号运算符

逗号运算符扩展了 for 循环的灵活性,以便在循环头中包含更多的表达式。例如,打印一类邮件资费(first-class postage rate)的程序(假设邮资为首重 40 美分/盎司,续重 20 美分/盎司)。

// 一类邮资
#include <stdio.h>
int main(void)
{
    const int FIRST_OZ = 46;
    const int NEXT_OZ = 20;
    int ounces, cost;
    printf(" ounces cost\n");
    for(ounces = 1, cost = FIRST_OZ; ounces <= 16; ounces++, cost += NEXT_OZ)
        printf("%5d    $%4.2f\n", ounces, cost / 100.0);
    return 0;
}

该程序在初始化表达式和更新表达式中使用了逗号运算符。初始化表达式中的逗号使 ounces 和 cost 都进行了初始化,更新表达式中的逗号使每次迭代 ounces 递增 1、cost 递增 20(NEXT_OZ 的值是 20)。绝大多数计算都在 for 循环头中进行。

逗号运算符并不局限于在 for 循环中使用,但是这是它最常用的地方。逗号运算符有两个其他性质。首先,它保证了被它分隔的表达式从左往右求值(换言之,逗号使一个序列点,所以逗号左侧项的所有副作用都在程序执行逗号右侧项之前发生)。因此,ounces 在 cost 之前被初始化。在该例中,顺讯并不重要,当如果 cost 的表达式中包含了 ounces 时,顺讯就很重要。

小结:新的运算符

赋值运算符:
+= 把右侧的值加到左侧的变量上
-= 从左侧的变量中减去右侧的值
*= 把左侧的变量乘以右侧的值
/= 把左侧的变量除以右侧的值
%= 左侧变量除以右侧值得到的余数
逗号运算符:
逗号运算符把两个表达式连接成一个表达式,并保证最左边的表达式最先求值。逗号运算符通常在 for 循环头的表达式中用于包含更多的信息。整个逗号表达式的值是逗号右侧表达式的值。

6.8 出口条件循环:do while

while 循环和for 循环都是入口条件循环,即在循环的每次迭代之前坚持测试条件,所以有可能根本不执行循环体中的内容。C语言还有 出口条件循环(exit-condition loop) ,即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次。这种循环被称为 do while 循环。例如:

// 出口条件循环
#include <stdio.h>
int main(void)
{
    const int secret_code = 13;
    int code_entered;

    do
    {
        printf("To enter the triskaidekaphobia therapy club,\n");
        printf("please enter the secret code number: ");
        scanf("%d", &code_entered);
    }while(code_entered != secret_code);
    printf("Congratulations! You are cured!\n");

    return 0;
}

输出:
To enter the triskaidekaphobia therapy club,
please enter the secret code number: 12
To enter the triskaidekaphobia therapy club,
please enter the secret code number: 14
To enter the triskaidekaphobia therapy club,
please enter the secret code number: 13
Congratulations! You are cured!

小结:do while 语句

**关键字:**do while
一般注解:
do while 语句创建一个循环,在 expression 为假或 0 之前重复执行循环体中的内容。do while 语句是一种出口条件循环,即在执行完循环体后才根据测试条件决定是否再次执行循环。因此,该循环至少必须执行一次。statement 部分科室一条简单语句或复合语句。

6.9 如何选择循环

首先,确定是需要入口条件还是出口条件。通常,入口条件循环用得比较多,有一个原因。奇异,一般原则是在执行徐怒吼之前测试条件比较好。其二,测试放在循环的开头,成的可读性更高。另外,在许多应用中,要求在一开始不满足测试条件时就直接跳过整个循环。

6.10 嵌套循环

嵌套循环(nested loop) 指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示数据,也就是说,一个循环处理一行中的所有列,另一个循环处理 所有的行。在外层的叫做外层循环(outer loop),在内层的叫做内层循环(inner loop)。

6.11 数组简介

数组(array) 是按顺序储存的一系列类型相同的值,通过整数下表访问数组中单独的项或元素(element)。用于识别数组元素的数字被称为下标(subscript)、索引(indice)或偏移量(offset)。下标必须是整数,而且要从 0 开始计数。数组的元素被依次储存在内存中相邻的位置。

6.12 关键概念

循环是一个强大的编程工具。在创建循环时,要特别注意一下 3 个方面:

  • 注意循环的测试条件要能使循环结束;
  • 确保循环测试中的值在首次使用之前已初始化;
  • 确保循环在每次迭代都更新测试的值。

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

数组由相邻的内存位置组成,值储存相同类型的数据。记住,数组元素的标号从 0 开始,所有数组最后一个元素的下标一定比元素数目少 1。C编译器不会检查数组下标值是否有效,自己要多留心。

使用函数涉及 3 个步骤:

  • 通过函数原型声明函数;
  • 在程序中通过函数调用使用函数;
  • 定义函数。

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

6.13 本站小结

本章的主题是程序控制。C语言为实现结构化的程序提供了许多工具。while 语句和 for 语句提供了入口条件循环。for 语句特别使用与需要初始化和更新的循环。使用逗号运算符可以在 for 循环中初始化和更新多个变量。又饿场合也需要使用出口条件循环,C为此提供了 do while 语句。

除了关系运算符,本章还介绍了其他的组合赋值运算符。这些运算符通过对其左侧运算对象执行算术运算类修改它的值。

6.14 复习题

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 > 0 将永远满足,进入死循环,而且 转换符 %d 类型也不符,打印出来的数与实际值不相同(实际打印的值为随机数)

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

答案:a、 x > 5;b、scanf("%lf", &x) != 1;c、x = 5

4、用代码表示一下测试条件:
a、scanf() 成功读入一个整数
b、x 不等于 5
c、x 大于或等于 20

答案: a、scanf("%d", &x) == 1;b、x != 5;c、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 行 */

答案:

#include <stdio.h>
int main(void)
{
	int i, j, list[10];

	for(i = 0; i < 10; i++)
	{
		list[i] = 2 * i + 3;
		for(j = 0; j <= i; j++)
			printf(" %d", list[j]);
		printf("\n");
	}
	return 0;
}

6、编写一个程序打印下面的图案,要求使用嵌套循环:

$$$$$$$$
$$$$$$$$
$$$$$$$$
$$$$$$$$

答案:

#include <stdio.h>
int main(void)
{
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 8; j++)
        {
            printf("$");
        }
        printf("\n");
    }
	return 0;
}

7、下面的程序个打印什么内容?
a、

#include <stdio.h>
int main(void)
{
    int i = 0;
     
    while(++i < 4)
        printf("Hi! ");
    do
        printf("Bye! ");
    while (i++ < 8);
    return 0;

}

b、

#include <stdio.h>
int main(void)
{
    int i;
    char ch;
    for(i = 0, ch = 'A'; i < 4; i++, ch += 2 * i)
        printf("%c", ch);
    return 0;

}

答案:a、Hi! Hi! Hi! Bye! Bye! Bye! Bye! Bye! ;b、ACGM

8、假设用户输入的是 Go west, young man!,下面各程序的输出是什么?(在ASCII码中,!紧跟在空格字符后面)

a、

#include <stdio.h>
int main(void)
{
    char ch;
    scanf("%c", &ch);
    while(ch != 'g'){
        printf("%c", ch);
        scanf("%c", &ch);
    }
    return 0;
}

b、

#include <stdio.h>
int main(void)
{
    char ch;
    scanf("%c", &ch);
    while(ch != 'g'){
        printf("%c", ++ch);
        scanf("%c", &ch);
    }
    return 0;
}

c、

#include <stdio.h>
int main(void)
{
    char ch;
    scanf("%c", &ch);
    do
    {
        printf("%c", ch);
        scanf("%c", &ch);
    } while (ch != 'g');

    return 0;
}

d、

#include <stdio.h>
int main(void)
{
    char ch;
    scanf("%c", &ch);
    for(ch = '$'; ch != 'g'; scanf("%c", &ch))
    {
        printf("%c", ch);
    }
    return 0;
}

答案:a、Go west, youn;b、Hp!xftu-!zpvo;c、Go west, young;d、$o west, young;

9、下面的程序打印什么内容?

#include <stdio.h>
int main(void)
{
    int n ,m;
    n = 30;
    while(++n <= 33)
        printf("%d|", n);

    n = 30;

    do
        printf("%d|", n);
    while(++n <= 33);

    printf("\n***\n");

    for(n = 1; n*n < 200; n += 4)
        printf("%d\n", n);

    printf("\n***\n");

    for(n = 2, m = 6; n < m; n *= 2, m+= 2)
        printf("%d %d\n", n , m);

    printf("\n***\n");

    for(n = 5; n > 0; n--)
    {
        for(m = 0; m <= n; m++)
            printf("=");
        printf("\n");
    }
    return 0;
}

答案:

31|32|33|30|31|32|33|
***
1
5
9
13

***
2 6
4 8
8 10

***
======
=====
====
===
==

10、考虑下面的声明:
double mint[10]
a、数组名是什么?
b、该数组有多少个元素?
c、每个元素可以储存什么类型的值?
d、下面的哪一个 scanf() 的用法正确?
i、scanf("%lf", mint[2])
ii、scanf("%lf", &mint[2])
iii、scanf("%lf", &mint)

答案:a、mint;b、10个;c、double;d、ii

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

#include <stdio.h>
#define SIZE 8
int main(void)
{
    int by_twos[SIZE];
    int index;
    
    for(index = 1; index <= SIZE; index++)
        by_twos[index] = 2 * index;
    for(index = 1; index <= SIZE; index++)
        printf("%d ", by_twos);
    printf("\n");
    return 0;
}

答案:1、index 的范围应该是 0 ~ SIZE - 1;2、by_twos[index] = 2 * (index + 1)

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

答案:将函数的返回值类型定义为 long,并添加返回一个 long 类型数字的 return 语句。

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

答案:将函数的返回值类型定义为 long,将函数接收参数类型定义为 int 类型,将该 int 值强制转换为 long 类型(如果计算平方的 int 值过大,计算后的值将超过 int 范围,会丢失精度),计算平方值,并添加返回一个 long 类型数字的 return 语句。

14、下面的程序打印什么内容?

#include <stdio.h>
#define SIZE 8
int main(void)
{
    int k;
    for(k = 1, printf("%d: Hi!\n", k); printf("k = %d\n", k), k*k < 26; k += 2, printf("Now k is %d\n", k))
        printf("k is %d in the loop\n", k);
    return 0;
}

答案:

1: Hi!
k = 1
k is 1 in the loop
Now k is 3
k = 3
k is 3 in the loop
Now k is 5
k = 5
k is 5 in the loop
Now k is 7
k = 7

6.15 编程练习

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

#include <stdio.h>
int main(void)
{
    char ch[] = {'a','b','c','d','e','f','g','g','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    for(int i = 0,length = sizeof(ch); i < length; i++)
    {
        printf("%2c", ch[i]);
    }
    return 0;
}

2、使用嵌套循环,按下面的格式打印字符:

$
$$
$$$
$$$$
$$$$$

答案:

#include <stdio.h>
int main(void)
{
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j <= i; j++){
            printf("$");
        }
        printf("\n");
    }
    return 0;
}

3、使用嵌套循环,按下面的格式打印字符:

F
FE
FED
FEDC
FEDCB
FEDCBA

注意:如果你的系统不使用 ASCII 或其他以数字顺序编码的代码,可以把字符数组初始化为字母表中的字母:
char lets[26] = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;
然后用数组下标选择单独的字母,例如 lets[0] 是 ‘A’ ,等等。
答案:

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

4、使用嵌套循环,按下面的格式打印字符:

A
BC
DEF
GHIJ
KLMNO
PQRSTU

如果你的系统不使用一数字顺序编码的代码,请参照练习 3 的方案解决。
答案:

#include <stdio.h>
int main(void)
{
    char lets[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int index = 0;
    for(int i = 0; i < 6; i++)
    {
        for(int j = 0; j <= i; j++){
            printf("%c", lets[index]);
            index++;
        }
        printf("\n");
    }
    return 0;
}

5、编写一个程序,提示用户输入大写字母。使用嵌套循环以下面金字塔型的格式打印字母:

    A
   ABA
  ABCBA
 ABCDCBA
ABCDEDCBA

打印这样的图形,要根据用户输入的字母来决定。例如,上面的图形是用户输入 E 后的打印结果。提示:用外层循环处理行,每行使用 3 个内层循环,分别处理空格、以升序打印字母、以降序打印字母。如果你的系统不使用一数字顺序编码的代码,请参照练习 3 的方案解决。
答案:

#include <stdio.h>
int main(void)
{
    char lets[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int index = 0;
    for(int i = 0; i < 5; i++)
    {
        for(int j = 5; j > i; j--){
            printf(" ");
        }
        for(int k = 0; k <= i; k++){
            index = k;
            printf("%c", lets[k]);
        }
        for(int l = index - 1; l >= 0; l--){
            printf("%c", lets[l]);
        }
        printf("\n");
    }
    return 0;
}

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

#include <stdio.h>
int main(void)
{
    int start,end;
    printf("Please input start number!\n");
    scanf("%d", &start);
    printf("Please input end number!\n");
    scanf("%d", &end);
    for(; start <= end; start++){
        printf("%2d %2d %2d\n", start, start * start, start * start * start);
    }
    return 0;
}

7、编写一个程序把一个单词读入一个字符数组中,然后倒序打印这个单词。提示:strlen() 函数可用于计算数组最后一个字符的下标。
答案:

#include <stdio.h>
#include <string.h>
int main(void)
{
    char ch[20];
    printf("Please input words!\n");
    scanf("%s", ch);
    int len = strlen(ch);
    for(int i = len - 1; i >= 0; i--){
        printf("%2c", ch[i]);
    }
    printf("\n");
    return 0;
}

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

#include <stdio.h>
int main(void)
{
    float a, b;
    printf("Please input two num!\n");
    while(scanf("%f %f", &a, &b) == 2)
        printf("%f\n", (a - b) / (a * b));
    return 0;
}

9、修改练习 8 ,使用一个函数返回计算的结果。
答案:

#include <stdio.h>
float compute(float a, float b);
int main(void)
{
    float a, b;
    printf("Please input two num!\n");
    while(scanf("%f %f", &a, &b) == 2)
        printf("%f\n", compute(a,b));
    return 0;
}
float compute(float a, float b)
{
    return (a - b) / (a * b);
}

10、编写一个程序,要求用户输入一个上限整数和一个下限整数,计算从上限到下限范围内所有整数的平方和,并显示计算结果。然后程序继续提示用户输入上限和下限整数,并显示结果,直到用户输入的上限整数小于下限整数为止。程序的运行示例如下:
Enter lower and upper integer limits: 5 9
The sums of the squares form 25 to 81 is 255
Enter next set of limits: ** 3 25**
The sums of the squares form 9 to 625 is 5520
Enter next set of linits: ** 5 5**
Done
答案:

#include <stdio.h>
int main(void)
{
    int start, end, sum;
    printf("Enter lower and upper integer limits:");
    while(scanf("%d %d", &start, &end) == 2 && start < end)
    {
        sum = 0;
        for(int i = start; i <= end; i++)
        {
            sum += i * i;
        }
        printf("The sums of the squares form %d to %d is %d\n", start * start, end * end, sum);
        printf("Enter next set of limits:");
    }
    printf("Done\n");
    return 0;
}

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

#include <stdio.h>
int main(void)
{
    int size = 8;
    int it[8];
    for(int i = 0; i < size; i++)
    {
        scanf("%d", &it[i]);
    }
    for(int i = size - 1; i >= 0; i--)
    {
        printf("%2d", it[i]);
    }
    return 0;
}

12、考虑下面两个无限序列:
1.0 + 1.0 / 2.0 + 1.0 / 3.0 + 1.0 / 4.0 + …
1.0 - 1.0 / 2.0 + 1.0 / 3.0 - 1.0 / 4.0 + …
编写一个程序计算这两个无限序列的总和,直到到达某次数。提示:奇数个 -1 相乘得 -1,偶数个 -1 相乘得 1。让用户交互地输入指定的次数,当用户输入 0 或负值时结束输入。查看运行 100 项、1000 项、10000项后的总和,是否发现每个序列都收敛于某值?
答案:

#include <stdio.h>
int main(void)
{
    printf("100 times\n");
    float sum1 = 0;
    float sum2 = 0;
    for(float i = 1.0; i < 101; i++)
    {
        sum1 += (1.0 / i);
        if((int)i % 2 == 0)
        {
            sum2 -= (1.0 /i);
        }
        else
        {
            sum2 += (1.0 / i);
        }
    }
    printf("%f\n",sum1);
    printf("%f\n",sum2);

    printf("1000 times\n");
    float sum3 = 0;
    float sum4 = 0;
    for(float i = 1.0; i < 1001; i++)
    {
        sum3 += (1.0 / i);
        if((int)i % 2 == 0)
        {
            sum4 -= (1.0 /i);
        }
        else
        {
            sum4 += (1.0 / i);
        }
    }
    printf("%f\n",sum3);
    printf("%f\n",sum4);

    printf("10000 times\n");
    float sum5 = 0;
    float sum6 = 0;
    for(float i = 1.0; i < 10001; i++)
    {
        sum5 += (1.0 / i);
        if((int)i % 2 == 0)
        {
            sum6 -= (1.0 /i);
        }
        else
        {
            sum6 += (1.0 / i);
        }
    }
    printf("%f\n",sum5);
    printf("%f\n",sum6);
    return 0;
}

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

#include <stdio.h>
int power(int count);
int main(void)
{
    int ar[8];
    for(int i = 1; i < 9; i++)
    {
        ar[i - 1] = power(i);
    }

    int i = 0;
    do
    {
        printf("%4d", ar[i]);
        i++;
    }while(i < 8);
    printf("\n");
    return 0;
}
int power(int count)
{
    int sum = 2;
    int base = 2;
    for(int i = 1; i < count; i++)
    {
        sum *= 2;
    }
    return sum;
}

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

#include <stdio.h>
int main(void)
{
    double ar1[8];
    double ar2[8];
    for(int i = 0; i < 8; i++)
    {
        printf("Please input integer\n");
        scanf("%lf", &ar1[i]);
    }

    int sum = 0;
    for(int i = 0; i < 8; i++)
    {
        sum += ar1[i];
        ar2[i] = sum;
    }
    for(int i = 0; i < 8; i++)
    {
        printf("%10.2lf", ar1[i]);
    }
    printf("\n");
    for(int i = 0; i < 8; i++)
    {
        printf("%10.2lf", ar2[i]);
    }
    printf("\n");
    return 0;
}

15、编写一个程序,读取一行输入,然后把输入的内容倒序打印出来。可以把输入储存在 char 类型的数组中,假设每行字符不超过 255。回忆一下,根据 %c 转换说明,scanf() 函数一次只能从输入中读取一个字符,而且在用户按下 Enter 键时 scanf() 函数会生成一个换行字符(\n)。
答案:

#include <stdio.h>
#include <string.h>
int main(void)
{
    char ch[255];
    printf("please input a line words!\n");
    scanf("%s",ch);
    for(int i = strlen(ch) - 1; i >= 0; i--)
    {
        printf("%c", ch[i]);
    }
    printf("\n");
    return 0;
}

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

#include <stdio.h>
int main(void)
{
    float daphneMoney = 100;
    float daphneInterest = 0.1;
    float deirdreMoney = 100;
    float deirdreInterest = 0.05;
    int years = 1;
    do
    {
        daphneMoney += 100 * daphneInterest;
        deirdreMoney = deirdreMoney + deirdreMoney * deirdreInterest;
        years++;
    }while(daphneMoney > deirdreMoney);
    printf("need %d years Deirdre's money more than Daphne, Deirdre's money is %0.2f, Daphne's money is %0.2f\n", years, deirdreMoney, daphneMoney);
    return 0;
}

17、Chuckie Lucky 赢得了 100 万美元(税后),他把奖金存入年利率 8% 的账户。在每年的最后一天。Chuckie 取出 10万美元。编写一个程序,计算多少年后 Chuckie 会取完账户的钱?
答案:

#include <stdio.h>
int main(void)
{
    float money = 100;
    int years = 1;
    do
    {
        money += (money * 0.08);
        money -= 10;
        years++;
    }while(money > 0.0);
    printf("after %d years Chuckie doesn't have any money %f", years, money);
    return 0;
}

18、Rabnud 博士加入了一个社交圈。起初他有 5 个朋友。他注意到他的朋友数量以下面的方式增长。第 1 周少了 1 个朋友,剩下的朋友数量翻倍;第 2 周少了 2 个朋友,剩下的朋友数量翻倍。一般而言,第 N 周少了 N 个朋友,剩下的朋友数量翻倍。编写一个程序,计算并显示 Rabnud 博士每周的朋友数量。该程序一直运行,直到超过邓巴数(Dunbar’s number)。邓巴数是粗略估算一个人在社交圈中有稳定关系的成员的最大值,该值大约是 150。
答案:

#include <stdio.h>
int main(void)
{
    int friends = 5;
    int weeks = 1;
    do
    {
        friends = (friends - weeks) * (friends - weeks);
        weeks++;
        printf("%d week Rabnud has %d friends\n", weeks, friends);
    }while(friends < 150);
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值