C语言程序案例【持续更新中】

C语言程序案例

  • 一、书中程序案例
    • 1、第一个C语言程序——hello,world
    • 2、使用如下公式,打印华氏温度与摄氏温度对照表
      • (1) 程序优化—— 右对齐、浮点数
      • (2) 练习题1-3 —— 标题
      • (3) 练习题1-4 —— 摄氏转华氏
    • 3、用 for语句 实现华氏温度转换为摄氏温度
      • (1)练习题1-5——逆序打印
      • (2)程序优化——define指令定义特定的字符串
    • 4、文件复制:利用字符输入getchar()/输出putchar()函数
      • (1)程序优化——更精炼的写法:将为c赋值的操作放入while循环的测试部分
      • (2)练习1-6——getchar() != EOF 的值
      • (3)练习1-7——打印EOF的值
    • 5、字符计数 ~~~不符合预期
      • (1)程序优化——double双精度浮点型~~不符合
    • 6、行计数
    • 7、单词计数
    • 8、使用数组,统计各个数字、空白符以及所有其它字符出现的次数
  • 二、课上程序案例
    • 1、做点计算:让程序输出算数结果
    • 2、[补充]:VSCode的工作区
    • 3、付钱&找零
      • (1)程序优化
        • ① 常量:
        • ② 变量:
      • (2)程序优化 —— if-else语句
    • 4、身高 —— 英尺英寸换算为米
      • (1)计算身高的程序
      • (2)总结:
    • 5、计算时间差:
      • (1)运用for循环语句 优化
    • 6、求两数平均值
    • 7、逆序的三位数
    • 8、计算薪水:
    • 9、判断成绩
    • 10、判断数字的位数
        • ① 四位数及以下:
        • ② 优化 —— 循环语句
        • ③ do-while 循环进行优化
    • 11、 阶乘 运算
      • (1)while 循环
      • (2)for 循环
    • 12、三个数大小的比较
    • 13、循环计算 —— 计算log 以 2 为底,x 的对数
    • 14、算平均数
    • 15、猜数游戏
    • 16、整数求逆
    • 17、判断一个数是不是素数
    • 18、输出100以内的素数
    • 19、输出前50个素数
    • 20、凑硬币 _ 用1角、2角、5角的硬币凑出10元以下的金额
        • 【代码①】:—— 接力 ```break```
        • 【代码②】:—— ```goto```语句
    • 21、求前 n 项和
        • ① f(n)=1+1/2+1/3+…1/n
        • ② f(n)=1-1/2+1/3-1/4+…+1/n
    • 22、求最大公约数
      • 法①:枚举
      • 法②:==辗转相除法==
    • 23、正序分解整数
        • 法①:先逆序,再逆序
        • 法②:正序输出
  • 三、PTA编程练习
    • 1、厘米换算成英尺、英寸

一、书中程序案例

1、第一个C语言程序——hello,world

#include <stdio.h>  //包含标准库的信息
main()
{
    printf("hello,world\n");

	return 0;
}

上面的程序也可改写成:

#include <stdio.h>  //包含标准库的信息
main()
{
    printf("hello");
    printf(",world");
    printf("\n");
}

2、使用如下公式,打印华氏温度与摄氏温度对照表

°C=(5/9)(°F-32)
C语言程序案例【持续更新中】_第1张图片

#include<stdio.h>
/* 当fahr=0,20,···,300时,分别打印华氏温度与摄氏温度对照表 */
main()
{
    int fahr,celsius;
    int lower,upper,step;

    lower = 0;      /* 温度表的下限 */
    upper = 300;    /* 温度表的上限 */
    step = 20;      /* 步长 */

    fahr = lower;
    while (fahr <= upper){
        celsius = 5 * (fahr-32) / 9;
            /* 之所以写成先乘5然后再除以9,而不是直接写成5 / 9,是因为整数除法操作执行将进行舍位,结果中的小数部分会被舍弃。即5/9 = 0 */
        printf("%d\t%d\n",fahr,celsius);
            /* 每个 % 表示它的参数之一进行替换的位置,并指定打印格式。eg. %d指定一个整型参数;\t——在两者之间留一个制表符的空间。 */
        fahr = fahr + step;
    }
}

运行结果:
C语言程序案例【持续更新中】_第2张图片

(1) 程序优化—— 右对齐、浮点数

(1)如果在printf语句中的第一个参数的%d中指明打印宽度,则打印的数字会在打印区域内 右对齐

printf("%3d %6d\n",fahr,celsius);
            /* fahr的值占3个数字宽,celsius的值占6个数字宽 */

运行结果:
C语言程序案例【持续更新中】_第3张图片
(2)
Alt
代码:

