C语言零基础入门级数据类型+运算符+控制流+ASCII 码表+面试题【系统学习第二天】

C语言零基础入门级数据类型+运算符+控制流

第一项 C语言-》数据类型全讲解上

【1】整型int

概念:表达整数类型的数据
语法:

int a = 123; // 定义了一个专门用来存储整数的变量a 

需要注意的地方:

int 的本意是 integer,即整数的意思 int a 代表在内存中开辟一块小区域,称为 a,用来存放整数,a 一般被称为变量。 变量
a 所占内存大小,在不同的系统中是不一样的,64位系统典型的大小是4个字节。 变量 a
有固定的大小,因此也有取值范围,典型的范围是:-2147483648到2147483647

【2】整型修饰符short、long、unsigned

short:用来缩短整型变量的尺寸,减少取值范围并节省内存,称为短整型
long:用来增长整型变量的尺寸,增大取值范围并占用更多内存,称为长整型
long long:用来增长整型变量的尺寸,增大取值范围并占用更多内存,称为长长整型
unsigned:用来去除整型变量的符号位,使得整型变量只能表达非负整数
short int a; // 短整型
long int b; // 长整型
long long int c; // 长长整型
==unsigned int e; ==// 无符号整型
unsigned short int f; // 无符号短整型
unsigned long int g; // 无符号长整型
unsigned long long int h; // 无符号长长整型

使用整型修饰符后,关键字 int 可以被省略:

short a; // 短整型
long b;  // 长整型
long long c; // 长长整型
unsigned e;  // 无符号整型
unsigned short f; // 无符号短整型
unsigned long g;  // 无符号长整型
unsigned long long h; // 无符号长长整型

【3】符号位

有符号的整型数据,首位为符号位,0表示正数,1表示负数。 无符号的整形数据,没有符号位。

编码形式:

原码:正数直接使用二进制来表达,比如a=100,在内存中是 00…001100100
补码:负数用绝对值取反加一来表达,比如a=-3,在内存中是11…1111111101 注意负数的补码在取反加一的时候,符号位是不动的
溢出:超过数据所能表达的范围,称为溢出,就像汽车里程表,最大值和最小值是相邻的

在这里插入图片描述

进制:源码中可以使用八进制、十进制或十六进制,但实际数据在内存中一律是二进制
十进制(默认),比如1099
八进制,比如013
十六进制,比如0x6FF0A

【4】格式控制符%d+%hd+%ld+%lld+%#o、 %#x

int 整型:%d
short 整型:%hd, h代表half,即一半的存储字节
long 整型:%ld
long long 整型:%lld
显示不同进制的前缀: %#o、 %#x

【5】浮点型float+double +long double

概念:用来表达实数的数据类型
分类:

单精度浮点型(float),典型尺寸是4字节
双精度浮点型(double),典型尺寸是8字节
长双精度浮点型(long double),典型尺寸是16字节 占用内存越多,能表达的精度越高

float f1; // 单精度
double f2; // 双精度
long double f3; // 长双精度

在这里插入图片描述

【6】字符char+ASCII 码表

char ch1 = 'a';  // 'a'是字符常量,代表字母a
char ch2 = '\n'; // '\n'是不可见字符常量,代表回车

计算机中存储的都是1和0,因此各种字符都必须被映射为某个数字才能存储到计算机中,这种映射关系形成的表称为 ASCII 码表。

在这里插入图片描述
在这里插入图片描述

字符本质上就是一个单字节的整型,支持整型所有的运算。比如:

char c1 = 20;
char c2 = c1 + 'a'; // 等价于 char c2 = 20 + 97;

printf("%c\n", c2); // 以字符形式输出117,即 'u'
printf("%d\n", c2); // 以整型形式输出117

【7】字符串char *s1+char s2[]+指针和数组

定义
字符串的定义方式有两种:指针和数组

char *s1 = "abcd"; // 使用字符指针来表示字符串
char s2[]= "abcd"; // 使用字符数组来表示字符串

注意,使用数组来定义字符串时,方括号[]里面的数字可以省略
不省略也可以,但必须必字符串实际占用的内存字节数要大,比如:

char s3[] = "apple";

在内存中的存储 在内存中实际上是多个连续字符的组合 任何字符串都以一个 ‘\0’ 作为结束标记,例如:“funny story” 的内存如下
在这里插入图片描述

