Bootstrap

【C语言学习笔记】翁恺课程(1)

目录

0. 前言

1. 第一个程序

2. 变量

变量赋值与初始化

常量

浮点数

表达式

3. 判断机制

if条件判断

嵌套的if-else

级联的if-else

多路分支:switch-case语句

4. 循环

while循环

 do-while循环

算平均数

整数求逆

for循环

循环次数

循环控制

 循环嵌套

凑硬币

求前N项和

整数分解

最大公约数


0. 前言

计算机程序的执行:
1) 解释:借助一个程序,那个程序能试图理解你的程序,然后按照你的要求执行
2) 编译:借助一个程序把你的程序翻译成机器语言写的程序,计算机可以直接执行。
解释语言vs编译语言:
语言本无解释与编译之分,常用的执行方式不同。
解释型语言有特殊的计算能力;编译型语言有确定的运算性能。

C语言的用途:操作系统、嵌入式系统、驱动程序、底层驱动、图形引擎、图像处理、声音效果(直接给我们提供数据的代码不是用C语言写的)一些底层的东西。

C语言是一种工业语言,基础性工作使用。
C语言需要被编译才能运行,所以需要:编辑器和编译器。(或者IDE,Integrated Development Environment集成开发环境)

1. 第一个程序

# include <stdio.h>

int main()
{
    printf("hello world!\n");
    
    return 0;
}

printf()会把" "内的内容(字符串)原封不动地输出,\n表示换行。
除了printf这行 其他为框架,为必须部分。

# include <stdio.h>

int main()
{
    printf("hello world! \n");
    printf("%d \n",12+34);
    printf("12+34=%d \n",12+34);
    return 0;
}

printf("%d",12+34);    %d则是输出后面的值,12+34为式子,则算后输出。
四则运算:加+ 减- 乘* 除/  取余%(取两个数相除后的余数(27除以6, 商数为4,余数为3))  括号()

2. 变量

找零钱问题
1) 有办法输入数字;
2) 有地方放输入的数字;
3) 输入的数字参与计算。

# include <stdio.h>

int main()
{
    int price = 0;//定义了整形变量price,类型是int,初始值=0
    printf("请输入金额(元):");
    scanf("%d",&price);//要求scanf函数读入下一个整数,结果赋值给变量price
    int change = 100 - price;//定义了整形变量change,并做了计算
    printf("找您%d元。\n",change);
    
    return 0;
}

如何输入:在终端窗口中;以行为单位进行,行的结束标志为按下回车键,按下回车前程序不会读到任何东西。

变量:

int price = 0:定义了整形变量price,名字为price,类型是int,初始值为0。
变量是一个保存数据的地方。
变量定义的一般形式就是:<类型名称> <变量名称>
变量的名字叫“标识符”

基本原则:
- 只能由字母、数字、下划线构成,
- 数字不能出现在第一个位置上。
- C语言的关键字(又叫保留字)不可用作字符。

变量赋值与初始化

price = 0:式子,= 赋值运算符,将右边的值赋给左边。
和数学不同,a=b 与 b=a意思完全相反。

当赋值发生在定义变量时,为变量的初始化。
虽然C语言并没有强制要求所有的变量在被定义的地方做初始化,但所有变量在第一次被使用(出现在赋值运算符等号右边)前都应该被赋值一次。
如果没有被初始化?
则变量的值就是其在内存中的原来的值。
变量初始化:<类型名称> <变量名称>=<初始值>
也可以在组合变量定义中给单个变量单独赋初值,如

int price=0, change=10;

有运算符的式子就叫表达式(比如=是赋值运算符),如

price = 0;
charge=100-price;

C语言是有类型的语言,所有变量在使用前必须先定义或声明;
所有变量必须有确定的数据类型(表示在变量中可以存放什么样的数据),变量中也只能存放指定类型的数据,程序运行过程中也不能改变变量的类型。
传统的ANSI C只能在开头的地方定义变量,而C99可以任何地方定义。


读整数:

scanf("%d",&price);//要求scanf函数读入下一个整数,结果赋值给变量price;注意有 & 
如果输入非整数,后面再说。
出现在scanf字符串里面的东西是它一定要你输入的东西,而不是给你看的东西。