#include<stdio.h>
/* 当fahr=0,20,···,300时,分别打印华氏温度与摄氏温度对照表 */
main()
{
    float fahr,celsius;     /* 浮点型 */
    float lower,upper,step;

    lower = 0;      /* 温度表的下限 */
    upper = 300;    /* 温度表的上限 */
    step = 20;      /* 步长 */

    fahr = lower;
    while (fahr <= upper){
        celsius = (5.0/9.0) * (fahr-32.0); 
            /* 5.0 / 9.0 是两个浮点数相除,结果不被舍位 */
        printf("%3.0f %6.1f\n",fahr,celsius);
            /* %3.0f 表明fahr至少占3个字符宽,且不带小数点和小数部分;%6.1f 表明celsius至少占6个字符宽,且小数点后面有 1 位数字 */
        fahr = fahr + step;
    }
}

运行结果:
C语言程序案例【持续更新中】_第4张图片

Note:此外,printf函数还支持下列格式说明:
%o 表示八进制数;%x 表示十六进制数;
%c 表示字符;%s 表示字符串;%% 表示%本身。

(2) 练习题1-3 —— 标题

1-3 修改程序,使之能在转换表的顶部打印一个标题。
【答】:只需在while语句前添加一行代码:

	fahr = lower;
    printf("这是一个标题\n");	//所添加的代码
    while (fahr <= upper){

运行结果:
C语言程序案例【持续更新中】_第5张图片

(3) 练习题1-4 —— 摄氏转华氏

1-4 编写一个程序,打印摄氏温度转化为相应的华氏温度的转换表。
【代码】:

#include<stdio.h>
/* 分别打印摄氏温度与华氏温度对照表 */
main()
{
    float fahr,celsius;     /* 浮点型 */
    float lower,upper,step;

    lower = -20;      /* 温度表的下限 */
    upper = 300;    /* 温度表的上限 */
    step = 20;      /* 步长 */

    celsius = lower;
    printf("这是一个标题\n\n");
    while (celsius <= upper){
        fahr = (9.0/5.0) * celsius + 32.0; 
            /* 9.0 / 5.0 是两个浮点数相除,结果不被舍位 */
        printf("%3.0f %6.1f\n",celsius,fahr);
            /* %3.0f 表明fahr至少占3个字符宽,且不带小数点和小数部分;%6.1f 表明celsius至少占6个字符宽,且小数点后面有 1 位数字 */
        celsius = celsius + step;
    }
}

【运行结果】:
C语言程序案例【持续更新中】_第6张图片

3、用 for语句 实现华氏温度转换为摄氏温度

【程序】:

#include<stdio.h>
/* 打印华氏温度与摄氏温度对照表 */
main()
{
    int fahr;

    for (fahr = 0; fahr <= 300; fahr = fahr + 20)   /* ① 初始化部分,仅在进入循环前执行一次;② 条件部分;③ 增加步长部分*/
        printf("%3d  %6.1f\n",fahr , (5.0/9.0)*(fahr-32));
}

【运行结果】:
C语言程序案例【持续更新中】_第7张图片

(1)练习题1-5——逆序打印

1-5 修改程序,要求以逆序打印温度转换表。(即按照从300度到0度的顺序)
【程序代码】:

#include<stdio.h>
/* 打印华氏温度与摄氏温度对照表——逆序 */
main()
{
    int fahr;

    for (fahr = 300; fahr >= 0;fahr = fahr - 20)
        printf("%3d  %6.1f\n",fahr , (5.0/9.0)*(fahr-32));

    //for (fahr = 0; fahr <= 300; fahr = fahr + 20)   /* ① 初始化部分,仅在进入循环前执行一次;② 条件部分;③ 增加步长部分*/
    //    printf("%3d  %6.1f\n",fahr , (5.0/9.0)*(fahr-32));
}

【运行结果】:
C语言程序案例【持续更新中】_第8张图片

(2)程序优化——define指令定义特定的字符串

【程序代码】:

#include<stdio.h>
/* 打印华氏温度与摄氏温度对照表 */

/* define指令把符号名定义为一个特定的字符串     #define 名字 替换文本  ;其中,名字——以字母打头的字母或数字序列;替换文本可以是任何字符串序列 */
#define LOWER   0       /* lower limit of table */
#define UPPER   300     /* 温度表的上限 */              /* 符号常量名通常用大写字母,用以区分小写字母的变量名 */
#define STEP    20      /* 步长 */
    /* Note: #define 指令行的末尾没有分号 */

main()
{
    int fahr;

    for (fahr = LOWER; fahr <= UPPER;fahr = fahr + 20)
        printf("%3d  %6.1f\n",fahr , (5.0/9.0)*(fahr-32));
}

运行结果与上述结果相同。

4、文件复制:利用字符输入getchar()/输出putchar()函数

【程序代码】:

#include<stdio.h>
/* copy input to output; 1st version */
main()
{
    int c;                          /* 将c声明成int类型原因:必须让 c 足够大,除了能存储任何可能的字符外,还要能存储文件结束符 EOF */

    c = getchar();
    while (c != EOF )       /* 在没有输入时,getchar函数将返回一个特殊值,这个特殊值与任何实际字符都不同。这个值称为EOF(end of file,文件结束)。*/
    {
        putchar(c);
        c = getchar();
    }
}

【运行结果】:
C语言程序案例【持续更新中】_第9张图片

(1)程序优化——更精炼的写法:将为c赋值的操作放入while循环的测试部分

【程序代码】:

#include<stdio.h>

/* copy input to output; 2nd version */
main()
{
    int c;                      

    while ((c = getchar()) != EOF )       /* 对于 while 语句的条件部分,赋值表达式两边的圆括号不能省略!因为 != 的优先级高于 = 的 */
        putchar(c);
}

运行结果与上述相同。

(2)练习1-6——getchar() != EOF 的值

1-6 验证表达式 getchar() != EOF 的值是0还是1。
【程序代码】:

#include<stdio.h>

/* 验证表达式 getchar() != EOF 的值是0还是1 */
main()
{
    int c;                      
    
    while (c = getchar() != EOF )
        printf("%d\n",c);
}

【运行结果】:
C语言程序案例【持续更新中】_第10张图片

(3)练习1-7——打印EOF的值

1-7 编写一个打印EOF值的程序。
【程序代码】:

#include<stdio.h>

/* 编写一个打印EOF值的程序 */
main()
{
    int c;                      

    printf("EOF is %d\n",c);
}

【运行结果】:
C语言程序案例【持续更新中】_第11张图片

5、字符计数 ~~~不符合预期

【程序代码】:

#include<stdio.h>

/* count characters in input; 1st version */
main()
{
    long nc;    // 长整型至少要占用32位存储单元

    nc = 0;
    while (getchar() != EOF)
        ++nc;               // nc = nc + 1
    printf("%ld\n", nc);   // %ld 告诉printf函数其对应的参数是 long 整型
}

【运行结果】:
C语言程序案例【持续更新中】_第12张图片
Note:运行结果不符合预期!!!

(1)程序优化——double双精度浮点型~~不符合

【代码】:

#include<stdio.h>

/* count characters in input; 2nd version */
main()
{
    double nc;    // 双精度浮点型可以处理更大的数字

    for (nc = 0; getchar() != EOF; ++nc)
        ;           // for 语句的循环体是空的——用【;】代替
    printf("%.0f\n", nc);   // float 与 double 类型,printf函数都用【%f】进行说明; %.0f 不打印小数点和小数部分。
}

【运行结果】:
C语言程序案例【持续更新中】_第13张图片

Note:运行结果也不符合预期!!

6、行计数

统计输入中的行数——等价于统计换行符的个数
【程序代码】:

#include<stdio.h>

/* count lines in input */
main(){
    int c, n1;
    
    n1 = 0;
    while((c = getchar()) != EOF)
        if (c == '\n')      // 单引号中的字符表示一个整型值,如 '\n' 代表换行符的值,在ASCII字符集中其值为10——是一个整型数;而 "\n" 是一个仅包含一个字符的字符串常量。
            ++n1;
    printf("%d\n", n1);
}

7、单词计数

【程序代码】:

#include<stdio.h>

#define IN  1   /* inside a word */
#define OUT 0   /* outside a word */

/* count lines, words, and characters in input */
main()
{
    int c, nl, nw, nc, state;

    state = OUT;
    nl = nc = nw = 0;
    while ((c = getchar()) != EOF){
        ++nc;
        if(c == '\n')
            ++nl;
        if (c == ' ' || c ==  '\n' || c == '\t')       // 逻辑或;从左到右求值; && 比 || 高一个优先级
            state = OUT;
        else if (state == OUT ){
            state = IN;
            ++nw;
        }
    }
    printf("%3d  %3d  %3d\n", nl, nw, nc);
}

8、使用数组,统计各个数字、空白符以及所有其它字符出现的次数

题目:
使用数组,统计各个数字、空白符(包括空格符、制表符、换行符)以及所有其它字符出现的次数。

#include<stdio.h>

/* count digits, white space, others */
main()
{
    int c, i, nwhite, nother;
    int ndigit[10];         // 将变量声明为由十个整型数构成的数组;数组下标总是从 0 开始

    nwhite = nother =0;
    for(i = 0; i < 10; ++i)
        ndigit[i] = 0;

    while ((c = getchar()) != EOF)
        if(c >= '0' && c <= '9')
            ++ndigit[c-'0'];    // 如果是数字,则对应的数值为 c-'0'
        else if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;
        else
            ++nother;

    printf("digits = ");
    for (i = 0; i < 10; ++i)
        printf(" %d",ndigit[i]);
    printf(", white space = %d, other = %d\n", nwhite,nother);
    
    system("pause");
}

二、课上程序案例

1、做点计算:让程序输出算数结果

【程序】:

#include<stdio.h>

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

【运行结果】:
C语言程序案例【持续更新中】_第14张图片
【补充】
C语言程序案例【持续更新中】_第15张图片

2、[补充]:VSCode的工作区

C语言程序案例【持续更新中】_第16张图片
此时,直接点击【run】,会提示 编译不成功;
是因为编译只是编译了当前的 hello.c 文件。会发现 eval 函数不存在,所以不能简单的直接用这个方式去编译,因为这种编译只认当前文件!
【正确编译方法——方案①】:
点【查看】----【调试控制台】----用gcc进行编译 ---- 在下端的终端内输入gcc hello.c eval.c -o eval ,回车 ---- 可用dir查看,可知多出一个eval.exe ---- ./eval----此时没有输出,说明正确(hello.c中,assert的语句说明,如果计算结果=12,则无任何事情发生)
C语言程序案例【持续更新中】_第17张图片
【正确编译方法——方案②】:
Makefile通过gcc去编译hello.o和eval.o来形成 eval ,也可以用make来编译一个工程中所有的文件 :在下端的终端内输入mingw32-make ---- 也能得到 eval.exe
C语言程序案例【持续更新中】_第18张图片
代码:

CC := gcc
CFLAG := -03 -Wall
OBJS := hello.o eval.O
TARGET := eval

$(TARGET): (OBJS)
	$(CC) -o $@ $(OBJS)

%.o: %.c
	$(CC) $(CFLAG) -c -o $@ $<

3、付钱&找零

【代码】:

#include <stdio.h>

int main()
{
    int price = 0;

    printf("请输入金额(元):");
    scanf("%d", &price);

    int change = 100 - price;

    printf("找您%d元。\n", change);

    return 0;
}

【运行结果】:
C语言程序案例【持续更新中】_第19张图片

(1)程序优化

① 常量:

1、eg.主程序:

	const int AMOUNT = 100;
    int price = 0;      
                           
    printf("请输入金额(元):");
    scanf("%d", &price);    // 注意price前面的 & ;

    int change = AMOUNT - price;

    printf("找您%d元。\n", change);

2、const 是一个修饰符,加在int 前。初始化后不能修改,即不能再赋值;

② 变量:

3、让用户输入变量 AMOUNT ,而不是使用固定的初始值
【主程序】:

    int amount = 100;
    int price = 0;      // 定义了整型变量price --- 变量是保存数据的地方;变量的名字是一种“标识符”
                            // 标识符只能由字母、数字和下划线组成,数字不能出现在第一个位置上
    printf("请输入金额(元):");
    scanf("%d", &price);    // 注意price前面的 & ;

    printf("请输入票面:");
    scanf("%d",&amount);

    int change = amount - price;

    printf("找您%d元。\n", change);

【运行结果】:
Alt

(2)程序优化 —— if-else语句

#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;
}