【8】布尔型数据 bool

概念:布尔型数据只有真、假两种取值,非零为真,零为假。
语法:

bool a = 1; // 逻辑真,此处1可以取其他任何非零数值
bool b = 0; // 逻辑假 

注意: 逻辑真除了 1 之外,其他任何非零数值都表示逻辑真,等价于 1。 使用布尔型 bool 定义变量时需要包含系统头文件
stdbool.h。 布尔型数据常用语逻辑判断、循环控制等场合。

【9】常量与变量

概念:不可改变的内存称为常量,可以改变的内存称为变量
举例:

int a = 100;    // a是变量,而100是常量
float f = 3.14; // f是变量,而3.14是常量
char s[] = "abcd"; // s是变量,"abcd"是常量

在这里插入图片描述

【10】标准输入 scanf+fgets+stdin

概念:键盘是系统的标准输入设备,从键盘中输入数据被称为标准输入
相关函数:

scanf(); // 格式化输入函数
fgets(); // 字符串输入函数

int a;
float f;
scanf("%d", &a);   // 从键盘输入一个整型,放入指定的内存地址 &a 中
scanf("%f", &f);   // 从键盘输入一个浮点数,放入指定的内存地址 &f 中

scanf("%d%f", &a, &f); // 从键盘依次输入一个整型和一个浮点型数据,用空白符隔开

char c;
char s[10];
scanf("%c", &c);  // 从键盘输入一个字符,放入指定的内存地址 &f 中
scanf("%s", s );  // 从键盘输入一个单词,放入指定的数组 s 中(注意不是&s)

fgets(s, 10, stdin); // 从键盘输入一行字符串,放入数组 s 中

注意1:

scanf() 与 printf() 不同,scanf() 的格式控制串不可乱写,尤其是结尾处的 \n 用户必须完全按照 scanf()
中描述的输入格式控制串来输入数据,否则将出错。

示例:

// 此处输入时必须带逗号
scanf("%d,%d", &a, &b);
// 此处必须先输入a=,然后才能输入整数
scanf("a=%d", &a); 

**错误点 **

// 此处结束输入时按下的回车符将被scanf()误以为格式控制符,无法正常结束输入
scanf("%d\n", &a); 

注意2:

scanf() 的返回值,代表成功从键盘读取的数据的个数 无法匹配 scanf() 指定格式的数据,将被遗留在输入缓冲区中,不会消失 示例:

// scanf() 试图从键盘读取两个整数
// 返回值 n 代表成功读取的个数,比如:
// 输入100 200,则 n 将等于2
// 输入100 abc,则 n 将等于1
// 输入abc xyz,则 n 将等于0;输入abc 200,n也将等于0
int n = scanf("%d%d", &a, &b);

// 根据 scanf() 的返回值,判断用户是否输入了正确的格式
while(n != 2)
{
    // 需要清空缓冲区并提示用户重新输入
    char s[50];
    fgets(s, 50, stdin);
    printf("请重新输入两个整数\n");

    n = scanf("%d%d", &a, &b);
}

第二项 C语言-》数据类型全讲解下

【11】类型转换 隐式转换+强制转换+隐式规则

概念:不一致但相互兼容的数据类型,在同一表达式中将会发生类型转换。
转换模式:

隐式转换:系统按照隐式规则自动进行的转换
强制转换:用户显式自定义进行的转换
隐式规则:从小类型向大类型转换,目的是保证不丢失表达式中数据的精度
在这里插入图片描述
隐式转换示例代码

char  a = 'a';
int   b = 12;
float c = 3.14;
float x = a + b - c; // 在该表达式中将发生隐式转换,所有操作数被提升为float

强制转换:用户强行将某类型的数据转换为另一种类型,此过程可能丢失精度

char  a = 'a';
int   b = 12;
float c = 3.14;
float x = a + b - (int)c;

在该表达式中a隐式自动转换为int,c被强制转为int
不管是隐式转换,还是强制转换,变换的都是操作数在运算过程中的类型,是临时的,操作数本身的类型不会改变,也无法改变。

【12】数据类型的本质

概念:各种不同的数据类型,本质上是用户与系统对某一块内存数据的解释方式的约定。
推论:

