第1章 基础知识
1.1 进制转换
计算机信息的编码有很多种,二进制、八进制、十进制及十六进制都是常用的编码。在编程和应用过程中,经常遇到它们之间的互换。本节介绍的几个程序就实现了进制间的转换。
实例001 十进制转换为十六进制
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\001
实例说明
在C语言程序中,主要使用十进制数。有时为了提高效率或其他一些原因,也会使用八进制或十六进制数。十进制和十六进制数之间可以直接转换,不需要复杂的过程,运行结果如图1.1所示。
图1.1 十进制转换为十六进制
技术要点
主要利用输入、输出格式控制符。C语言规定,“%x”和“%d”分别代表十六进制和十进制数的输入和输出格式控制符。
注意:在使用printf()及scanf()函数时要注意格式,尤其是scanf()函数,scanf("%d",&i);中的&符号不要忘记写。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件stdio.h。代码如下:
#include <stdio.h>
(3)利用格式输入函数scanf(),从键盘中获得一个十进制整数,利用格式输出函数将转换后的结果输出。
(4)/*…*/中为程序注释。
(5)主要程序代码如下:
main() /*main()主函数*/ { int i; /*定义一个整型变量i*/ printf("please input decimalism number:\n"); /*双引号内普通字符原样输出并换行*/ scanf("%d",&i); /*scanf()函数以十进制形式获得i的值*/ printf("the hex number is %x",i); /*将i的值以十六进制形式输出*/ }
举一反三
根据本实例,读者可以:
实现十进制转二进制或八进制。
实现二进制、十六进制或八进制转十进制。
实例002 十进制转换为二进制
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\002
实例说明
实例001中介绍了一种较为简单的转换方式,其实进制间相互转换的方式有好多种,本实例也仅为其中一种,目的就是给大家编程提供一种思路,即怎样将平时在纸上运算的过程写入程序中。运行结果如图1.2所示。
图1.2 十进制转换为二进制
技术要点
将十进制数转换为二进制数的具体过程有以下几个要点。
(1)要用数组来存储每次对2取余的结果,所以在数据类型定义的时候要定义数组,并将其全部数据元素赋初值为0。
(2)两处用到for循环,第一次for循环为0~14(本例中只考虑基本整型中的正数部分的转换,所以最高位始终为0),第二次for循环为15~0,这里大家要注意不能改成0~15,因为在将每次对2取余的结果存入数组时是从a[0]开始存储的,所以输出的时候就要从a[15]开始输出,这也符合我们平时计算的过程。
(3)%、/的应用,%模运算符,或称求余运算符,%两侧均应为整型数据。/除法运算符,两个整数相除的结果为整数,运算的两个数中有一个数为实数,则结果是double型的。
注意:for循环体中有多个语句要执行而不是一句,所以{}要加在适当位置,不要忘记写。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include <stdio.h>
(3)数据类型声明,数组元素赋初值均为0。
(4)使用输入函数获得要进行转换的十进制数。
(5)两个for循环语句实现十进制转换二进制的过程,并将最结果输出。
(6)第二个for循环中if条件语句作用使输出结果更直观。
(7)主要程序代码如下:
main() { int i,j,n,m; /*定义变量i,j,n,m*/ int a[16] = { 0 }; /*定义数组a,元素初始值为0*/clrscr(); /*清屏*/ printf("please input the decimalism number(0~32767):\n");/*输出双引号内普通字符*/ scanf("%d",&n); /*输入n的值*/ for(m=0;m<15;m++) /*for循环从0~14,最高为符号位,本例始终为0*/ { i=n%2; /*取2的余数*/ j=n/2; /*取被2整除的结果*/ n = j; a[m]=i; /*将余数每次的余数存入数组a中*/ } for(m = 15; m >= 0; m--) { printf("%d",a[m]); /*for循环,将数组中的16个元素从后往前输出*/ if(m % 4 = = 0) printf(""); /*每输出4个元素,输出一个空格*/ } }
举一反三
根据本实例,读者可以:
实现十进制(基本整型中的负数部分)转二进制。
实现二进制、十六进制或八进制转十进制。
实例003 n进制转换为十进制
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\003
实例说明
编程实现任意输入一个数并输入其进制,即可将该数转换为十进制输出。运行结果如图1.3所示。
图1.3 十进制转换为十六进制
技术要点
程序中用到了字符串函数strupr()和strlen(),前者用于将括号内指定字符串中的小写字母转换为大写字母,其余字符串不变,后者用于求括号中指定字符串的长度,即有效字符的个数。使用这两个函数前应在程序开头加入如下语句:
#include<string.h>
本例的主要思路是用字符型数组a存放一个n进制数,再对数组中的每个元素进行判断,如果是0~9的数字则进行以下处理:
t = a[i] - '0';
如果是字母则进行以下处理:
t = a[i] - 'A' + 10;
如果输入的数据与进制不符,则输出数据错误并退出程序。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include <stdio.h> #include <string.h>
(3)开始主函数的编写,从键盘中输入数据并输入其进制,如果数据与进制不符则输出错误并退出程序,否则判断是数据还是字母并进行相应处理。
(4)将最终得出的结果t1输出。
(5)主要程序代码如下:
main() { long t1; int i, n, t, t3; char a[100]; printf("please input a number string:\n"); gets(a); /*输入n进制数存到数组a中*/ strupr(a); /*将a中的小写字母转换成大写字母*/ t3=strlen(a); /*求出数组a的长度*/ t1=0; /*为t1赋初值0*/ printf("please input n(2or8or16):\n"); scanf("%d",&n); /*输入进制数*/ for(i = 0; i < t3; i++) { if(a[i]-'0'>=n&&a[i]<'A'||a[i]-'A'+10>=n) /*判断输入的数据和进制数是否相符*/ { printf("data error!!"); /*输出错误*/ exit(0); /*退出程序*/ } if(a[i]>='0'&&a[i]<='9') /*判断是否为数字*/ t=a[i]-'0'; /*求出该数字赋给t*/ else if(n>=11&&(a[i]>='A'&&a[i]<='A'+n-10)) /*判断是否为字母*/ t=a[i]-'A'+10; /*求出字母所代表的十进制数*/ t1=t1*n+t; /*求出最终转换成的十进制数*/ } printf("the decimal is %ld\n",t1); /*将最终结果输出*/ }
举一反三
根据本实例,读者可以:
实现十进制数转换为n进制数。
实现n进制数转换为m进制数。
实例004 以IP地址形式输出
这是一个自娱自乐的实例
实例位置:光盘\mingrisoft\01\004
实例说明
任意输入32位的二进制数,编程实现将该二进制数转换成IP地址形式。例如:
输入:11111111111111111111111100000000
输出:255.255.255.0
运行结果如图1.4所示。
图1.4 以IP地址形式输出
技术要点
本实例主要通过将输入的二进制数以每8位数为一个单位分开,再通过自定义的函数将这8位二进制数转换成对应的十进制数。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include<stdio.h>
(3)自定义bin_dec()函数,作用是将二进制数转换为十进制数。代码如下:
int bin_dec(int x,int n) /*自定义函数将二进制数转换成十进制数*/ { if(n==0) /*递归结束条件*/ { return 1; } return x*bin_dec(x,n-1); /*递归调用bin_dec()函数*/ }
(4)主函数程序代码如下:
main() { int i; int ip[4] ={0}; char a[33]; /*存放输入的二进制数*/ printf("please input binary number:\n"); scanf("%s",a); /*二进制数以字符串形式读入*/ for(i = 0; i < 8; i++) { if(a[i] = = '1') { ip[0]+=bin_dec(2,7-i); /*计算0~7转换的结果*/ } } for(i = 8; i < 16; i++) { if(a[i] = = '1') { ip[1]+=bin_dec(2,15-i); /*计算8~15转换的结果*/ } } for(i = 16; i < 24; i++) { if(a[i] = = '1') { ip[2]+=bin_dec(2,23-i); /*计算16~23转换的结果*/ } } for(i = 24; i < 32; i++) { if(a[i] = = '1') { ip[3]+=bin_dec(2,31-i); /*计算24~31转换的结果*/ } if(a[i] = = '\0') { break; } } printf("ip:\n"); printf("%d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]); /*将最终结果以IP形式输出*/ }
举一反三
根据本实例,读者可以:
实现输入一个十进制数,在屏幕上输出其原码。
实现输入一个十进制的负数,在屏幕上输出其补码。
1.2 条件判断
从程序流程的角度来看,程序可以分为3种基本结构,即顺序结构、分支结构、循环结构。这3种基本结构可以组成各种复杂程序。C语言提供了多种语句来实现这些程序结构。本节介绍的这几个实例就是教读者如何来实现分支结构,使读者对C程序有进一步的认识,为后面各章的学习打下基础。
实例005 a2+b2
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\005
实例说明
编程要求输入整数a和b,若a2+b2的结果大于100,则输出a2+b2的值,否则输出a+b的结果。运行结果如图1.5所示。
图1.5 a2+b2
技术要点
本实例的基本思路是首先求出输入的两个数的平方和,再对该平方和进行判断,如果平方和大于100,则将平方和输出,否则输出a+b的值。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include<stdio.h>
(3)利用if语句对计算出的平方和进行判断,如果大于100,则将平方和输出,否则输出a+b的值。
(4)主函数程序代码如下:
main() { int a,b,x,y; /*定义变量为基本整型*/ printf("please input a and b:\n"); scanf("%d%d",&a,&b); /*输入变量a和b的值*/ x=a*a+b*b; /*计算出平方和*/ if(x>100) /*判断平方和是否大于100*/ { printf("a^2+b^2="); printf("%d",x); /*如果平方和大于100,则输出平方和*/ } else printf("a+b=%d",a+b); /*如果平方和不大于100,则输出两数之和*/ }
举一反三
根据本实例,读者可以:
输入整数a和b,若a3-b3小于0,则输出a-b的值,否则输出a3-b3的结果。
输入整数a和b,若a-b的结果为奇数,则输出该值,否则输出提示信息。
实例006 判断闰年
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\006
实例说明
从键盘上输入一个表示年份的整数,判断该年份是否是闰年,判断后的结果显示在屏幕上。运行结果如图1.6所示。
图1.6 判断闰年
技术要点
(1)计算闰年的方法用自然语言描述如下:如果某年能被4整除但不能被100整除,或者该年能被400整除则该年为闰年。在本实例中我们用如下表达式来表示上面这句话:
year%4= =0&&year%100!=0)||year%400= =0
除本实例外判断闰年还有许多方法,下面给出的算法(伪代码描述)也为其中一种:
{ If(某年能被400整除) 输出是闰年; Else if(该年能被100整除) 输出不是闰年; Else if(该年能被4整除) 输出是闰年; Else 输出不是闰年; }
这种算法略显繁琐,读者可以根据实际情况选择适当的方法。
(2)将判断闰年的自然语言转换成C语言要求的语法形式时,需要用到逻辑运算符&&、||和!,具体使用规则如下。
● && 逻辑与(相当于其他语言中的AND),a&&b若a,b为真,则a&&b为真。
● || 逻辑或(相当于其他语言中的OR),a||b若a、b之一为真,则a||b为真。
● ! 逻辑非(相当于其他语言中的NOT),a若为真,则!a为假。
● 三者的优先次序是:!—>&&—>||,即“!”为三者中最高的。
注意:程序编写过程中要注意“= =”和“=”使用的区别,“= =”为关系运算符,方向“自左至右”,而“=”是赋值运算符,方向“自右至左”。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件stdio.h。代码如下:
#include <stdio.h>
(3)定义数据类型,本实例中定义year为基本整型。
(4)使用输入函数从键盘中获得表示年份的整数。
(5)使用if语句进行条件判断,如果满足括号内的条件则输出是闰年,否则输出不是闰年。
(6)主要程序代码如下:
main() { int year; /*定义基本整型变量year*/ printf("please input the year:\n"); scanf("%d",&year); /*从键盘输入表示年份的整数*/ if((year % 4==0&&year % 100!=0)||year % 400==0)/*判断闰年条件*/ printf("%d is a leap year",year); /*满足条件的输出是闰年*/ else printf("%d is not a leap year",year); /*否则输出不是闰年*/ }
举一反三
根据本实例,读者可以:
编程实现2009月份表的输出。
编程实现万年历。
实例007 阶梯问题
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\007
实例说明
在你面前有一条长长的阶梯,如果你每步跨2阶,那么最后剩1阶;如果你每步跨3阶,那么最后剩2阶;如果你每步跨5阶,那么最后剩4阶;如果你每步跨6阶,那么最后剩5阶;只有当你每步跨7阶时,最后才正好走完,一阶也不剩。请问这条阶梯至少有多少阶?(求所有三位阶梯数)运行结果如图1.7所示。
图1.7 阶梯问题
技术要点
本实例中的关键是如何来写if语句中的条件,如果这个条件大家能够顺利写出,那整个程序也基本上完成了。根据题意来看,“每步跨2阶,那么最后剩1阶……当每步跨7阶时,最后才正好走完,一阶也不剩”可以看出题的规律就是总的阶梯数对每步跨的阶梯数取余得的结果就是剩余阶梯数,这5种情况是&&的关系,也就说必须同时满足。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include <stdio.h>
(3)用for循环对大于等于100且小于1000的所有3位整数进行筛选。
(4)使用if语句根据题意设置相应的条件,如果满足条件则输出该结果,否则继续下次循环。
(5)主要程序代码如下:
main() { int i; /*定义基本整型变量i*/ for(i=100;i<1000;i++) /*for循环求100~1000的所有3位数*/ if(i%2==1&&i%3==2&&i%5==4&&i%6==5&&i%7==0) /*根据题意写出对应的条件*/ printf("the number of the stairs is %d\n",i);/*输出阶梯数*/ }
举一反三
根据本实例,读者可以:
编程输出国际象棋棋盘。
求1~1000满足用3除余2、用5除余3、用7除余2的所有数并输出,要求每行输出5个数。
实例008 评定成绩
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\008
实例说明
编程对输入的百分制分数给出相应的等级,分数大于等于90为“A”,80~89为“B”,70~79为“C”,60~69为“D”,60分以下为“E”。运行结果如图1.8所示。
图1.8 评定成绩
技术要点
本实例的思路如下:输入成绩,当输入的成绩是100时,我们可以把它看成90分,因为100分和90分都是A等的;对输入的成绩使用除法便求出其高位数字,因为通过高位数字就可以判断出输出的成绩在哪个等级;使用switch语句对取出的高位数字进行选择判断,如果高位数为9则是A等,如果是8则是B等,依此类推,分别出现C、D、E等。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include<stdio.h>
(3)利用算术运算符“/”取输入成绩的高位数,使用switch语句对取出的高位数做选择,根据不同数字,给出不同等级。
(4)主函数程序代码如下:
main() { int score; printf("\nplease enter score(score<=100):"); scanf("%d",&score); /*输入学生成绩*/ if(score==100) /*如果成绩是100则和90是一样的等级*/ score = 90; score=score/10; /*求出成绩的高位数字*/ switch(score) { case 9: printf("the grade is A"); /*等级为A*/ break; case 8: printf("the grade is B"); /*等级为B*/ break; case 7: printf("the grade is C"); /*等级为C*/ break; case 6: printf("the grade is D"); /*等级为D*/ break; default: printf("the grade is E"); /*等级为E*/ } }
举一反三
根据本实例,读者可以:
利用switch语句求输入某年某月某日,判断这一天是这一年的第几天。
企业根据员工创造的利润将工资分为5个等级。利润低于或等于10万元时,为五等;利润高于10万元,低于20万元时,为四等;20万到40万之间时,为三等;60万到100万之间时,为二等;超过100万元时,为一等。从键盘中输入员工创造的利润,输出其工资等级。
1.3 多重循环打印图形
在学习编程的过程中经常能够遇到字符组成的各种图形,对于初学者来说往往不知道该用什么方法实现,本节列举的几个实例就是专门介绍如何使用多重循环实现图形的打印。
实例009 用#打印三角形
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\009
实例说明
用#打印如下所示的三角形,运行结果如图1.9所示。
图1.9 用#打印的三角形
# ### ##### ####### #########
技术要点
本实例中多次用到for循环,以下是对for循环的详细讲解。
for语句的一般形式为:
for(表达式1;表达式2;表达式3)语句
它的执行过成如下。
(1)先求解表达式1。
(2)求解表达式2,若其值为非0,则执行for语句中指定的内嵌语句,然后执行下面第3步。若表达式2值为0,则结束循环,转到下面第(5)步。
(3)求解表达式3。
(4)返回第2步继续执行。
(5)循环结束,执行for语句下面的一个语句。
说明如下。
● 表达式1通常用来给循环变量赋初值,一般是赋值表达式。也允许在for语句外给循环变量赋初值,此时可以省略该表达式。
● 表达式2通常是循环条件,一般为关系表达式或逻辑表达式。如果表达式2省略,既不判断循环条件,也就是认为表达式2始终为真,则循环将无终止地进行下去。
● 表达式3通常可用来修改循环变量的值,一般是赋值语句。表达式3也可以省略,但此时程序设计者应另外设法保证循环能正常结束。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include<stdio.h>
(3)定义数据类型,本实例中i、j、k均为基本整型。
(4)第一个for循环控制整个图形的行数,本实例中的图形共5行,所以i的范围为1~5。
(5)第二个for循环用来控制空格的数量,这时需要找出每行空格数在图形中的规律,第1行需4个空格,第2行需3个空格,依此类推第5行需0个空格,所以找出其中规律即每行的空格数等于5减去行数,这样就确定了第二个for循环中j的范围。
(6)第三个for循环用来控制输出#的数量,同样也要找出每行需输出的字符个数的规律,第1行输出1个#,第2行输出3个#,依此类推第5行输出9个#,所以找出其中规律即每行需输出#的个数等于行数的2倍减1,这样也就确定了第三个for循环中k的范围。
(7)主要程序代码如下:
main() { int i,j,k; /*定义变量i,j,k为基本整型*/ for(i=1;i<=5;i++) /*控制行数*/ { for(j=1;j<=5-i;j++) /*控制空格数*/ printf(" "); for(k=1;k<=2*i-1;k++) /*控制打印#号的数量*/ printf("#"); printf("\n"); } }
举一反三
根据本实例,读者可以:
编写程序输出如下图形:
123456 612345 561234 456123
用*打印菱形:
* *** ***** ******* ***** *** *
实例010 用*打印图形
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\010
实例说明
用*打印如下图形,运行结果如图1.10所示。
图1.10 用*打印图形
***** ***** ***** ***** *****
技术要点
本实例使用了字符数组,可能这时有读者会问输出这个图形用上个实例讲过的方法可以吗?答案是肯定的,当然可以。像本实例这种每行个数是一定的,通常也可以采用字符数组这种方法。程序中字符数组是一个一个输出的,当然也可以用“%s”的形式将数组中的元素一次性输出,也就是将程序中的如下代码:
for(k=0;k<5;k++) printf("%c",a[k]);
用下面的语句:
printf("%s",a);
替代,此时千万不要忘记将数组长度从5改为6,因为字符串在存储的时候会自动在结尾处加“\0”作为结束标志。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include<stdio.h>
(3)定义数据类型,本实例中i、j、k均为基本整型,数组a为字符型。
(4)第一个for循环控制整个图形的行数,本实例中的图形共5行,所以i的范围为0~4。
(5)第二个for循环用来控制空格的数量。
(6)第三个for循环用将数组a中的元素逐个输出。
(7)主要程序代码如下:
main() { char a[5] = { '*', '*', '*', '*', '*' }; /*定义字符型数组,五个元素初值均为'*'*/ int i,j,k; /*定义变量i,j,k为基本整型*/ for(i=0;i<5;i++) /*输出5行*/ { for(j=1;j<=i;j++) /*输出空格的数量随着行数的变化而变化*/ printf(" "); for(k = 0; k < 5; k++) printf("%c",a[k]); /*将a数组中的元素输出*/ printf("\n"); /*每输出一行后换行*/ } }
举一反三
根据本实例,读者可以:
用*打印如下图形:
****** ****** ****** ****** ****** ******
编写程序输出如下图形:
#*******# #*****# #***# #*# #
实例011 绘制余弦曲线
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\01\011
实例说明
编程实现用“*”绘制余弦曲线,运行结果如图1.11所示。
图1.11 绘制余弦曲线
技术要点
绘制余弦曲线用到了反余弦函数acos(),通过纵坐标的值来求出横坐标的值,确定了横坐标的值,其对称位置的横坐标值也就可以确定,即用62 减去确定的横坐标值,那么为什么是62呢?这里的62是一个近似值即2π×10。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h> #include<math.h>
(3)调用acos()函数计算出相应的横坐标位置,使用for循环在未到该位置之前输出空格,直到到达指定位置再输出*,对称位置相同。
(4)主函数程序代码如下:
main() { double y; int x, m; for(y=1;y>= -1;y-=0.1) /*0到π,π到2π分别绘制21个点*/ { m=acos(y)*10; /*求出对应的横坐标位置*/ for(x = 1; x < m; x++) printf(""); /*画*前画空格数*/ printf("*"); /*画**/ for(;x<62-m;x++) /*画出对称面的**/ printf(" "); printf("*\n"); } getch(); }
举一反三
根据本实例,读者可以:
绘制正切曲线。
绘制余切曲线。
实例012 打印乘法口诀表
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\012
实例说明
打印乘法口诀表。运行结果如图1.12所示。
图1.12 打印乘法口诀表
技术要点
如何打印乘法口诀表关键是要分析程序的算法思想,本实例中两次用到for循环,第一次for循环即将它看成乘法口诀表的行数,同时也是每行进行乘法运算的第一个因子,第二个for循环范围的确定建立在第一个for循环的基础上,即第二个for循环的最大取值是第一个for循环中变量的值。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中i、j均为基本整型。
(4)第一个for循环控制乘法口诀表的行数及每行乘法中的第一个因子。本实例为九九乘法口诀表,故变量i的取值范围为1~9。
(5)第二个for循环中变量j是每行乘法运算中的另一个因子,运行到第几行j的最大值也就为几。
(6)主要程序代码如下:
main() { int i,j; /*定义i,j两个变量为基本整型*/ for(i=1;i<=9;i++) /*for循环i为乘法口诀表中的行数*/ { for(j=1;j<=i;j++) /*乘法口诀表中的另一个因子,取值范围受一个因子i的影响*/ printf("%d*%d=%d",i,j,i*j); /*输出i,j及i*j的值*/ printf("\n"); /*打完每行值后换行*/ } }
举一反三
根据本实例,读者可以:
利用循环输出以下图形:
*#*#*#*#$
利用循环输出以下图形:
0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0
实例013 打印杨辉三角
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\013
实例说明
打印出以下的杨辉三角形(要求打印出10行)。运行结果如图1.13所示。
图1.13 打印杨辉三角
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 ……
技术要点
要想打印出杨辉三角首先得找出图形中数字间的规律,从图形中我们分析出这些数字间有以下规律。
● 每一行的第一列均为1。
● 对角线上的数字也均为1。
● 除每一行第一列和对角线上的数字外,其余数字均等于其上一行同列数字与其上一行前一列数字之和。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中i、j、a[11][11]均为基本整型。
(4)第一个for循环中变量i的范围为1~10,循环体中语句a[i][i]将对角线元素置1,语句a[i][1]=1将每行中的第一列置1。
(5)用两个for循环实现除对角线和每行第一个元素外其他元素的赋值过程,即a[i][j]=a[i-1][j-1]+a[i-1][j]。
(6)再使用for循环的嵌套将数组a中的所有元素输出。
(7)主要程序代码如下:
main() { int i,j,a[11][11]; /*定义i,j,a[11][11]为基本整型*/ for(i=1;i<11;i++) /*for循环i的范围从1到10*/ { a[i][i]=1; /*对角线元素全为1*/ a[i][1]=1; /*每行第一列元素全为1*/ } for(i=3;i<11;i++) /*for循环范围从第3行开始到第10行*/ for(j=2;j<=i-1;j++) /*for循环范围从第2列开始到该行行数减一列为止*/ a[i][j]=a[i-1][j-1]+a[i-1][j]; /*第i行j列等于第i-1行j-1列的值加上第i-1行j列的值*/ for(i = 1; i < 11; i++) { for(j = 1; j <= i; j++) printf("%4d",a[i][j]); /*通过上面两次for循环将二维数组a中元素输出*/ printf("\n"); /*每输出完一行进行一次换行*/ } }
举一反三
根据本实例,读者可以:
从键盘中输入如下字母“a、b、c、d、e、f”,输出时的顺序如下:“f、a、b、c、d、e”。
编程实现通过循环按行顺序为一个5×5的二维数组data赋1~25的自然数,然后输出该数组的左下半三角形。
1.4 循环的数学应用
循环的应用十分广泛,在1.3节的实例中,我们主要介绍了如何利用循环来输出特殊图形,这一节主要介绍循环另一方面的应用,即在数学方面的应用。
实例014 序列求和
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\014
实例说明
用while循环做一个简单的计算s=1+1/2+1/3+…+1/n。运行结果如图1.14所示。
图1.14 序列求和
技术要点
本实例中用到while循环,这也是实现累加求和的关键,以下是对其使用方法的讲解。
while语句用来实现“当型”循环结构。其一般形式如下:
while(表达式)语句
其语义是:当表达式为非0值时,执行while语句中的内嵌语句。
其特点是:先判断表达式,后执行语句。
说明如下。
● while语句中的表达式一般是关系表达或逻辑表达式,只要表达式的值为真(非0)即可继续循环。
● 循环体如果包含一个以上的语句,应该用花括弧括起来,以复合语句形式出现。如果不加花括弧则while语句的范围知道while后面第一个分号处。
● 在循环体中应有使循环趋向于结束的语句以避免死循环。
提到while语句就不能不提到do-while,首先看下do-while语句的一般形式:
do 循环体语句 while(表达式);
其语义是:先执行一次指定的循环体语句,然后判别表达式,当表达式的值为非零(真)时,返回重新执行循环体语句,如此反复,直到表达式的值等于0为止,此时的循环结束。
其特点是:先执行循环体,然后判断循环条件是否成立。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中i、n均为基本整型,sum为双精度型并赋初值0。
(4)使用scanf函数获取n的值。
(5)当i小于等于n时,执行循环体语句,这里的循环体语句由两个语句组成,所以用{}括起来。第一个语句实现累加求和,而第二个语句是实现变量自加。
(6)将n和sum的值输出。
(7)主要程序代码如下:
main() { int i=1,n; /*定义变量i,j为基本整型并给i赋初值1*/ double sum=0; /*定义变量s为双精度型并赋初值0*/ printf("input n:\n"); scanf("%d",&n); /*scanf函数获取n的值*/ while(i<=n) /*当i小于等于n时,s逐次累加求和*/ { sum = sum + 1.0 /(double)i; i++; } printf("n=%d,sum=%lf\n",n,sum);/*将n与sum的值打印输出*/ }
举一反三
根据本实例,读者可以:
求1~100中所有整数相加的和。
求平均分:任意输入某学生的五门学科成绩,求出总成绩及平均分。
实例015 简单的级数运算
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\015
实例说明
有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13……求出这个数列的前20项之和。运行结果如图1.15所示。
图1.15 简单的级数运算
技术要点
本实例的关键是分析这个分数序列有什么规律,只要找出其中的规律,程序代码的编写就相对简单了许多。
看这个分数序列,我们不难发现前一个分数的分子是后一个分数的分母,并且前一个分数的分子与分母的和是后一个分数的分子。题中要求求出这个数列的前20项之和,那么我们只要让循环执行20次即可。循环语句我们前面已介绍过3种,使用其中任何一种均可,本实例采用for语句。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中n、t均为基本整型,a、b、sum为单精度型并分别赋初值2、1、0。
(4)使用for语句实现求前20项的和。
(5)循环体中第二个语句,即t=a;a=a+b;b=t;,就是借助中间变量t来实现将前一个分数的分子a赋给后一个分数的分母b,将前一个分数的分子a和分母b的和赋给后一个分数的分子a。
(6)将最终所求的和即sum的值输出。
(7)主要程序代码如下:
main() { int n,t; /*定义变量n,t为基本整型*/ float a=2,b=1,sum=0; /*定义变量a,b,sum单精度型并分别赋初值2,1,0*/ for(n=1;n<=20;n++) /*for循环变量n的范围从1到20*/ { sum=sum+a/b; /*累加求和*/ t=a;a=a+b;b=t; /*借助中间变量t完成后一个分数与前一个分数间数值间的转换*/ } printf("sum is %f\n",sum); /*将最终所求的和sum输出*/ }
举一反三
根据本实例,读者可以:
尝试将本实例用while循环编写。
鸡兔共有30只,脚共有90只,编程计算鸡、兔各有多少只。
实例016 用while语句求n!
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\01\016
实例说明
3!=3*2*1,5!=5*4*3*2*1,依此类推n!=n*(n-1)*…*2*1,使用while语句求n!。运行结果如图1.16所示。
图1.16 用while语句求n!
技术要点
(1)在写程序之前首先要理清求 n!的思路。求一个数 n的阶乘也就是用n*(n-1)*(n-2)*…*2*1,那么反过来从1一直乘到n求依然成立。当n为0和1的时候我们单独考虑,此时它们的阶乘均为1。
(2)求得的阶乘的最终结果,这里我们要给它定义为单精度或双精度型,如果定义为整型就很容易出现溢出现象。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中i、n均为基本整型,fac为单精度型并分别赋初值1。
(4)用if语句判断如果输入的数是0或1,输出阶乘是1。
(5)当while语句中的表达式i小于等于输入的数n时执行while循环体中的语句,fac=fac*i作用是当i为2时求2!,当i为3时求3!……当i为n时求n!。
(6)将n的值和最终所求的fac……值输出。
(7)主要程序代码如下:
main() { int i=2,n; /*定义变量i,n为基本整型并为i赋初值2*/ float fac=1; /*定义fac为单精度型并赋初值1*/ printf("please input an interger>=0.\n"); scanf("%d",&n); /*使用scanf函数获取n的值*/ if(n==0||n==1) /*当n为0或1的时候输出阶层为1*/ { printf("factorial is 1.\n"); return 0; } while(i<=n) /*当满足输入的数值大于等于i时执行循环体语句*/ { fac=fac*i; /*实现求阶层的过程*/ i++; /*变量i自加*/ } printf("factorial of %d is:%.2f.\n",n,fac);/*输出n和fac最终的值*/ }
举一反三
根据本实例,读者可以:
要求从键盘中输入三角形的三边判断是否能组成三角形,若可以则输出它的面积和三角形的类型。
计算1-3+5-7+……-99+101的值。
实例017 特殊等式
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\01\017
实例说明
有这样一个等式,xyz+yzz=532,编程求x、y、z的值(xyz和yzz分别表示一个三位数)。运行结果如图1.17所示。
图1.17 特殊等式
技术要点
本实例的算法思想是对 x、y、z 分别进行穷举,由于 x和y均可做最高位,所以x和y不能为0,所以穷举范围为1~9,而z始终做个位,所以z的穷举范围为0~9。对其按照题中要求的等式求和,看和是否等于532,如果等于,则 x、y、z就是所求结果,否则继续寻找。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)对x、y、z进行穷举,判断xyz与yzz之和是否是532,是则将结果输出,否则进行下次判断。
(4)主函数程序代码如下:
main() { int x, y, z, i; for(x=1;x<10;x++) /*对x进行穷举*/ for(y=1;y<10;y++) /*对y进行穷举*/ for(z=0;z<10;z++) /*对z进行穷举,由于是个位所以可以为0*/ { i=100*x+10*y+z+100*y+10*z+z; /*求和*/ if(i==532) /*判断和是否等于532*/ printf("x=%d,y=%d,z=%d\n",x,y,z); /*输入x、y、z最终的值*/ } }
举一反三
根据本实例,读者可以:
有这样一个等式:xyz*yx=10248,编程求x、y、z可能的值。
有这样一个等式:xyz-zyx=297,编程求x、y、z可能的值。
实例018 求一个正整数的所有因子
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\01\018
实例说明
从键盘中输入一个正整数求它的所有因子。运行结果如图1.18所示。
图1.18 求一个整数的所有因子
技术要点
(1)本实例中用到for语句,这里要提到的仍然是for语句中变量i的取值范围,因为实例中要求所有因子,那么编程序的时候就应考虑到从1 到你要求的这个数的本身所有的数是否是这个数的因子,所以i的取值范围从1到你所输入的数n。在今后编程的过程中经常要用到像for、while、do…while这种循环语句,在使用这些语句的时候很关键的一点就是如何确定其中变量的范围,在这个时候就特别需要编程人员考虑问题要全面,另外多做些与此相关的练习也能帮助大家尽快地掌握这部分知识。
(2)实例中要求因子换成比较能接受的话来说就是用一个数除以另一个数,看是否能被整除(余数是否为零),如果能被整除(余数为0)则另一个数为一个数的因子,否则不是因子。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中i、j均为基本整型。
(4)用scanf函数获得要求的数。
(5)当for语句中的表达式满足条件的时候执行if语句,当if语句中的表达式为真,则将j的值输出,否则继续下次循环。
(6)主要程序代码如下:
main() { int i,j; /*定义变量i,j为基本整型*/ printf("please input:\n"); scanf("%d",&i); /*用scanf函数获得i的值*/ for(j=1;j<=i;j++) /*for语句中j的取值范围从1到i*/ if(i%j==0) /*如果i对j取余的结果为0说明j是i的因子*/ printf("%d,",j); /*将每次求出的因子输出*/ }
举一反三
根据本实例,读者可以:
随机产生一个无重复的10个数的序列,找出其中因子有5的所有数。
编程求100~1000之间有多少个数其个位数字之和是5。
实例019 一元钱兑换方案
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\019
实例说明
如果要将整钱换成零钱,那么一元钱可兑换成一角、两角或五角,问有多少种兑换方案。运行结果如图1.19所示。
图1.19 一元钱兑换方案
技术要点
本实例中3次用到for语句,第一个for语句中变量i的范围为1~10,这是如何确定的呢?根据题意知道可将一元钱兑换成一角钱,那么我们就得考虑如果将一元钱全部兑换成一角钱将能兑换多少个?答案显而易见是10,当然一元钱也可以兑换两角或五角而不兑换成一角,所以i的取值范围为0~10,同理可知j(两角)的取值范围为0~5,k(五角)的取值范围为0~2。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,本实例中i、j、k均为基本整型。
(4)嵌套的for循环的使用将所有在取值范围内的数全部组合一次,凡是能使if语句中的表达式为真的则将其输出。
(5)主要程序代码如下:
main() { int i,j,k; /*定义i,j,k为基本整型*/ for(i=0;i<=10;i++) /*i是一角钱兑换个数,所以范围从1到10*/ for(j=0;j<=5;j++) /*j是两角钱兑换个数,所以范围从0到5*/ for(k=0;k<=2;k++) /*k是五角钱兑换个数,所以范围从0到2*/ if(i+j*2+k*5==10) /*三种钱数相加是否等于十*/ printf("yi jiao%d,liang jiao%d,wu jiao%d\n",i,j,k);/*将每次可兑换的方案输出*/ }
举一反三
根据本实例,读者可以:
输出0~9组成的所有无重复的三位数。
从键盘中输入一个不多于5位的正整数,求它是几位数然后逆序打印出各位数字显示在屏幕上。
实例020 对调数问题
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\020
实例说明
一个两位正整数,将它的个位和十位对调,得到另一个两位正整数,我们称这两个正整数互为对调数。现给定一个两位正整数,问能否找出另一个对调后不同的两位正整数,使得这两个正整数之和等于它们各自的对调数之和?例如:63+47=36+74。编写程序为输入的一个两位正整数找到满足如上要求的数或输出“不存在”。运行结果如图1.20所示。
图1.20 对调数问题
技术要点
(1)实例中多次用到continue和break,以下是continue和break使用的相关要点。
● continue语句的一般形式:
continue;
其作用为结束本次循环,即跳过循环体中下面还未执行的语句,接着进行下一次是否执行循环的判断。
● break语句的一般形式:
break;
其作用为提前结束循环,即不再执行循环体中后面的语句及其余的几次循环。
● continue和break语句的区别是:continue语句只结束本次循环,而不是终止整个循环的执行。而break语句则是结束整个循环过程,不再判断执行循环的条件是否成立。
(2)本实例的另一个要点就是如何求一个两位数十位上的数和个位上的数,这里求十位上的数我们采用对10整除的方法,求个位上的数采用对10取余的方法,通过这两次运算就很容易地求出一个两位整数的对调数。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型及判断输入的数是否为符合要求的两位正整数。如不符合条件则提示重新输入,符合条件则通过运算求出其对调数。
(4)寻找另一个满足条件的两位数,若该数满足条件则继续判断其是否符合两数相加等于这两个数的对调数相加之和且这两个数不互为对调数的条件,若满足该条件则按题中要求格式输出,不满足条件结束本次循环继续下次循环条件判断。
(5)j在程序中起到计数作用,若j等于0,这说明没有满足上面条件的两位数,则输出不存在。
(6)主要程序代码如下:
main() { int x,y,z,x1,y1,z1,i,k,n,j=0; /*定义变量的数据类型*/ while(1) { printf("please input an integer\n"); scanf("%d",&n); /*输入函数获得n的值*/ if(n<=10||n>=100) /*当输入的数小于等于10或大于等于100时输出错误*/ { printf("data error\n"); continue; /*跳出本次循环*/ } else if(n%10==0) /*当这个两位数对10取余等于0时输出错误*/ { printf("data error\n"); continue; /*跳出本次循环*/ } else { x=n/10; /*x为输入的两位数中的十位*/ y=n%10; /*y为输入的两位数中的个位*/ z=10*y+x; /*z为n的对调数*/ break; /*跳出循环*/ } } for(i=11;i<100;i++) /*i遍历所有的两位数*/ { if(i%10==0) /*除去所有的对调数是个位的数*/ continue; /*结束本次循环*/ else { x1=i/10; /*x1为i的十位*/ y1=i%10; /*y1为i的个位*/ z1=10*y1+x1; /*z1为i的对调数*/ if(n+i==z+z1&&n!=z1) /*当满足n加i等于n的对调数加i的对调数且n和i不互为对调数*/ { printf("%d+%d=%d+%d\n",n,i,z,z1);/*输出题中要求的表达式形式*/ j++; /*j自加*/ } else continue; /*否则结束本次循环*/ } } if(j==0) /*判断j是否等于0*/ printf("inexistince"); /*条件成立输出不存在*/ }
举一反三
根据本实例,读者可以:
从键盘中输入一组数据,当输入#号时结束输入,求输入的这组数据中奇数和偶数的个数分别是多少?
输出0~100之间不能被3整除的所有数。
实例021 求解平方和
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\01\021
实例说明
任意给出一个自然数k,数k不为0,计算其各位数字的平方和k1,再计算k1的各位数字的平方和k2……重复此过程,最终将得到数1 或145,此时再做数的平方和运算它最终结果将始终是1或145。编写程序验证此过程。运行结果如图1.21所示。
图1.21 数平方和运算
技术要点
本实例主要是用while循环来求一个数各位平方和的过程。while语句在前面介绍过这里不详细介绍,细心的读者会发现程序中用到了goto语句,下面介绍一下goto语句的使用要点。
goto语句为无条件转向语句,它的一般形式为:
goto语句标号
这里语句标号用标识符表示,它的命名规则与变量名相同。goto语句通常有两个用途。
● 与if语句一起构成循环结构。
● 从多层循环的内层循环跳到外层循环。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)定义数据类型,为了验证一个较大的数是否符合此规律,这里将数据类型定义为长整型。
(4)任意输入一个数n,如果n不等于1并且n不等于145,则对n按位拆数,先低位后高位,存入数组a中,再按逆序计算平方和并将计算过程显示出来。
(5)主要程序代码如下:
main() { long a[10],n,i; /*定义数组及变量为基本整型*/ p: printf("please input a number:\n"); scanf("%ld",&n); /*从键盘中输入一个数n*/ if(n==0) /*如果输入的数为0则重新输入*/ goto p; while(n != 1 && n != 145) { printf("n=%ld->", n); i = 1; while(n > 0) { a[i++]=n % 10; /*将n的各位数字存放到数组a中*/ n /= 10; } n = 0; i--; while(i>=1) /*使用while语句将运算过程输出*/ { printf("%ld*%ld", a[i], a[i]); if(i > 1) printf("+"); n += a[i] *a[i]; i--; } printf("=%ld\n",n); /*将最终求得的平方和n输出*/ } getch(); }
举一反三
根据本实例,读者可以:
已知两个平方三位数abc和xyz,其中a、b、c、x、y、z未必是不同的,而ax、by、cz是三个平方二位数。试编程求三位数abc和xyz。
设x是一个四位数,它的9倍恰好是其反序数,编写程序求x的值(反序数就是将整数的数字倒过来形成的整数,如9568的反序数是8659)。
1.5 数组
在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来,这样的形式称为数组。在C语言中,数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别,本节主要介绍数值数组的应用。
实例022 逆序存放数据
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\022
实例说明
任意输入5个数据,编程实现将这5个数据逆序存放,并将最终结果显示在屏幕上。运行结果如图1.22所示。
图1.22 逆序存放数据
技术要点
本实例没有太多难点,但是通过本实例的练习能让读者明白在编程过程中如何运用一维数组。这里介绍一下一维数组的一些相关知识。
● 一维数组的定义方式
类型说明符 数组名[常量表达式]
说明:常量表达式表示元素的个数,即数组长度。例如a[5],5表示数组中有5个元素,下标从0开始,到4结束。a[5]不能使用,数组下标越界。
● 一维数组的初始化
(1)在定义数组的时可直接对数组元素赋初值。
(2)可以只给一部分元素赋值,未赋值的部分元素默认值为0。例如:int a[5]={1,2};表示给前两个元素赋了初值,后面a[2]、a[3]、a[4]值均为0。
(3)在对全部数组元素赋初值时,可以不指定数组长度。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)借助中间变量temp实现数据间的互换。
(4)主要程序代码如下:
main() { int a[5],i,temp; /*定义数组及变量为基本整型*/ printf("please input array a:\n"); for(i=0;i<5;i++) /*逐个输入数组元素*/ scanf("%d", &a[i]); printf("array a:\n"); for(i=0;i<5;i++) /*将数组中的元素逐个输出*/ printf("%d ", a[i]); printf("\n"); for(i=0;i<2;i++) /*将数组中元素的前后位置互换*/ { temp=a[i]; /*元素位置互换的过程借助中间变量temp*/ a[i] = a[4-i]; a[4-i] = temp; } printf("Now array a:\n"); for(i=0;i<5;i++) /*将转换后的数组再次输出*/ printf("%d ", a[i]); }
举一反三
根据本实例,读者可以:
任意输入10个数据,编程求这10个数据中小于0的元素之和。
任意输入10个数据,编程求这10个数据中偶数的个数及偶数之和。
实例023 相邻元素之和
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\01\023
实例说明
从键盘中任意输入10个整型数据存到数组a中,编程求出a中相邻两元素之和,并将这些和存在数组b中,按每行3个元素的形式输出。运行结果如图1.23所示。
图1.23 相邻元素之和
技术要点
本实例的算法思想如下:输出10个元素存到数组a中,利用for循环将数组a中相邻的元素求和存到数组b中,相邻元素的表示形式为a[i-1]及a[i]。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include<stdio.h>
(3)利用for循环将数组a中相邻的元素求和存到数组b中,利用for循环和if条件判断将b数组中的元素以3个元素一行的形式输出。
(4)主函数程序代码如下:
main() { int a[10],b[10],i; /*定义数组及变量为基本整型*/ printf("please input array a:\n"); for(i = 0; i < 10; i++) scanf("%d",&a[i]); /*输入10个元素到数组a中*/ for(i = 1; i < 10; i++) b[i]=a[i]+a[i-1]; /*将数组a中相邻两个元素求和放到数组b中*/ for(i = 1; i < 10; i++) { printf("%5d",b[i]); /*将数组b中元素输出*/ if(i % 3 = = 0) printf("\n"); /*每输出3个元素进行换行*/ } }
举一反三
根据本实例,读者可以:
从键盘中任意输入10个整型数据存到数组a中,编程求出a中相邻两元素之积,并将这些积存在数组b中,按每行3个元素的形式输出。
从键盘中任意输入10个整型数据存到数组a中,编程求出a中每隔一个元素之和,并将这些和存在数组b中,按每行3个元素的形式输出。