4、身高 —— 英尺英寸换算为米

(1)计算身高的程序

1、两个整数的运算结果只能是整数;
eg. 10/3*3 = 9
2、浮点数——小数点是浮动的;
3、当整型数和浮点数放在一起运算时,C会将整数转换为浮点数,再进行浮点数的运算;
【代码】:

#include <stdio.h>

int main()
{
	printf("请分别输入身高的英尺和英寸,"
		"如输入\"5 7\"表示5英尺7英寸:");

	int foot;
	int inch;

	scanf("%d %d", &foot, &inch);

	printf("身高是%f米。\n", 
		((foot + inch / 12.0) * 0.3048));

    return 0;
}

【运行结果】:
Alt
4、双精度浮点数 double
【代码】:

#include <stdio.h>

int main()
{
	printf("请分别输入身高的英尺和英寸,"
		"如输入\"5 7\"表示5英尺7英寸:");

	double foot;
	double inch;

	scanf("%lf %lf", &foot, &inch); // lf 来表达输入的事 double 类型

	printf("身高是%f米。\n", 
		((foot + inch / 12) * 0.3048));

    return 0;
}

运行结果与上述相同。

(2)总结:

1、整数 int :输入输出都用%d

printd("%d",...);
scanf("%d",...);

2、带小数点的数:

double
printf("%f",...);
scanf("lf",...);

5、计算时间差:

【思路】:
1、程序中要有哪些变量,这些变量要怎么读入数据、表达数据;
2、有了数据以后,怎么去计算;
【代码】:

#include <stdio.h>

int main()
{
	int hour1,minute1;
    int hour2,minute2;
    int t1,t2,t;

    scanf("%d %d",&hour1,&minute1);
    scanf("%d %d",&hour2,&minute2);

    t1 = hour1 * 60 + minute1;  // 转换成以分钟为单位
    t2 = hour2 * 60 + minute2;

    t = t2 - t1;

    printf("时间差是%d小时%d分", t/60, t%60 );  // t/60 -- 小时部分, t%60 -- 分钟部分

	return 0;
}

【运行结果】:
Alt

(1)运用for循环语句 优化

#include <stdio.h>

int main()
{
	int hour1,minute1;
    int hour2,minute2;
    int ih,im;

    scanf("%d %d",&hour1,&minute1);
    scanf("%d %d",&hour2,&minute2);

    ih = hour2 - hour1;
    im = minute2 - minute1;

    if(im<0){
        im = 60+im;
        ih --;
    }

    printf("时间差是%d小时%d分", ih, im );  
    
	return 0;
}

Alt
运行结果正确。