scanf("%d,%d",&a,&b);

键盘输入:1,2回车

键盘输入:1空格2回车

scanf("price%d %d",&a,&b);

键盘输入:1空格2回车

键盘输入:Price1空格3回车

常量

const int AMOUNT=100;

其中const是个修饰符,加在int前面,给这个变量加上一个const(不变的)属性,表示这个变量的值一旦初始化,就不能再更改赋值了。
好处:1.便于理解、2.便于修改
一般常量名字全大写
 输入时如果要两个数,在中间、最后敲空格或回车,计算机读到两个数字时才会停止。

浮点数

两个整数做运算结果只能是整数,去掉小数部分,10 和10.0 在C中为完全不同的数

浮点数(浮点数指小数点时可以浮动的,是计算机中表示分数和无理数的一种方式。人们用浮点数来称呼有小数点的数),C中无定点数。

当浮点数和整数放在一起运算时,计算机会自动把整数转化为浮点数计算。

# include <stdio.h>
/* 身高单位英尺英寸转为米单位  */
int main()
{
	printf("请分别输入身高的英尺和英寸,"
			"如输入\"5 7\"表示5英寸7英尺:" );
	
	int foot, inch;
	scanf("%d %d",&foot,&inch);
	printf("身高是%f米。\n",
			((foot + inch / 12)*0.3048));
	
	printf("10/3*3 = %d\n",10/3*3);    // 输出结果为9,即10/3=3.333去掉小数部分,为3 3*3=9
	printf("10.0/3*3 = %f\n",10.0/3*3);// 10 改进为10.0,%d改成%f。
	
	printf("身高是%f米。\n",
			((foot + inch / 12.0)*0.3048));// 12 改进为12.0,%d改成%f。
	
	return 0;
}

浮点数类型,可以为double 双精度浮点数,float (单精度)浮点数。,若定义变量时就改int为double,则 scanf、printf 的 %d 部分也应改为 %lf %f

表达式

运算符(operator)是指进行运算的动作,比如加/减法运算符+ -
算子(operand)是指参与运算的,可能是常数/变量/一个方法的返回值。

a = b + 5:= + 为运算符; a b 5为算子

# include <stdio.h>
/*   求时间差   */
 
int main()
{
	printf("请分别两次时刻的小时和分钟,如4小时30分:4 30\n");
	
	int hour1, minute1;
	int hour2,minute2;
	
	scanf("%d %d",&hour1,&minute1);
	scanf("%d %d",&hour2,&minute2);
	
	int t1 = hour1*60 + minute1;	// 转换为分钟为单位,防止进位问题 
	int t2 = hour2*60 + minute2;
	
	int t = t2 - t1;

	printf("时间差是 %d 小时 %d 分。\n", t/60, t%60); // t%60为求分钟部分 
	
	return 0;
}

运算符的优先级

优先级运算符运算结合关系举例
1+单目不变自右向左a*+b
1-单目取负自右向左a*-b
2*自左向右a*b
2/自左向右a/b
2%取余自左向右a%b
3+自左向右a+b
3-自左向右a-b
4=赋值自右向左a=b

(单目:如+a,-a,相当于正负号;双目:a+b,a-b);赋值也是运算,也有结果。
a=6的结果就是a被赋予6;a=b=6∶自右向左,先b =6 后再 a =b。

# include <stdio.h>
/*   交换a b的值  */
 
int main()
{
	int a = 5,b = 6;
	int t;
	t = a;
	a = b;
	b = t;
	printf("a = %d,b = %d\n",a,b);
}

(8条消息) C语言:使用Dev C++断点调试_qq_45660901的博客-CSDN博客_c语言设置断点调试步骤https://blog.csdn.net/qq_45660901/article/details/109129667?spm=a2c6h.12873639.article-detail.8.69b2518aHcX6uF复合运算符:+ - * / % 和 = 结合形成+= -= *= /= %=

total += 5 即是 total = total + 5;

total += (sum+100)/2 即是 total = total +(sum+100)/2;

total *= sum+12 即是 total = total*(sum+12);右边先算完,再做复合运算符。

