C语言零基础--数据类型转换+运算符+控制流--系统学习3day

目录

一.数据类型转换

1. 隐式转换+强制转换+隐式规则

2.数据类型的本质

 3.可移植性整型 typedef

二 .符号位

1.算术运算符

2.关系运算符

 3.逻辑运算符

4.位运算符

5.特殊运算符

 6.条件运算符

 7.sizeof 运算符

 8.return运算符

 9.优先级与结合性+优美表格

三.控制流

1.二路分支 if-else

2. 多路分支 switch

3.while与 do…while循环

 4.for循环

5. break与continue   

 6.goto语句

四.练习3day

1.问题一

2.问题二(基本数据类型)

3.问题三

4.问题四

5.问题五

 6.问题六(基本程序路基、单目增减运算符)

7. 问题七(基本输入输出,运算)

8.问题八(位运算) 

9.问题九 (循环控制)

10.问题十(循环控制)

11.问题十一(循环控制、多路分支)

 12.问题十二(分支控制、循环控制)

13.问题十三(分支控制、循环控制)



一.数据类型转换

1. 隐式转换+强制转换+隐式规则

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

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

#include  <stdio.h>
int main(void){
    
    char  a = 'a';
    int   b = 12;
    float c = 3.14;
    float x = a + b - c; // 在该表达式中将发生隐式转换,所有操作数被提升为float
    printf("a + b - c = %f",x);
}


   

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

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

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

2.数据类型的本质

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

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

 3.可移植性整型 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 … …
 

二 .符号位

1.算术运算符

   注意:

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

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

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

2.关系运算符

在这里插入图片描述

     注意: 1. 关系运算符用于判断运算符两边的表达式是否满足给定的大小条件。

                 2.由关系运算符组成的表达式称为关系表达式,其值为布尔型。
                 3.判断是否相等是双等号==,而不是一个等号。

 3.逻辑运算符

在这里插入图片描述

        运算规则:

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

&&01||01
000001
101111

         注意:

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

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

4.位运算符

  在这里插入图片描述

         位运算符操作的对象是数据中的每一位

         运算规则:

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

5.特殊运算符

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

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;

 6.条件运算符

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

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

 7.sizeof 运算符

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

        eg: 

#include  <stdio.h>
//2023.2.2 gyp
int main(void){

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

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

}

 

 8.return运算符

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

int main()
{
    return 0;
}

 9.优先级与结合性+优美表格

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

 

三.控制流

1.二路分支 if-else

逻辑:程序中某段代码需要在满足某个条件时才能运行
形式:if 语句:表达一种 如果-则 的条件执行关系
           if-else 语句:表达一种 如果-否则 的互斥分支关系

        eg: 

#include  <stdio.h>
//2023.2.2 gyp
int main(void){
int a;
printf("请输入一个正整数:");
scanf("%d",&a);

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


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

return 0;
}//of main

  

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

2. 多路分支 switch

        定义:根据不同的条件执行不同的代码片段

         eg:


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

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

        要点分析

1.switch(n) 语句中的 n 必须是一个整型表达式,即 switch 判断的数据必须是整型

2.case语句只能带整型常量,包括普通整型或字符,不包括 const 型数据。

3.break 语句的作用是跳出整个 swtich 结构,没有 break程序会略过case往下执行 default 语句不是必须的,一般放在最后面(因此不需要 break)

3.while与 do…while循环

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

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

              while循环:入口判断

// 循环输出一系列整数,直到100为止

int a;
scanf("%d", &a);
while(a <= 100){

    printf("%d\n", a);
    a++;
}

               do-while循环:出口判断

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

do{
    printf("%d\n", a);
    a++;
}while(a <= 100);

                注意:

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

 4.for循环

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

int a;
for(a=1; a<=100; a++){

    printf("%d\n", a);
}

         语法点:

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

5. 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);       
}

 6.goto语句

        逻辑:无条件跳转

int main(){

    printf("%d\n", __LINE__); // 打印第3行 
    
    // 无条件跳转到label处 
    goto label;

    printf("%d\n", __LINE__); // 打印第7行,此处被略过

label:  
    printf("%d\n", __LINE__); // 打印第9行

}

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

四.练习3day

1.问题一

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

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

         参考答案:


#include <stdio.h>
int main(){

    unsigned int data=0x12ff0045;//0001 0010 1111 1111 0000 0000 0100 0101
    unsigned int num1=0x3<<14;//0110 0000 0000 0000

    data=data|num1;//或运算data的第14、15位置1

    unsigned int num2=0x3<<22;//1100 0000 0000 0000 0000 0000
    data=data^num2;//异或 22、23位置零

    printf("%x",data);
}

2.问题二(基本数据类型)

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

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

        参考答案:

#include <stdio.h>
int main(){

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

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

}

3.问题三

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

( 每个水分子的质量是3.02*10 ^(-23)千克)

        参考答案: 

#include <stdio.h>
#define WaterMolecule 3.02e-23
int main(){
    double MolecularNumber,WaterCapacity;
    printf("请输入水的容量(升):\n");
    while(1){
        // 输入数字
	    if(scanf("%lf", &WaterCapacity) == 1)
            break;

        // 输入非数字,清空缓冲区
        while(getchar()!='\n');
        printf("请输入数字:\n");
    }//of while
    MolecularNumber=WaterCapacity/WaterMolecule;
    printf("你拥有%e个水分子!",MolecularNumber);
}

4.问题四

【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 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.问题六(基本程序路基、单目增减运算符)

【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("华氏%.2fF° = 摄氏%.2fC°\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-开)。

        参考答案: 

C语言中define的用法_in_nocence的博客-CSDN博客_define函数的用法

#include <stdio.h>

#define TEMP_MASK  0x000000FF
#define HUMI_MASK  0x0000FF00

#define temperature(a) ( (a&TEMP_MASK) >> 0 )//define定义函数
#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(){

    char alphabet;
    for(alphabet='a';alphabet<'z';alphabet++){

        printf("%c ",alphabet);
    }
    
    printf("\n");
	return 0;

}

10.问题十(循环控制)

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

    A
   ABA
  ABCBA
 ABCDCBA
ABCDEDCBA

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

        参考代码:

#include <stdio.h>
#include <stdlib.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代表输入完成),自动统计用户输入的空格数、大小写字母数和其他字符数。

参考代码:

#include<stdio.h>
int main()
{
	char cc;
    
	int a=0,b=0,c=0,d=0,e=0;

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

	while((cc=getchar()) != '#')
	{
		if(cc==32)
		{
			a++;
			continue;
		}
		if(cc>='0'&&cc<='9')
		{
			b++;
			continue;
		}
		if(cc>='A'&&cc<='Z')
		{
			c++;
			continue;
		}
		if(cc>='a'&&cc<='z')
		{
			d++;
			continue;
		}
			e++;
	}
	printf("空格数为:%d\n",a);
	printf("数字个数为:%d\n",b);
	printf("大写字母数为:%d\n",c);
	printf("小写的字母数为:%d\n",d);
	printf("其他字符数:%d\n",e);
}

 12.问题十二(分支控制、循环控制)

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

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

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

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

bool prime(int num){//函数prime
	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谷底所经过的变换次数吧。

#include <stdio.h>

int main(void)
{
	unsigned long long n;

	int num, max=0;

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

			count++;
		}//of while

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

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

	return 0;
}//of main

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

西柚小萌新

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值