6、求两数平均值

【思路】:
1、有什么样的变量来保存读进来的东西;
2、怎么计算;

【代码】:

#include <stdio.h>

int main()
{
    int a,b;
    double c;

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

    c = (a + b) / 2.0;

    printf("%d和%d的平均值=%lf\n",a,b,c);

	return 0;
}

【运行结果】:
Alt

7、逆序的三位数

逆序的三位数:
程序每次读入一个正三位数,然后输出逆序的数字。注意,当输入的数字含有结尾的0时,输出不应带有前导的0。比如输入700,输出应该是7。
提示:用%10可以得到个位数,用/100可以得到百位数…。将这样得到的三个数字合起来:百位100+十位10+个位,就得到了结果。

【代码】:

#include <stdio.h>

int main()
{
    int a;

    printf("请输入一个三位数:");
    scanf("%d",&a);

    printf("逆序数 = %d\n", (a%10)*100+(((a-(a/100)*100)/10)*10)+a/100);
        // 得到十位数的方法也可以是:① a%100,再/10 ;或 ② a/10 再 %10
	return 0;
}

Alt
Alt

8、计算薪水:

#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);
	else
   		pay = hours * RATE;
	printf("应付工资: %f\n", pay);

	return 0;
}

9、判断成绩

#include <stdio.h>

int main()
{
	const int PASS=60;
	int score;

	printf("请输入成绩: ");
	scanf("%d", &score);
	
	printf("你输入的成绩是%d.\n", score);
	if ( score < PASS )
		printf("很遗憾,这个成绩没有及格。");
	else {
		printf("祝贺你,这个成绩及格了。");
		printf("再见\n");
	}

	return 0;
}

10、判断数字的位数

① 四位数及以下:
#include<stdio.h>

int main()
{
    int x;
    int n = 1;

    scanf("%d",&x);

    if(x>999)
        n = 4;
    else if (x > 99)
        n = 3;
    else if(n > 9)
        n = 2;
    else
        n = 1;
    printf("%d\n",n);

    return 0;
}
② 优化 —— 循环语句
#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;
}

【Note】:程序中, ++n; x/=10;不能全写到while循环语句中。因为x = 0 时,n应该 = 1。

③ do-while 循环进行优化
	do
	{
		<循环体语句>
	}while(<循环条件>);

【note】:
1、无论条件满不满足,do-while一定会做一遍;而while在条件不满足时,什么都不做。

#include<stdio.h>

int main()
{
    int x;
    int n = 0;

    scanf("%d",&x);
    do
    {
        x /= 10;
        n++ ;
    } while(x > 0);
    printf("%d\n",n);

    return 0;
}

11、 阶乘 运算

(1)while 循环

#include<stdio.h>

int main()
{
    int n;
    int fact = 1;
    int i = 1;

    scanf("%d",&n);

    while(i <= n){
        fact *= i;
        i++;
    }
    printf("%d!=%d\n",n,fact);

    return 0;
}

(2)for 循环

#include<stdio.h>

int main()
{
    int n;
    int fact = 1;
    int i = 1;

    scanf("%d",&n);

    /* 从 1 乘到 n */
    //for(i=1; i<=n; i++ ){  // ① 初始条件;② 循环条件;③ 增加步长
    //    fact *= i;
    //}

    for(i=n; i>1; i--){ // 从 n 乘到 1
        fact *= i;
    }
    printf("%d!=%d\n",n,fact);

    return 0;
}

for 语句也可写成如下,但只有C99编译能使用;