类型转换,实际上是对先前定义时候的约定,做了一个临时的打破。 理论上,可以对任意的数据做任意的类型转换,但转换之后的数据解释不一定有意义。

【13】整型数据 size

概念:整型数据尺寸是指某种整型数据所占用内存空间的大小

C语言标准并未规定整型数据的具体大小,只规定了相互之间的 “ 相对大小 ” ,比如:

short 不可比 intlong 不可比 intlong 型数据长度等于系统字长

系统字长:CPU 一次处理的数据长度,称为字长。比如32位系统、64位系统。

典型尺寸:

char 占用1个字节
short 占用2个字节
int16位系统中占用2个字节,在32位和64位系统中一般都占用4个字节
long 的尺寸等于系统字长
long long32位系统中一般占用4个字节,在64位系统中一般占用8个字节

存在问题:

同样的代码,放在不同的系统中,可能会由于数据尺寸发生变化而无法正常运行。
因此,系统标准整型数据类型,是不可移植的,这个问题在底层代码中尤为突出。

【14】可移植性整型 typedef

概念:不管放到什么系统,尺寸保持不变的整型数据,称为可移植性整型
关键:typedef

typedef int int32_t;  // 将类型 int 取个别名,称为 int32_t
typedef long int64_t; // 将类型 long 取个别名,称为 int64_t

思路:

为所有的系统提供一组固定的、能反应数据尺寸的、统一的可移植性整型名称 在不同的系统中,为这些可移植性整型提供对应的 typedef 语句
系统预定义的可移植性整型:
int8_t
int16_t
int32_t
int64_t

uint8_t
uint16_t
uint32_t
uint64_t

pid_t
time_t
size_t … …

第三项 C语言-》运算符

【15】算术运算符

在这里插入图片描述
关注点:

减号也是负号,比如 -a 是取变量 a 的相反数。 取模运算要求左右两边操作数必须是整型数据。
自加和自减运算不仅可以对整型操作,也可以对浮点数、指针操作。 前后缀运算:

  1. 前缀自加自减运算:先进行自加自减,再参与表达式运算
  2. 后缀自加自减运算:先参与表达式运算,在进行自加自减
int a = 100;
int b = 200;

int c = ++a; // a先自加1,变成101;然后再赋值给c,因此c等于101
int d = b++; // b先赋值给d,因此d等于200;然后b自加1,变成201

【16】关系运算符

在这里插入图片描述
关注点:

关系运算符用于判断运算符两边的表达式是否满足给定的大小条件。 由关系运算符组成的表达式称为关系表达式,其值为布尔型。
判断是否相等是双等号==,而不是一个等号。

【17】逻辑运算符

在这里插入图片描述
运算规则:

逻辑反:将逻辑真、假翻转,即真变假,假变真。
逻辑与:将两个关系表达式串联起来,当且仅当左右两个表达式都为真时,结果为真。
逻辑或:将两个关系表达式并联起来,当且仅当左右两个表达式都为假时,结果为假。

在这里插入图片描述
特殊规则:

在逻辑与运算中,如果左边表达式的值为假,那么右边表达式将不被执行。 在逻辑或运算中,如果左边表达式的值为真,那么右边表达式将不被执行。

【18】位运算符

在这里插入图片描述
位运算符操作的对象是数据中的每一位
运算规则:

位逻辑反、位逻辑与、位逻辑或拥有与逻辑运算相似的规则和一样的真值表
异或运算:相同为0,不同为1
移位运算:移出去的不要,空出来的补零。移位运算都是针对无符号数的运算。
左移:
在这里插入图片描述
右移:
在这里插入图片描述

【19】特殊运算符

赋值运算符

不能对常量赋值,只能对变量赋值 不能对数组赋值 可以连续赋值,顺序从右到左

int a, b;
int x[5];

a = 100; // 对变量 a 赋值,正确
3 = 100; // 对常量 3 赋值,错误!
x = 123; // 对数组 b 赋值,错误!
// 连续赋值
a = b = 50; // 先将 50 赋给 b,再将 b 的值赋给 a,正确

复合赋值符

当左右两边有相同的操作数时,采用复合赋值符不仅直观,且能提高运算效率 除了下述10个复合运算符之外,生造别的复合运算符是非法的