递增递减运算符:++  -- 。是单目运算符,只能有一个算子,这个算子还只能是变量。会让该变量+1/-1;

a++后缀形式:a++ 运算式的值为a+1 的值。

++a前缀形式:++a 运算式的值加了1之后的值。

无论哪个 a自己的值都是加了1的

表达式运算表达式的值
count++给count加1count原来的值
++count给count加1count+1后的值
count--给count减1count原来的值
--count给count减1count-1后的值

a = b += c++-d+--e/-f 表示啥?
 

3. 判断机制

if条件判断

    if(条件){
        要执行的语句,只有条件成立时才会执行
    }
# include <stdio.h>
/* 求时间差,if结构判断是否有借位 */
int main()
{
	int hour1, minute1;
	int hour2, minute2;
	scanf("%d %d",&hour1,&minute1);
	scanf("%d %d",&hour2,&minute2);
	int ih = hour2 - hour1;
	int im = minute2 - minute1;
	if ( im < 0)
	{
		im = 60 + im;
		ih --;
	}
	printf("时间差为%d小时%d分。\n", ih,im);
	return 0;
}

 条件

计算两个值之间的关系,关系运算:== 相等 ; != 不相等;> 大于;>= 大于等于;< 小于;<= 小于等于。

关系运算的结果:成立 为1;不成立 为0。·

优先级:比算术运算低 比赋值运算高。== 与!=优先级比其他的低,连续的关系运算从左到右。

5>3==6>4表示:5大于3是否等于6大于4 

6>5>4 表示:6大于5是否成立 成立为1 1 > 4是否成立,不成立 结果为0。

找零计算器

# include <stdio.h>
/*   找零计算器  */

int main()
{
	//初始化
	int price=0;
	int bill=0;
	//读入金额和票面
	printf("请输入金额:");
	scanf("%d",&price);
	printf("请输入票面:");
	scanf("%d",&bill);
	//计算找零
	if (bill >= price){
		printf("应找您:%d\n",bill - price);
	}else{
		printf("您的钱不够\n");
	}
	
	return 0;
}

//是(单行)注释;  /* */中间可以有多行注释。
comment对程序的功能没有任何影响,但是往往能使程序更容易被人理解。

输入比较两数求大者:

# include <stdio.h>
/*   比较ab大小_方案1  */

int main()
{
	int a,b;
	printf("请输入两个整数:");
	scanf("%d %d",&a,&b);
	
	int max=0;
	if(a>b){
		max=a;
	}else {
		max=b;
	}
	
	printf("大的那个是%d\n",max);
	
	return 0;
}
# include <stdio.h>
/*   比较ab大小_方案2  */

int main()
{
	int a,b;
	printf("请输入两个整数:");
	scanf("%d %d",&a,&b);
	
	int max=b;
	if(a>b)
		max=a;
	printf("大的那个是%d\n",max);
	
	return 0;
}

if语句可以没有大括号{},if语句这一行结束的时候并没有表示语句结束的“;”,而后面的赋值语句写在if的下一行,并且缩进了,在这一行结束的时候有一个表示语句结束的;这表明这条赋值语句是if语句的一部分,if拥有和控制这条赋值语句,觉得是否执行。else也是,可以没大括号,只有紧跟的那一句有效。

# include <stdio.h>
/*   计算薪水  */

int main()
{
	//初始化
	const double RATE = 8.25; //标准工资
	const int STANDARD = 40;
	double pay = 0.0;
	int hours;

	printf("请输入工作小时数:");
	scanf("%d",&hours);
	printf("\n");
	

	if (hours >= STANDARD){
		pay = STANDARD * RATE + (hours-STANDARD)*(RATE*1.5); // 1.5倍加班工资
	}else{
		pay = hours * RATE;
	}
	printf("应付工资:%f\n", pay);
	return 0;
}

嵌套的if-else

找abc的最大值:

# include <stdio.h>
/*   比较abc最大值  */

int main()
{
	//初始化
	int a,b,c;
	
	scanf("%d %d %d",&a,&b,&c);
	int max = 0;
	if(a>b){
		if(a>c){
			max = a;
		}else{
			max = c;
		}
	}else{
		if(b>c){
			max = b;
		}else{
			max = c;
		}
	}
	printf("max = %d\n",max);
	return 0;
}
if(a>b)
{
    if(a>c)max=a;
    else max=c;
}
else
{
    if(b>c)max=b;
    else max=c;
}