for( int i=1; i<=n; i++ ){  
        fact *= i;
    }

12、三个数大小的比较

#include<stdio.h>
#include<stdbool.h>

int main(){
    int a,b,c,max;
    scanf("%d %d %d",&a,&b,&c);

    if(a>b){
        if(a>c)
            max = a;
        else
            max = c;
    }
    else{
        if(b>c)
            max = b;
        else
            max = c;
    }
    printf("The max is %d\n",max);
    
    return 0;
}

【Note】:

  1. 缩进格式不能暗示else的匹配;
  2. tips: 即使只有一条语句,if 和 else 后面也要用大括号{ }!易于理解!

13、循环计算 —— 计算log 以 2 为底,x 的对数

#include<stdio.h>

/* 计算log 以 2 为底,x 的对数*/
int main(){
    int x,t;
    int ret = 0;
    scanf("%d",&x);

    t = x;
    while( t > 1 ){
        t /= 2;
        ret ++;
    }
   
    printf("log2 of %d is %d.\n", x, ret);
      
    return 0;
}

14、算平均数

【要求】:输入一系列正整数,最后输入 -1 表示输入结束,然后计算这些数字的平均数,输出输入的数字的个数和平均数。
【思路】:

  • 变量 —> 算法 —> 流程图 —> 程序
    【代码】:
#include<stdio.h>

/* 计算平均数 */
int main(){
    int number;
    int sum = 0;
    int count = 0;

    scanf("%d",&number);
    while(number != -1){
        sum += number;
        count ++;
        scanf("%d",&number);
    }

/*    do{
        scanf("%d",&number);
        if(number != -1){
            sum += number;
            count++;        // count 表明从程序中读入了多少个数据;
        } 
    }while (number != -1);
*/
    printf("输入的%d个数的平均数 = %f\n", count, 1.0*sum / count);
      
    return 0;
}

15、猜数游戏

【需求】:计算机想一个数,让用户来猜。用户每输入一个数据,就告诉他大了还是小了,直到用户猜中为止。最后还要告诉他猜了多少次。
【思路】:

  1. 计算机随机想一个数,记在变量number中;
  2. 负责计数的变量 count 初始化为0;
  3. 让用户输入一个数字a;
  4. count++;
  5. 判断number与 a 的大小关系,如果 a 大,就输出“大”;如果 a 小,就输出 a “小”;
  6. 重复循环
  7. 否则,输出 “猜中” 和次数,结束。

【代码】:

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

/* 猜数游戏 */
int main(){
    srand(time(0));
    int number = rand()%100+1;  // 每次 召唤 rand() 就得到一个随机的整数;
                                // x % n 的结果是 [0,n-1] 的一个整数;
    int a = 0;
    int count = 0;

    printf("我已经想好了一个 1-100 之间的数。\n");
    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;
}

【Note】:

  1. x % n的结果是 [0,n-1] 的一个整数;
  2. 每次 召唤rand() 就得到一个随机的整数;

【运行结果】:
Alt

16、整数求逆

【思路】:

  • 对一个整数做%10的操作,就可的到 个位数;
  • 对一个整数做/10的操作,就去掉了个位数
  • ……

【代码】:

#include<stdio.h>

/* 整数求逆 */
int main(){
    int x,t;
    int digit;
    int ret = 0; // 初始时结果为0
    
/* 此时若输入为 700,则输出为 7 */
    scanf("%d",&x);
    t = x;
    while(x > 0){
        digit = x%10;
        // printf("%d\n",digit);
        ret = ret *10 + digit;
        printf("x=%d, digit=%d, ret=%d\n", x, digit, ret);
        x /= 10;
    }
    printf("整数%d的逆=%d。\n", t,ret);
      
    return 0;
}

Alt

/* 此时若输入为 700,则输出为 007 */
    scanf("%d",&x);
    t = x;
    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;
    }

17、判断一个数是不是素数

【需求】:读入一个数x,判断x是不是素数。
素数:只能被 1 和自己整除的数,不包括1.

【代码】:

#include<stdio.h>

/* 判断是否是素数 */
int main(){
    int x;
    int i;
    int isPrime = 1;    // isPrime = 1,则 x 是素数
    scanf("%d",&x);

    for (i=2; i<x; i++){
        if( x % i == 0){     // 说明不是素数
            isPrime = 0;
            break;          //break; --- 跳出循环  ; continue; --- 跳过这一轮循环,进入下一轮
        }
    }
    if (isPrime == 1){
        printf("是素数。\n");
    } else {
        printf("不是素数。\n");
    }
     
    return 0;
}

【Note】:

  • break; ---- 跳出循环;
  • continue; ---- 跳过这一轮循环中剩下的语句,进入下一轮