// 加减乘除:
a += n; // 等价于 a = a+n;
a -= n; // 等价于 a = a-n;
a *= n; // 等价于 a = a*n;
a /= n; // 等价于 a = a/n;
// 求余:
a %= n; // 等价于 a = a%n;
// 位运算:
a &= n; // 等价于 a = a&n;
a |= n; // 等价于 a = a|n;
a ^= n; // 等价于 a = a^n;
a >>= n; // 等价于 a = a>>n;
a <<= n; // 等价于 a = a<<n;

【20】条件运算符

唯一需要三个操作数的运算符
语法:表达式1 ? 表达式2 : 表达式3
释义:当表达式1为真时,取表达式2,否则取表达式3

举例:

int a = 100;
int b = 200;
int m = (a>b) ? a : b;  // 如果 a>b 为真,则 m 取 a 的值,否则取 b 的值

【21】sizeof 运算符

含义:计算指定数据类型或者变量所占据内存的字节数
语法:sizeof(类型) 、sizeof(变量) ,计算变量的字节数时圆括号可以省略

举例:

printf("%d\n", sizeof(int));
printf("%d\n", sizeof(long double));

int a[5];
printf("%d\n", sizeof(a));
printf("%d\n", sizeof a);

【22】return运算符

含义:退出某个函数(如果退出的是主函数main,那么整个程序也就退出了) 语法:必须出现在函数体内,可以带函数对应类型的数据

举例:

int main()
{
    return 0;
}

【23】优先级与结合性+优美表格

当表达式中出现不同的运算符时,根据优先级来决定谁先执行,比如先乘除,后加减
当表达式中出现多个相同优先级的运算符时,根据结合性来决定谁先运行,比如从左到右

在这里插入图片描述

第四项 C语言-》控制流

【24】二路分支 if-else

逻辑:程序中某段代码需要在满足某个条件时才能运行
形式:

if 语句:表达一种 如果-则 的条件执行关系
if-else 语句:表达一种 如果-否则 的互斥分支关系

举例:

// if 语句
if(a%2 == 0)
{
    printf("a是偶数\n");
}
//if-else 语句
if(a%2 == 0)
{
    printf("a是偶数\n");
}
else
{
    printf("a是奇数\n");
}

注意:

if 语句可以单独使用,else 语句不可以,else 语句必须跟if语句配套使用 不管是 if 语句还是 else
语句,代码块都必须使用大括号{}括起来,否则只有首句有效

【25】多路分支 switch

逻辑:根据不同的条件执行不同的代码片段
语法:

switch(n)
{
case 1:
    printf("one\n");
    break;

case 2:
    printf("two\n");
    break;
  
case 3:
    printf("three\n");
    break;
  
default:
    printf("其他数字\n");
}

要点解析:

switch(n) 语句中的 n 必须是一个整型表达式,即 switch 判断的数据必须是整型 case
语句只能带整型常量,包括普通整型或字符,不包括 const 型数据。 break 语句的作用是跳出整个 swtich 结构,没有 break
程序会略过case往下执行 default 语句不是必须的,一般放在最后面(因此不需要 break)

【26】const巧用

逻辑:使一个变量不可修改
作用:

修饰普通变量,使之不可修改
修饰指针变量,使之不可修改或者使其指向的目标不可修改
示例:

int const a = 100; // 定义了一个不可修改的变量a
const int b = 200; // 定义了一个不可修改的变量b

a = 101; // 错误
b = 202; // 错误

【27】while与 do…while循环

逻辑:使得程序中每一段代码可以重复循环地运行
形式:

while 循环:先判断,再循环
do-while 循环:先循环,再判断

在这里插入图片描述
while循环:入口判断

// 循环输出一系列整数,直到100为止
int a;
scanf("%d", &a);
while(a <= 100)
{
    printf("%d\n", a);
    a++;
}
do-while循环:出口判断
// 循环输出一系列整数,直到100为止
int a;
scanf("%d", &a);
do
{
    printf("%d\n", a);
    a++;
}while(a <= 100);

在这里插入图片描述
语法点:

while 循环先进行判断,条件为真后才执行循环体,因此循环体可能一遍也不执行。
do-while循环先执行循环体,再进行判断,因此循环体至少会执行一遍。
do-while 循环中的 while 语句后面有分号;