当if的条件满足或不满足的时候要执行的语句也是一条if或if-else语句,为嵌套的if语句。

如果省略掉大括号,容易引起自己认为、别人认为、编译器认为有区别。最好都写上{}。

else与最近的if联系

级联的if-else

# include <stdio.h>
/*   分段函数  */

int main()
{
	//初始化
	int x;
	scanf("%d",&x);
	
	int f = 0;
	if(x < 0){
		f = -1;
	}else if(x == 0){
		f = 0;
	}else if (x > 5){
		f = 2*x;
	}else{
		f = 3*x;
	}
	
	printf("f = %d\n",f);
	return 0;
}

另一种方法:在上面代码上改为每次决定了就输出值。

第一种方法好,有单一出口(都是输出f),代码要降低重复性,出问题的时候好统一处理。

多路分支:switch-case语句

# include <stdio.h>
/*   Swith-case语句  */

int main()
{
	int type;
	scanf("%d", &type);
	switch (type) {
	case 1:
		printf("Good Morning!");
		break;
	case 2:
		printf("Good afternoon!");
		break;
	default:
		printf("Good Night!");
		break;
	}
	return 0;
}

if-else从上向下判断,上面的都得执行了不满足条件才到下面。

switch-case则是从case中找到对应的值,执行后面的语句,直到遇到break跳出switch,或switch结束为止(即使后面没break,有了下一个case,就执行下一个case里的语句。)

switch后括号里的控制表达式之只能是整数型int的结果。case后面的常数,也可以是常数计算表达式。

4. 循环

写程序写的是步骤,不是关系,不是说明。

while循环

if换成while,if是一次性的,做了之后满足不满足,都离开;while反复试,直到不满足跳出循环体。在循环体内要有改变条件的机会。

#include <stdio.h>
/*  数正整数数字的位数*/
int main()
{
	int x;
	int n=0;
	scanf ("%d" ,&x);
	n++;
	x/=10;
	while (x>0) {
		n++;
		x /= 10;
	}
	printf("%d\n",n);
	return 0;
}

do-while

数字位数的算法

  1. 用户输入x;
  2. 初始化n为0;
  3. X/=10,去掉个位;
  4. n++;
  5. 如果x>0,回到3;
  6. 否则n就是结果。

 do-while循环

进入循环的时候不做检查,而是执行完一轮循环体的代码之后再来检查循环条件是否满足,满足的话继续,不满足的话结束循环。无论如何,循环都会执行至少一遍。

do

{

<循环结构体>

}while(<循环条件>);
#include <stdio.h>
/*  数正整数数字的位数*/
int main()
{
	int x;
	int n=0;
	scanf ("%d" ,&x);
	n++;
	x/=10;
	do{
		n++;
		x /= 10;
	}while (x>0);
	printf("%d\n",n);
	return 0;
}

猜数游戏

- 让计算机来想一个数,然后让用户来猜,用户每输入一个数,就告诉它是大了还是小了,直到用户猜中为正,最后还要告诉用户它猜了多少次。
- 因为需要不断重复让用户猜,所以需要用到循环
- 在实际写出程序之前,我们可以先用文字描述程序的思路
- 核心重点是循环的条件
- 人们往往会考虑循环终止的条件

l.计算机随机想一个数,记在变量number里;2.一个负责计次数的变量count初始化为0;3.让用户输入一个数字a;
4. count递增(加一);
5.判断a和number的大小关系,如果a大,就输出“大”;如果a小就输出“小”;
6.如果a和number是不相等的(无论大还是小),程序转回到第3步;
7.否则,程序输出“猜中”和次数,然后结束。
 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/*  猜数游戏  */

int main()
{
	srand(time(0));
	int number = rand()%100+1;//想要a为100以内的整数:用取余即可(a%=100)
	int count = 0;
	int a = 0;
	
	printf("我已经想好了一个1到100之间的数。");
	do {
		printf("请猜这个1到100之间数:");
		scanf("%d",&a);
		count ++;
		if ( a > number ) {
			printf("你猜的数大了。");
		}else if ( a < number ) {
			printf("你猜的数小了。");
		}
	}while (a != number);
	printf("太好了,你用了%d次就猜到了答案。\n",count);

	return 0;
}