【或】:

/* 判断是否是素数 */
int main(){
    int x;
    int i;
//    int isPrime = 1;    // isPrime = 1,则 x 是素数
    scanf("%d",&x);

    for (i=2; i<x; i++){
        if( x % i == 0){     // 说明不是素数
//            isPrime = 0;
            break;          //break; --- 跳出循环  ; continue; --- 跳过这一轮循环,进入下一轮
        }
    }
//    if (isPrime == 1){
    if (i == x){
        printf("是素数。\n");
    } else {
        printf("不是素数。\n");
    }
  • 优点:节省了程序变量的内存消耗。
  • 缺点:程序有两个要求,一是要机器能读,二是人要能读。这种聪明的做法,逻辑不清晰,其他人读程序时会耗费更多的脑细胞,不利于后期程序移植、维护和团队合作。

18、输出100以内的素数

【代码】:

#include<stdio.h>

/* 输出 1-100 的素数 */
int main(){
    int x;
    int i;
    int isPrime = 1;    // isPrime = 1,则 x 是素数
    //scanf("%d",&x);
    x = 6;

    for (x=2; x<100; x++)
    {
        for (i=2; i<x; i++){
            if( x % i == 0){     // 说明不是素数
                isPrime = 0;
                break;          //break; --- 跳出循环  ; continue; --- 跳过这一轮循环,进入下一轮
            }
        }
        if (isPrime == 1){
            printf("%d ",x);
        } 
    }
    printf("\n");

    return 0;
}

19、输出前50个素数

【代码1】:

#include<stdio.h>

/* 输出前50个素数 */
int main(){
    int x;
    int i;
    int isPrime = 1;    // isPrime = 1,则 x 是素数
    int cnt = 0;        // 计数器
    //scanf("%d",&x);
    x = 2;

//    for (x=2; x<100; x++)
    while (cnt < 50)
    {
        for (i=2; i<x; i++){
            if( x % i == 0){     // 说明不是素数
                isPrime = 0;
                break;          //break; --- 跳出循环  ; continue; --- 跳过这一轮循环,进入下一轮
            }
        }
        if (isPrime == 1){
            printf("%d ",x);
            cnt++;
        } 
        x++;
    }
    printf("\n");

    return 0;
}

【代码2】:

//    for (x=2; x<100; x++)
//    while (cnt < 50)
    for (x=2; cnt<50; x++)
    {
        for (i=2; i<x; i++){
            if( x % i == 0){     // 说明不是素数
                isPrime = 0;
                break;          //break; --- 跳出循环  ; continue; --- 跳过这一轮循环,进入下一轮
            }
        }
        if (isPrime == 1){
            printf("%d ",x);
            cnt++;
        } 
    //    x++;
    }
    printf("\n");

20、凑硬币 _ 用1角、2角、5角的硬币凑出10元以下的金额

【代码①】:—— 接力 break
#include<stdio.h>

/* 凑硬币 _ 用1角、2角、5角的硬币凑出10元以下的金额 */
int main()
{
    int x;
    int one,two,five;
    int exit = 0;

    scanf("%d",&x);
    for(one=1; one<x*10; one++){    // 1角最多是 x*10个
        for(two=1; two < x*10/2; two++){    // 2角最多是 x*10/2 个
            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;              /* 【接力 break】*/
                }
            }
            if(exit)    break;  // 相当于 exit ==1;
        }
        if(exit)    break;
    }

    return 0;
}

【Note】:

  • break 和 continue 只能对它所在的那层循环做;
【代码②】:—— goto语句
  • goto 语句非常适合用于,多重嵌套循环的内层循环直接跳到最外面的情形。
#include<stdio.h>