【28】for循环

逻辑:与 while 循环类似,但更加紧凑,for 循环将控制循环的变量集中在一行
示例:

// 循环输出一系列整数,直到100为止
int a;
for(a=30; a<=100; a++)
{
    printf("%d\n", a);
}

语法点:

循环头的标准语法是: for(表达式1 ; 表达式2 ; 表达式3)
表达式1一般用来初始化循环控制变量
表达式2一般用来作为循环判定条件,为真则进入循环,为假则跳出循环
表达式3一般用来更新循环控制变量 三个表达式均可以省略,但分号不能省略

【29】break与continue

逻辑:

break:① 跳出 switch 语句; ② 跳出当层循环体
continue:结束当次循环,进入下次循环

举例:

switch(n)
{
case 1:
    printf("one\n");
    break;  // 跳出 switch 语句
case 2:
    printf("two\n");
    break;        
}

while(1)
{
    int n = scanf("%d", &a);
    if(n == 0)
        break; // 跳出当层 while 循环体
}

for(int i=1; i<=100; i++)
{
    if(i%7 == 0)
        continue; // 跳过所有能被7整除的数
     
    printf("%d\n", i);       
}

【30】goto语句

逻辑:无条件跳转
示例:

int main()
{
    printf("%d\n", __LINE__); // 打印第3行 
    
    // 无条件跳转到label处 
    goto label;
    printf("%d\n", __LINE__); // 打印第7行,此处被略过
label:  
    printf("%d\n", __LINE__); // 打印第9行
}

语法:

goto语句直接跳转到本代码块中的标签处 标签指的是以冒号结尾的标识符

作用:

goto语句的无条件跳转不利于程序的可读性,一般不建议使用 goto语句,常被用在程序的错误处理中

第五项 C语言-》举例实例+面试题攻坚克难

第一题

指出下列常量的类型:

‘\b’
1066
99.44
0XAA
2.0e30
0x00EEABCDUL

解答:

'\b' : char字符型数据,代表退格键
1066 : int整型数据,十进制整数
99.44: float浮点型数据
0XAA : int整型数据,十六进制整数
2.0e30 : float浮点型数据,科学计数法,代表2乘以1030次方
0x00EEABCDUL : unsigned long无符号整型数据,十六进制,末尾的UL代表无符号长整型

第二题

编程实现如下功能:

如果用户输入大小写字母,则输出字母对应的ASCII码值。
如果用户输入ASCII码值,则输出对应的大小写字母。

#include <stdio.h>

int main(void)
{
    int ch;

    while(1)
    {
        int n;
        n = scanf("%d", &ch);

        // 输入了ASCII码值
        if(n == 1 && getchar() == '\n')//输入一个值,并且敲了回车
        {
            printf("%c\n", ch);
        }

        // 输入了非数字字符
        else if(n == 0)
        {
            ch = getchar();

            if(ch>='A'&&ch<='Z' || ch>='a'&&ch<='z')
                printf("%d\n", ch);
            else
                printf("letters only\n");
        }

        // 数字后面带有非法字符
        else
        {
            printf("只能输入整数或字母\n");
            while(getchar()!='\n');
        }
    }

    return 0;
}

第三题

问题1: 假设有如下程序,程序输出的结果是什么?