算平均数

让用户输入一系列的正整数,最后输入-1表示输入结束,然后程序计算出这些数字的平均数,输出输入的数字的个数和平均数。

变量->算法->流程图->程序

变量

—— 一个记录读到的整数的变量平均数要怎么算?
—— 只需要每读到一个数,就把它加到一个累加的变量里,到全部数据读完,再拿它去除读到的数的个数就可以了
—— 一个变量记录累加的结果,一个变量记录读到的数的个数。

#include <stdio.h>
/*  算平均数  */

// do while方法,多了一次if判断,且在循环里面,每次都得运行

int main( )
{
	int number;
	int sum = 0;
	int count = 0;
	do {
		scanf( "%d", &number);
		if ( number != -1 ) {
			sum += number;
			count ++;
		}
	}while ( number != -1 );
	printf("%f\n", 1.0*sum/ count);
	return 0;
}

//while方法,后面循环中比较只进行一次,scanf多了一次,但是是整个程序运行一次。
int main( )
{
	int number;
	int sum = 0;
	int count = 0;
	scanf( "%d",&number);
	while ( number != -1 ) {
		sum += number;
		count ++;
		scanf ( "%d",&number); //
	}
	printf("%f\n", 1.0*sum/ count);//为能输出小数
	return 0;
}

整数求逆

● —个整数是由1至多位数字组成的,如何分解出整数的各个位上的数字,然后加以计算?
对一个整数做 %10 的操作,就得到它的个位数
对一个整数做 /10 的操作,就去掉了它的个位数
● 然后再对2的结果做%10,就得到原来数的十位数了;
● 依此类推。

#include <stdio.h>
/*  整数求逆序  */

int main( )
{
	int x = 12345;
	int digit;
	int ret = 0;

	while (x>0) {
		digit = x%10;
		//printf("%d", digit);
		ret = ret*10 + digit;
		printf("x=%d, digit=%d,ret=%d\n", x, digit, ret);
		x /= 10;
	}
	printf("逆序结果为:%d\n",ret);
	
	return 0;
}

// 对于700这种输出需要为007的

int main( )
{
  int x = 700;
  int digit;
  int ret = 0;
  
  while (x>0) {
	  digit = x%10;
	  printf("%d", digit);
	  ret = ret*10 + digit;
	  //printf("x=%d, digit=%d,ret=%d\n", x, digit, ret);
	  x /= 10;
  }
  //printf("逆序结果为:%d\n",ret);
  
  return 0;
}

for循环

求阶乘:n! = 1x2x3x4x...xn;
变量:显然读用户的输入需要一个int的n,然后计算的结果需要用一个变量保存,可以是int的factor,在计算中需要有一个变量不断地从1递增到n,那可以是int的i。

for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,讦数器值以一定步进进行调整,比如加1或者减1。
for = 对于
for ( count=10; count>0; count-- )
就读成:“对于一开始的count=10,当count>0时,重复做循环体,每一轮循环在做完循环体内语句后,使得count--”
求和初始化变量=0 求积初始化变量=1。

循环控制变量i只在循环里被使用了,循环外面它没有任何用处。
因此,我们可以把变量i的定义写到for语句里面去:for(int i=0; i<n; i++):(C99 only)

#include <stdio.h>
/*  求阶乘  */

int main( )
{
	int n;
	scanf ( "%d" , &n) ;
	
	int fact = 1;
	int i = 1;
	while ( i <= n ) {
		fact *= i;
		i++;
	}
	printf( "%d !=%d\n", n, fact) ;
	return 0;
}


// for循环做
int main( )
{
	int n;
	scanf ( "%d" , &n) ;
	int fact = 1;
	//int i = 1;
	//for ( i=1; i<=n; i++ ) {
	//	fact *= i;
	//}
	
	//从n乘到1:
	for(int n1=n;n1>1;n1--){
		fact *= n1;
	}
	
	printf ( "%d !=%d\n", n, fact) ;

	return 0;
}