/* 凑硬币 _ 用1角、2角、5角的硬币凑出10元以下的金额 */
int main()
{
    int x;
    int one,two,five;
    int exit = 0;

    scanf("%d",&x);
    for(one=1; one<x*10; one++){    // 1角最多是 x*10个
        for(two=1; two < x*10/2; two++){    // 2角最多是 x*10/2 个
            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;
}

21、求前 n 项和

① f(n)=1+1/2+1/3+…1/n

【代码】:

#include<stdio.h>

/* 求前 n 项和 —— 1+1/2+1/3+…1/n */
int main()
{
    int n;
    int i;
    double sum = 0.0;

    scanf("%d",&n);
    for (i=1; i<=n; i++){
        sum += 1.0/i;
    }
    printf("f(%d)=%f\n",n,sum);

    return 0;
}
② f(n)=1-1/2+1/3-1/4+…+1/n
#include<stdio.h>

/* 求前 n 项和 _f(n)=1-1/2+1/3-1/4+…+1/n */
int main()
{
    int n;
    int i;
    double sum = 0.0;
    int sign = 1;

    scanf("%d",&n);
    for (i=1; i<=n; i++){
        sum += sign*1.0/i;
        sign = -sign;
    }
    printf("f(%d)=%f\n",n,sum);

    return 0;
}

【或】:直接把 sign 定义为 double 类型
主程序:

    int n;
    int i;
    double sum = 0.0;
    // int sign = 1;
    double sign = 1.0;

    scanf("%d",&n);
    for (i=1; i<=n; i++){
        sum += sign/i;
        sign = -sign;
    }
    printf("f(%d)=%f\n",n,sum);

22、求最大公约数

法①:枚举

【思路】:

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

【代码】:

#include<stdio.h>

/* 求最大公约数 */
int main()
{
    int a,b;
    int min;
    int ret;
    int i;

    scanf("%d %d",&a,&b);
    if (a<b){
        min = a;
    }else {
        min = b;
    }
    for (i=1;i<min;i++){        // 从 1 开始,到 a 和 b 的最小值
        if (a%i == 0){          // a 能被 i 整除
            if ( b%i == 0){     // b 能被 i 整除
                ret = i;    // 目前的公约数
            }
        }
    }
    printf("%d和%d的最大公约数是%d\n",a, b, ret);

    return 0;
}

法②:辗转相除法

【思路】:

  1. 如果b等于0,计算结束,a 就是最大公约数;
  2. 否则,计算 a 除以 b 的余数,让 a 等于 b ,而 b 等于那个余数;
  3. 回到第一步;
    eg.
	a	b	t	// t—— 余数
	12	18	12
	18	12	6
	12	6	0
	6	0

【代码】:

#include<stdio.h>

/* 求最大公约数 */
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("gcd=%d.\n", a);

    return 0;
}

【运行结果】:
Alt

23、正序分解整数

  • 输入一个非负整数,正序输出它的每一位数字;
  • 输入:13425
  • 输出:1 3 4 2 5
法①:先逆序,再逆序

【代码】:

#include<stdio.h>

/* 求最大公约数 —— 先逆序,再逆序,—— 只适用于末尾不是0的数*/
int main()
{
    int x,d;
    int t = 0;

    scanf("%d",&x);
    do{             /* 做【逆序】 */
        d = x%10;
        t = t*10 + d;
        x /= 10;    // x 右移一位
    }while (x>0);
    printf("x=%d,t=%d\n",x,t);
    x = t;
    do{             /* 【再逆序】 */
        int d = x%10;   // 得到最右边的一位
        printf("%d",d);
        if (x>=10){
            printf(" ");    // 使最后一轮时不输出空格
        }
        x /= 10;        // x 右移一位
    } while( x>0 );
    printf("\n");

    return 0;
}

【运行结果】:
Alt

法②:正序输出

【思路】:

eg.
		x = 13425;
		13425 / 10000	--> 1
		13425 % 10000	--> 3425
		10000 / 10		--> 1000
		3425 / 1000	 -->3
		3425 % 1000	 -->435
		1000 / 10	 -->100
		425 / 100  -->4
		425 % 100  -->25
		100 /10	   -->10
		25 / 10	-->2
		25 % 10	-->5
		10 /10	-->1
		5 / 1 -->5
		5 % 1 -->5
		1 /10 -->0
	 		

【代码】:

#include<stdio.h>

/* 求最大公约数 —— 正序输出 */
int main()
{
    int d,x;
    int mask = 1;
    int t = 0;
    int cnt = 0;
    x = 13425;

    t = x;
    while (x > 9){                 // 可以知道 x 的位数
        x /= 10;
        mask *= 10;
        //cnt++;
    } 
    printf("mask = %d\n",mask);
    // mask = pow(10,cnt-1);   // mask=10^(cnt-1)
    do{
        d = t / mask;
        printf("%d",d);
        if( mask >9 ){
            printf(" ");
        }
        t %= mask;
        mask /= 10;
        // printf("x=%d,mask=%d,d=%d\n",x,mask,d);
    }while ( mask >0 );
    printf("\n");

    return 0;
}

三、PTA编程练习

1、厘米换算成英尺、英寸

Alt
【代码】:

#include<stdio.h>

int main(){
    int foot,inch;
    int cm;
    float m,t;
    
    scanf("%d",&cm);
    m = cm/100.0;
    // foot + inch / 12 = m/0.3048;
    t = m/0.3048;
    // foot = t的整数部分;
    // inch = t的小数部分*12
    foot = t;
    inch = (t - foot)*12;
    printf("%d %d",foot,inch);
    
    return 0;
    
}

【运行结果】:
Alt

你可能感兴趣的:(C语言,c语言,算法,c++)