int main(void)
{
    unsigned char a, b, c;
    a = 0x3;
    b = a|0x8;
    c = b<<1;

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

解答1:

这是简单的位运算的题目,a在二进制中的数位是【0000 0011】,与十六进制数0x8的二进制数位是【0000
1000】,因此这两数数相或的结果是:【0000 1011】,所以 b 等于11。

对上述二进制数据 b 进行左移 1 位操作,结果是【0001 0110】,所以 c 等于22. 最终输出的结果是:

11
22

第四题

问题2:

假设有一个无符号32位整型数据

unsigned int data=0x12ff0045
请编写一个程序用位运算把data的第14、15位置位(即赋值为1),把22、23位置零(即赋值为0), 并且输出修改后的数据。

解答2:

本题考察基本位运算逻辑,要把某几位置位,只需将数据与对应掩码进行位或运算即可;要把某几位置零,只需将数据与对应掩码取反位与即可。参考代码如下:

#include <stdio.h>

// 第14、15位掩码:
uint32_t mask1 = 0x3<<14; // 0000 0000 0000 0000 1100 0000 0000 0000

// 第22、23位掩码:
uint32_t mask2 = 0x3<<22; // 0000 0000 1100 0000 0000 0000 0000 0000

int main(void)
{
    unsigned int data = 0x12ff0045;

    // 将bit[13]、bit[14]置位
    data |= mask1;
    printf("%x", data);
    
    // 将bit[22]、bit[23]置零
    data &= ~mask2;
    printf("%x",data);

    return 0;
}

第五题(基本数据类型)

【1】每一种数据类型都是有一定的表达范围的,编程实现一种算法,在不假定数据类型长度的条件下,用最简便的方式算出当前系统的整型 int
所能表达的最大值。

要求:
不能使用系统宏定义 INT_MAX。

//参考代码:

#include <stdio.h>

int main(void)
{
    // 方式一:
    int a=1, max;
    while(1)
    {
        max = a;

        a <<= 1;
        a  |= 1;

        if(a < 0)
            break;
    }
    printf("int的最大值为%d\n", max);

    // 方式二:
    int max = ~(0x1 << sizeof(int)*8-1);
    printf("int的最大值为%d\n", max)
}

第六题(基本数据类型、基本算数运算)

【2】编写一个程序,计算N升纯净水所包含的分子个数,结果用科学计数法表示。

解析:

本题主要考察对C语言程序中各种基本数据类型的理解,尤其是数据所表达的范围。由于水分子的数目非常大,因此整型数据可能会溢出,本题需要采用浮点数来计算水分子个数。

//参考代码:

#include <stdio.h>

// 每个水分子的质量是3.02-23千克
#define MASS 3.0e-23

int main(void)
{
	double molculers;
	double litre;

	printf("请输入水的升数:\n");

    while(1)
    {
        // 输入数字
	    if(scanf("%lf", &litre) == 1)
            break;

        // 输入非数字,清空缓冲区
        while(getchar()!='\n');
        printf("请输入数字\n");
    }

	molculers = litre / mass;
	printf("你拥有%lf个水分子!", molculers);

	return 0;
}

第七题(字符与字符串)

【3】简述 ‘a’ 与 “a” 的异同。

解析: ‘a’ 的类型是char,而 “a” 的类型是char*。字符’a’在内存中占据一个字节,而字符串 “a” 占据两个字节。

第八题(破除思维定式)

【4】编写一个程序,计算 1+2+3+4+…+n 的值。

解析:
一般初学者看到本题,大多会直接使用循环来解决,但是求解1到n的求和问题是有公式的,在程序中恰当地运用数学公式,可以极大提高程序效率,数学是程序开发者不可以遗忘的关键一环。

//参考代码:

#include <stdio.h>

int main()
{
    int n;
    scanf("%d", &n);

    // 直接利用数学公式,求解前n为自然数之和
    printf("1+...+n = %d\n", n*(1+n)/2);
    return 0;
}

第九题(基本输入输出、基本算术运算)

【5】编写一个程序,将用户输入的天数转化为等价的星期数和天数。 例如:

输入:18
输出:2
星期零4天

解析: 本题主要考察求余(取模)运算符。

//参考代码:

#include <stdio.h>

#define DAYS_PER_WEEK 7

int main(void)
{
	int days;
	printf("请输入天数:\n");

    while(1)
    {
        // 输入数字
	    if(scanf("%d", &days) == 1)
            break;

        // 输入非数字,清空缓冲区
        while(getchar()!='\n');
        printf("请输入数字\n");
    }

    printf("%d星期零%d天\n", days/7, days%7);
	return 0;
}

第十题(基本程序路基、单目增减运算符)

【6】分析并解释以下程序的执行结果。

#include <stdio.h>
int main(void)
{
    int x = 10;
    int a, b, c;
    a = x++;
    b = ++x;
    c = 10*x++;
    printf(“x=%d,a=%d,b=%d,c=%d\n”, x, a, b, c);   
    return 0;
}

第十一题(基本输入输出、基本算术运算)

【7】编写一个程序,用户输入华氏温度F,程序输出摄氏温度C,结果保留2位小数。

提示: 华氏温度F转化为摄氏温度C的公式为: C = 5×(F - 32)÷ 9

//参考代码:

#include <stdio.h>

int main(void)
{
	float fah;
    float cel;

	printf("请输入华氏温度:\n");
    while(1)
    {
        // 输入数字
	    if(scanf("%f", &fah) == 1)
            break;

        // 输入非数字,清空缓冲区
        while(getchar()!='\n');
        printf("请输入数字\n");
    }

	cel = (5*(fah-32)) / 9;

	printf("华氏%.2f° = 摄氏%.2f°\n", fah, cel);
	return 0;
}

第十二题(位运算)

【8】现有一个嵌入式设备终端传输过来的数据包是一个32位无符号的整型数,这个数据包里面各位含义如下:

00-07位:表示温度数据
08-15位:表示湿度数据
16-19位:表示4扇门的状态(门编号0-3)
20-23位:表示4盏灯的状态(灯编号0-3)
24-31位:预留备用

下面是最近一段时间接受的数据包:

0x12344520, 0xff004B1C, 0x00553C1E
请编写一个程序接收这3个数据包,并解析出对应的数据【温度,湿度,门0-3,灯0-3】(门和灯的状态0-关,1-开)。

#include <stdio.h>

#define TEMP_MASK  0x000000FF
#define HUMI_MASK  0x0000FF00

#define TEMPERATURE(a) ( (a&TEMP_MASK) >> 0 )
#define HUMIDITY(a)  ( (a&HUMI_MASK) >> 8 )

#define DOOR0_MASK  0x00010000
#define DOOR1_MASK  0x00020000
#define DOOR2_MASK  0x00040000
#define DOOR3_MASK  0x00080000

#define LIGHT0_MASK 0x00100000
#define LIGHT1_MASK 0x00200000
#define LIGHT2_MASK 0x00400000
#define LIGHT3_MASK 0x00800000

int main(void)
{
    unsigned int data;
    
    printf("请输入接收的数据:\n");
    while(1)
    {
        scanf("%x",&data);

        printf("温度:%d\n", TEMPERATURE(data));
        printf("湿度:%d\n", HUMIDITY(data));

        printf("门0: %s\t", (data & DOOR0_MASK) ? "开":"关");
        printf("门1: %s\t", (data & DOOR1_MASK) ? "开":"关");
        printf("门2: %s\t", (data & DOOR2_MASK) ? "开":"关");
        printf("门3: %s\n", (data & DOOR3_MASK) ? "开":"关");

        printf("灯0: %s\t", (data & LIGHT0_MASK) ? "亮":"灭");
        printf("灯1: %s\t", (data & LIGHT1_MASK) ? "亮":"灭");
        printf("灯2: %s\t", (data & LIGHT2_MASK) ? "亮":"灭");
        printf("灯3: %s\n", (data & LIGHT3_MASK) ? "亮":"灭");
    }
}

第十三题(循环控制)

【9】编写一个程序,输出26个小写字母。

解析: 本题考点两个:

字符的整数本质,可以对字符直接进行加减法运算 基本循环结构
参考代码:

#include <stdio.h>

int main(void)
{
	char alp;

	for(alp='a'; alp<='z'; alp++)
	{
		printf("%c", alp);
	}
	printf("\n");

	return 0;
}

第十四题(循环控制)

【10】编写一个程序,在用户输入某个大写字母后,产生一个金字塔图案。 例如输入字母E,则产生如下图案:

    A
   ABA
  ABCBA
 ABCDCBA
ABCDEDCBA

解析: 每一行都是由:“空格、升序字母、降序字母” 序列构成,只要分析出第ii行中有多少个空格、升序字母和降序字母即可。

参考代码:

#include <stdio.h>

int main(void)
{
    // 输入一个字母
	char ch;
	scanf("%c", &ch);
		
	if((ch<'A') || (ch>'Z'))
	{
		printf("只接受大写字母\n");
        exit(0);
	}

    // 总行数
	int line = ch - 'A' + 1;

	int i, j;
	for(i=1; i<=line; i++)
	{
        // 输出若干个空格
		for(j=0; j<line-i; j++)
		{
			printf(" ");
		}

        // 输出若干个升序字母
		for(j=0; j<i; j++)
		{
			printf("%c", 'A'+j);
		}

        // 输出若干个降序字母
		for(j-=2; j>=0; j--)
		{
			printf("%c", 'A'+j);
		}
		printf("\n");
	}
	return 0;
}

第十五题(循环控制、多路分支)

【11】编写一个程序,接收用户的输入信息,当用户输入完成后(Ctrl+D代表输入完成),自动统计用户输入的空格数、大小写字母数和其他字符数。

解析: 使用switch结构来判断用户的输入。

参考代码:

#include <stdio.h>
#include <ctype.h>

int main(void)
{
	int c;
	int spaces = 0;
	int lines = 0;
	int characters = 0;

	printf("请输入文本(井号#结束):\n");

	while((c=getchar()) != '#')
	{
		switch(c)
		{
			case ' ':
				spaces++;
				break;
			case '\n':
				lines++;
				break;
			default:
				characters++;
		}
	}

	printf("空格数=%d, 行数=%d, 其他字符=%d\n", 
		   spaces, lines, characters);
	return 0;
}

第十六题(分支控制、循环控制)

【12】编写一个程序,接受一个整数输入,然后显示所有小于或等于该数的素数。

提示: 素数指只能被1和自身整除的大于等于2的整数,例如2、3、5、7、11……

解答: 本题需要将判断素数的代码封装成一个函数,这可以用来让学生预习C语言中关于函数的语法。参考代码如下:

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

bool prime(int num)
{
	int i;
	for(i=2; i*i<(num+1); i++)
	{
		if(num%i == 0)
			return false;
	}
	return true;
}

int main(void)
{
	int n;
    scanf("%d", &n);

	for(int i=2; i<n+1; i++)
	{
		if(prime(i))
			printf("%d\t", i);
	}
	printf("\n");

	return 0;
}

第十七题(分支控制、循环控制)

【13】1976年的一天,《华盛顿邮报》于头版头条刊登了一条数学新闻,文中叙述了这样一则故事:70年代中期,美国个所名牌大学校园内,人们都像发疯一般,日以继夜废寝忘食地玩弄一种数学游戏,这个游戏十分简单,任意写出一个(非零)自然数N,并且按照以下规律进行变换:

如果是个奇数,则下一步变成 3N+1 如果是个偶数,则下一步变成 N/2
一时间学生、教师、研究员、教授,甚至是一等一的数学大拿、天才都纷纷加入这个看似简单的数学游戏,人们取了各种各样的数字N去检验这个算法,最终都无一例外地坠入自然数序列4-2-1,于是就自然萌生出这样的猜想:对于任意非零自然数N,经上述变换最终都将落入4-2-1序列的宿命。这就是著名的角谷猜想,或称冰雹猜想。

冰雹猜想最大的魅力,在于其不可预知性,数字N的转化过程变幻莫测,有些平缓温和,有些剧烈沉浮,但却都无一例外地会坠入4-2-1的谷底,这好比是一个数学黑洞,将所有的自然数牢牢吸住。有人把冰雹路径比喻一个参天大树,下面的树根是连理枝4-2-1,而上面的枝枝叶叶则构成了一个奥妙的通路,把一切(非零)自然数统统都覆盖了,这个小学生都看得懂的问题,迄今为止却没有任何数学手段和超级计算机可以证明。
冰雹猜想跟蝴蝶效应恰好相悖,蝴蝶效应蕴含的原理是:初始值的极小误差,会造成结果的巨大不同,而冰雹猜想恰好相反:无论刚开始存在多大的误差,最后都会自行修复,直到坠入谷底。

使用你所学习的C语言知识,编程实现冰雹猜想的算法,并测算各个自然数到达4-2-1谷底所经过的变换次数吧。

解答:
考察简单的C语言基本运算,主要是为了提起兴趣。参考代码如下:
#include <stdio.h>

int main(void)
{
	unsigned long long n;

	int num, max=0;

	for(n=2; n<ULLONG_MAX; n++)
	{
		int count = 0, a=n, b=n;
		while(a > 1)
		{
			if(a%2 == 0)
				a /= 2;
			else
				a = 3*a + 1;

			count++;
		}

		if(count > max)
		{
			max = count;
			num = b;

		}
		printf("数字[%llu]经过%5d次变换到达黑洞中心【变换次数最高纪录:%d】\n", n, count, max);
	}

	return 0;
}
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qt历险记

谢谢你的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值