循环次数

for ( i=0; i<n; i++ )
则循环的次数是n,而循环结束以后,i的值是n。
循环的控制变量i,是选择从0开始还是从1开始,是判断i<n还是判断i<=n,对循环的次数,循环结束后变量的值都有影响

#include <stdio.h>

int main( )
{
	int i;
	for ( i=0; i<5; i++ ){
		printf("i=%d ", i);
	}
	printf("\n最后i=%d\n", i);
	//循环次数与循环变量最终值
	int j;
	for ( j=1; j<=5; j++ ){
		printf("i=%d ", j);
	}
	printf("\n最后j=%d\n", j);
	//for循环改写为while循环
	int m = 1;
	while(m<=5){
		printf("m=%d ", m);
		m++;
	}
	printf("\n最后m=%d\n", j);
	return 0;
}

i=0 i=1 i=2 i=3 i=4最后i=5.
for ( 初始动作;条件;每轮的动作){}
for中的每一个表达式都是可以省略的for (;条件;) == while (条件)。

—— 如果有固定次数,用for
—— 如果必须执行一次,用do_while
—— 其他情况用while

循环控制

素数,只能被1和自己整除的数,不包括1;2,3,5,7,11,14,13,17···。

#include <stdio.h>
//判断是否是素数

int main( )
{
	int x;
	scanf("%d",&x);
	
	int i;
	int isPrime = 1;
	for(i=2; i<x; i++){
		if(x % i == 0){
			isPrime = 0;
			break;
		}
	}
	if(isPrime == 1){
		printf("是素数\n");
	}else{
		printf("不是素数\n");
	}
	return 0;
}

如果没有break,当输入数为6时,第一次判断就知道了不是素数,但仍然满足循环条件,会一直循环到不满足条件才跳出。遇到break,可以跳出循环。
continue:跳过循环这一轮剩下的语句,进入下一轮。

 循环嵌套

注意循环控制变量不能混淆。

#include <stdio.h>
//输出一百以内的素数

int main( )
{
	for(int x=2; x<100; x++){
		int isPrime = 1;
		int i;
		for(i=2; i<x; i++){
			if(x % i == 0){
				isPrime = 0;
				break;
			}
		}
		if(isPrime == 1){
			printf("%d ",x);
		}
	}
	printf("\n");
	return 0;
}

//前50个素数
int main( )
{
	int cnt;		//计数器
	int x = 2;
	while(cnt< 50){
		int isPrime = 1;
		int i;
		for(i=2; i<x; i++){
			if(x % i == 0){
				isPrime = 0;
				break;
			}
		}
		if(isPrime == 1){
			printf("%d ",x);
			cnt++;
		}
		x++;
	}
	printf("\n");
	return 0;
}

凑硬币

#include <stdio.h>
// 凑硬币 用1角、2角、5角的硬币凑出2元

int main( )
{
	int x;
	int one,two,five;
	x = 2;				// 凑出2元
	for(one = 1; one < x*10; one++){
		for(two = 1; two < x*10/2; two++){
			for(five = 1; five < x*10/5; five++){
				if(one + two*2 + five*5 == x*10){
					printf("可以用%d个1角加%d个2角加%d个5角凑出得到%d元\n",one,two,five,x);
				}
			}
		}
	}
	return 0;
}

// 期望找到一组解后就跳出输出出来。方法1,break。
int main( )
{
	int x;
	int one,two,five;
	int exit = 0;
	x = 2;				// 凑出2元
	for(one = 1; one < x*10; one++){
		for(two = 1; two < x*10/2; two++){
			for(five = 1; five < x*10/5; five++){
				if(one + two*2 + five*5 == x*10){
					printf("可以用%d个1角加%d个2角加%d个5角凑出得到%d元\n",one,two,five,x);
					exit = 1;
					break;
				}
			}
			if(exit) break;
		}if(exit) break;
	}
	return 0;
}

//方法2,goto 。goto后面加标号,遇到goto,跳到对应标号所指位置。
int main( )
{
	int x;
	int one,two,five;
	x = 2;				// 凑出2元
	for(one = 1; one < x*10; one++){
		for(two = 1; two < x*10/2; two++){
			for(five = 1; five < x*10/5; five++){
				if(one + two*2 + five*5 == x*10){
					printf("可以用%d个1角加%d个2角加%d个5角凑出得到%d元\n",one,two,five,x);
					goto out;
				}
			}
		}
	}
out:
	return 0;
}

—— break和continue只能对它所在的那层循环做。
—— goto后面加标号,遇到goto,跳到对应标号所指位置。

求前N项和

#include <stdio.h>
//求前n项和 f1(n) = 1 + 1/2 + 1/3 + 1/4 +...+ 1/n ;

int main( )
{
	double sum = 0.0;
	int n = 10;
	for(int i=1; i<=n; i++){
		sum = sum + 1.0/i;
	}
	printf("f1( %d ) = %f\n",n,sum);
}

//求前n项和 f2(n) = 1 - 1/2 + 1/3 - 1/4 +...+ 1/n ;
int main( )
{
	double sum = 0.0;
	int n = 10;
	double sign = 1.0;		// 引入符号,double,就变1.0的符号
	for(int i=1; i<=n; i++){
		sum += sign/i;
		sign = -sign;
	}
	printf("f2( %d ) = %f\n",n,sum);
}

整数分解

#include <stdio.h>
// 正序分解整数;输入非负整数,正序输出它每一位数字。如输入12345;输出:1 2 3 4 5;输入700,输出7 0 0;

int main( )
{
	int x;
	scanf("%d",&x);
	// 获得和输入整数对应位数的mask
	int mask = 1;
	int t = x;
	while(t>9)		// 当输入为1位时候,mask = 1。
	{
		t /= 10;
		mask *= 10;
	}
	// 用mask逐渐减小一位来对整数做商得到最高位,取余得到后几位,
	// 12345 / 10000 -> 1; 12345 % 10000 -> 2345; 减小mask /10 = 1000
	// 2345 / 1000 -> 2; 2345 % 1000 -> 345;减小mask /10 = 100
	// 345 / 100 -> 3; 345 % 100 -> 45;减小mask /10 = 10
	// 45 / 10 -> 4; 45 % 10 -> 5;减小mask /10 = 1
	// 5 / 1 -> 5; 5 % 1 -> 5;减小mask /10 = 0
	do{
		int d = x /mask;
		printf("%d",d);
		if(mask > 9)	// 中间需要有空格 ,最后一位不要空格
		{
			printf(" ");
		}
		x %= mask;
		mask /= 10;
	}while( mask>0 );
	printf("\n");
	return 0;
}

最大公约数

输入两个数a和b,输出他们的最大公约数。如输入12 18 输出:6

枚举法

1. 设t为2;
2. 如果u和v都能被t整除,则记下这个t
3. t加1后重复第2步,直到t等于u或v;
4. 那么,曾经记下的最大的可以同时整除u和v的t就是gcd
 

#include<stdio.h>

int main()
{
	
	int a,b;
	int min;
	scanf( "%d %d" , &a,&b);
	if ( a < b ) {
		min = a;
	}else {
		min = b;
	}
	
	int ret = 0;
	int i;
	for ( i = 1; i <= min; i++ ) {
		if ( a%i == 0 ) {
			if ( b%i == 0 ) {
				ret = i;
			}
		}
	}
	printf("%d和%d的最大公约数是%d.\n",a,b,ret);
}

 辗转相除法。(不是尝试所有数,效率更高)

欧几里得算法_百度百科 (baidu.com)

#include<stdio.h>
//辗转相除法求最大公约数
/*
  1.如果b等于0,计算结束,a就是最大公约数;
  2.否则,计算a除以b的余数,让a等于b,而b等于那个余数;
  3.回到第一步。
  a  b  t
  12 18 12
  18 12 6
  12 6 0
  6 0
 */
int main()
{
	
	int a,b;
	int t;
	scanf( "%d %d" , &a,&b);
	while(b != 0){
		t = a%b;
		a = b;
		b = t;
		printf("a = %d, b = %d, t = %d\n",a,b,t);
	}
	printf("最大公约数是%d.\n",a);
	return 0;
}


 

;