首页 > 其他分享 >标准C语言5

标准C语言5

时间:2024-05-05 17:00:42浏览次数:30  
标签:fx int fy 补码 ++ C语言 标准 &&

进制转换:

​ 现在的CPU只能识别高低两种电流,只能对二进制数据进行计算。

​ 二进制数据虽然可以直接CPU计算识别,但不方便书写、记录,把二进制数据转换成八进制是为了方便记录在文档中。

​ 随着CPU的不断发展位数不断增加,由早期的8位逐渐发展成现在的64位,因此八进制就不能满足需求了,所以发展出了十六进制,但由于历史原因八进制还不能退出历史舞台。为了理解编程时的一些奇怪现象,我们需要掌握二进制数据、八进制数据、十六进制数据。

二进制数据:

​ 由0~1两个数字组成,逢2进1,由于计算机的运算器只能识别高低两种电流,所以它在运算时只能识别二进制数据。

十进制转换成二进制:(其他进制)

​ 假如把x转换成二进制,x/2记录下余数,然后对商继续除以2,重复这个过程,直到商为0结束,然后把记录的余数倒序汇总,就得到了x的二进制。

例如:117转换成二进制
	117 / 2 余数1
    58 / 2 余数0
    29 / 2 余数1
    14 / 2 余数0
    7 / 2 余数1
    3 / 2 余数1
    1 / 2 余数1
    0
    117的二进制就是:000000000000001110101
手算:79 88 121 46
练习1:实现一个函数,能够获取无符号int的十进制数据的二进制
void print_binary(unsigned int num,char result[],int len);
// result 输出型参数 存储数据的二进制结果

#include <stdio.h>                                                                               

void print_binary(unsigned int num, char result[], int len) {
    int cnt = len - 1;
    while(cnt >= 0) {   
        result[cnt--] = num % 2;
        num /= 2;
    }   
}

int main() {
    unsigned int num;
    printf("请输入一个整数:");
    scanf("%u",&num);
    char result[32];
    print_binary(num,result,32);
    for (int i = 0; i < 32; ++i) {   
        printf("%hhd",result[i]);
    }   
}

八进制数据:

​ 由0~7八个数字组成,逢8进1,早期使用它记录二进制数据,现在基本不再使用,文件的权限还依然使用8进制数据表示,所以还无法退出历史。0644

二进制数据转换八进制:

​ 从二进制的低位开始划分,每三位二进制对应一位八进制。

    000 0
    001 1
    010 2
    011 3
    100 4
    101 5
    110 6
    111 7
注意:

​ 在C代码中,以0开头的是八进制数据,以%o输出的也八进制数据。

​ 0644

十六进制数据:

​ 由09和af十六个字符组成,随着计算机的发展CPU的位数越来越多,输出的二进制也越来越长,随后科学家又发明出十六进制用于记用二进制数据。

二进制转换成十六进制:

​ 从二进制的低位开始划分,每四位二进制对应一位十六进制,超过9的用字母ABCDEF表示(不区分大小写)。

    1000 8
    1001 9
    1010 a
    1011 b
    1100 c
    1101 d
    1110 e 
    1111 f 
注意:

​ 在C代码中,以0x开头的是十六进制数据,以%x,%p输出的是十六进制数据。

​ %#x、%#o 以对应的进制显示数据

任意进制转换成十进制:

​ 每一个非0位带该公式求和 v*b^(n-1) 就得到了十进制。
​ v 值 645
​ b 进制 8
​ n 位数 5+4 * 8 +6 * 64

​ 课下算:334 6进制数 788 9进制数

关于进制转换可能遇到的笔试题:

1、十进制转换成二进制、八进制、十六进制,先统一转换成二进制,然后再把二进制转换成八进制、十六进制

2、在代码阅读题中遇到类似 0123 或者 0xabcd,数据的开头使用0 或者 0x,那么隐藏了这是个八进制、十六进制数据的含义,需要先转换后运算

3、输入一个整数和一个N,把该整数转换成N进制数 (2<=N<=35)(超过10的位使用字母表示)
#include <stdio.h>                                                                               
int main() {
    int num = 0, N = 0;
    scanf("%d %d", &num, &N);
    char result[32] = {} ,cnt = 0;
    while(num) {
        result[cnt++] = num % N;
        num /= N;
    }
    for (int i = cnt - 1; i >= 0; --i) {
        if (result[i] < 10) {
            printf("%hhd", result[i]);
        } else {
            printf("%c",'A' + result[i] - 10);
        }
    }
}

原码、反码、补码:

原码:

​ 正数二进制就是它的原码。

​ 负数符号位为1,数值部分取绝对值的二进制就是它原码。

反码:

​ 正数的原码就是它的反码

​ 负数的反码是他的原码除符号位外,按位取反。

补码:

​ 正数的原码就是补码

​ 负数的反码+1是补码。

​ 十进制的数据是以补码形式存储在计算机中的,因为计算机的CPU中只有加法器,也就是只能运算加法,其它运算都是使用加法模拟的。

​ 为了能计算出a-b也就是a + -b 所以需要使用特殊格式存储负数。

-127

1111 1111 原码

1000 0000 反码

1000 0001 补码 0x81

// 以8位计算机为前提

24 - 15

1000 1111 15原

1111 0000 15反

1111 0001 15补码

0001 1000 24

0000 1001 9补码

注意:同一个数据,以不同类型显示时,可能结果不一样,所以要统一类型去讨论
%hhd 0x81	-127
%d   0x81    129
-1234
-5678

补码转换成十进制整数:

补码的两种解析方式:
无符号解析:

​ 由于无符号数据全部是正数,所以补码就是原码,直接转换成十进制即可。

有符号解析:

​ 根据补码的最高位判断它是正数的补码还是负数的补码。

​ 最高位是1:它必然是负数的补码。

​ 1、补码-1得到反码

​ 2、反码符号位不变,按位求反得到原码

​ 3、原码转换成十进制数据。

​ 最高位是0:它必然是正数的补码,直接转换成十进制即可。

int num = 11111111 11111111 11111011 00101110;
1、由于最高位是1,它必须是负数的补码
2、补码-1 得到反码
    11111111 11111111 11111011 00101101
3、反码 按位求反 得到 原码
    10000000 00000000 00000100 11010010
    1024+128+64+16+2 
    -1234
注意:

​ 当遇到补码转换成十进制数据的笔试题时,必须有是否是有符号信息。

// 假如以下变量的补码是10110011,代码会输出什么,补码的符号信息已经包含在代码中了
char num;
printf("%hhd",num);
10110011
10110010
11001101
64+8+4+1   
-77

// 把以下补码转换成十进制数据,条件不够充分
11001100
注意:

​ 一个整型变量的取值范围是环型状的,当它是最大值时再加1就会变成最小值,当它是最小值时减1就是变成最大值。

以char类型数据为例:
-128 
10000000 补码
01111111 -1后的补码,转换成十进制的结果是127
    
127
01111111 补码
10000000 加1后的补码,转换成十进制的结果是-128

char特殊的补码:
10000000 最小值(最高位是1,其余全是0)
01111111 最大值(最高位是0,其余全是1)
11111111 -1(所有二进制位都是1)

    //	简述下列代码的执行过程
char ch = 7, n = 0;
while(ch) {
    ch -= 3;
    n++;
}
135	 %3	 45  
-128      1 
125 % 3   41
2 
130	%3    43
-127       1
126 %3     42  0
    	   173  但是char范围是-128-127 结果应该-83

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

for (char i = 0; i < 128; ++i)	死循环
for (uint8_t i = 10; i >= 0; --i) 死循环

位运算符:

​ 位运算符是针对数据的补码进行运算。

A & B 按位与运算,它是针对数据的补码进行按位与运算
    0 & 0 结果是0
    0 & 1 结果是0
    1 & 0 结果是0
    1 & 1 结果是1
    1001 1101	0x9d
    0011 1110   0x3e
    0001 1100   0x1c

A | B 按位与运算
    0 | 0 结果是0
    0 | 1 结果是1
    1 | 0 结果是1
    1 | 1 结果是1

A ^ B 按位异或运算	相同为假、相异为真
    0 ^ 0 结果是0 
    0 ^ 1 结果是1 
    1 ^ 0 结果是1 
    1 ^ 1 结果是0

~A 按位求反,是单目运算符
    ~0 结果是1 
    ~1 结果是0

x << n 把x的补码前n位丢掉,末尾补上n个0,按位左移。相当于乘2
    10101100 << 3 01100000
    01100000
    0000 0001 << 1
    0000 1000
    
x >> n 把x的补码后n位丢掉,前面n位,如果x是正数则补0,如果是负数则补1。
    char num = -3;
    printf("%hhd\n",num >> 2+1);
    1000 0011
    1111 1100
    1111 1101
    1111 1111
实现一个函数,显示一个整数的补码(该整数可能是负数也可能是正数)
#include <stdio.h>
void show_bit(int num) {
    char bits[32] = {}; 
    for (int i = 0; i < 32; ++i) {   
        bits[i] = num >> i & 1;
    }   
    for (int i = 31; i >= 0; --i) {   
        printf("%hhd", bits[i]);
    }   
}
int main() {
    show_bit(88);                                                      
}

输入一个整数,把它的4~7位置为1100,其它位不变

​ 00000000 00000000 00000000 11110000 0xf0

​ 11101101 11110111 11111111 10101000 num

​ 11111111 11111111 11111111 00001111 & ~0xf0

​ 11101101 11110111 11111111 00001000 |

​ 00000000 00000000 00000000 11000000 0xc0

int num;
num & ~0xf0 | 0xc0
num & ~(0xf<<4) | 0xc0  	先与再或

标准C语言项目:2048游戏

1、需要4*4的整数二维数组

2、需要在数组的随机空位置产生2|4

3、显示界面

4、获取方向键

5、把数组中的数字向方向键的方向移动(前方数字相同,就要合并,并统计分数)

6、如果数组发生了移动或合并,再在随机空位置产生一个2|4

7、检查游戏是否失败(没有空位置或者不能再合并),如果没有结束重复步骤3往下

#include <stdio.h>
#include <stdbool.h>
int arr[4][4] = {};

//  随机位置产生2|4
void rand_num(void);

//  显示界面
void show_view(void);

//  方向处理
void up_move(void);
void down_move(void);
void left_move(void);
void right_move(void);

//  检查是否失败
bool is_over(void);

int main(int argc,const char* argv[])
{
    for(;;)
    {
        rand_num();
        show_view();
        switch(getch())
        {
            case 183:   up_move();      break;
            case 184:   down_move();    break;
            case 185:   right_move();   break;
            case 186:   left_move();    break;
        }                                                                                                                                                                 
        if(is_over())
        {
            printf("游戏结束\n");
            return 0;
        }
    }
}
~        
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <getch.h>
#include <string.h>
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1};
int d[4][4];
bool ok = false;
void print() {
	system("clear");
	for (int i = 0; i < 9; ++i) {
		if (i % 2 == 0) {
			puts("-----------------------------");
		} else {
			for (int j = 0; j < 4; ++j) if (d[i / 2][j] != 0) {
				printf("|%6d", d[i / 2][j]);
			} else {
				printf("|      ");
			}
			printf("|\n");
		}
	}
}
bool check() {
	int cnt = 0;
	ok = false;
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 4; ++j) {
			cnt += d[i][j] == 0;
			for (int dir = 0; dir < 4; ++dir) {
				int fx = i + dx[dir], fy = j + dy[dir];
				if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && d[fx][fy] == d[i][j] && d[i][j]) {
					ok = true;
					return true;
				}
			}
		}
	}
	return cnt != 0;
}
void get() {
	if (ok) {
		return ;
	}
	int w = rand() % 2;
	w = 1 << w + 1;
	int x = rand() % 4, y = rand() % 4;
	while (d[x][y] != 0) {
		x = rand() % 4, y = rand() % 4;
	}
	d[x][y] = w;
}
int move() {
	int dir = getch() - 183, score = 0;
	int cpd[4][4], cp[4][4];
	memcpy(cp, d, sizeof d);
	if (dir == 0) {
		for (int j = 0; j < 4; ++j) {
			for (int k = 0; k < 4; ++k) {
				for (int i = 1; i < 4; ++i) if (d[i - 1][j] == 0 && d[i][j]) {
					d[i - 1][j] ^= d[i][j] ^= d[i - 1][j] ^= d[i][j];
				}
			}
		}
		memcpy(cpd, d, sizeof d);
		for (int j = 0; j < 4; ++j) {
			for (int i = 0; i < 4; ++i) {
				int fx = dx[dir] + i, fy = dy[dir] + j;
				if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
					d[fx][fy] += d[i][j];
					d[i][j] = 0;
					score += d[fx][fy];
				}

			}
		}
		for (int j = 0; j < 4; ++j) {
			for (int k = 0; k < 4; ++k) {
				for (int i = 1; i < 4; ++i) if (d[i - 1][j] == 0 && d[i][j]) {
					d[i - 1][j] ^= d[i][j] ^= d[i - 1][j] ^= d[i][j];
				}
			}
		}
	} else if (dir == 1) {
		for (int j = 3; j >= 0; --j) {
			for (int k = 0; k < 4; ++k) {
				for (int i = 2; i >= 0; --i) if (d[i + 1][j] == 0 && d[i][j]) {
					d[i + 1][j] ^= d[i][j] ^= d[i + 1][j] ^= d[i][j];
				}
			}
		}
		memcpy(cpd, d, sizeof d);
		for (int j = 3; j >= 0; --j) {
			for (int i = 3; i >= 0; --i) {
				int fx = dx[dir] + i, fy = dy[dir] + j;
				if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
					d[fx][fy] += d[i][j];
					d[i][j] = 0;
					score += d[fx][fy];
				}
			}
		}
		for (int j = 3; j >= 0; --j) {
			for (int k = 0; k < 4; ++k) {
				for (int i = 2; i >= 0; --i) if (d[i + 1][j] == 0 && d[i][j]) {
					d[i + 1][j] ^= d[i][j] ^= d[i + 1][j] ^= d[i][j];
				}
			}
		}
	} else if (dir == 2) {
		for (int i = 3; i >= 0; --i) {
			for (int k = 0; k < 4; ++k) {
				for (int j = 2; j >= 0; --j) if (d[i][j + 1] == 0 && d[i][j]) {
					d[i][j + 1] ^= d[i][j] ^= d[i][j + 1] ^= d[i][j];	
				}
			}
		}
		memcpy(cpd, d, sizeof d);
		for (int i = 3; i >= 0; --i) {
			for (int j = 3; j >= 0; --j) {
				int fx = dx[dir] + i, fy = dy[dir] + j;
				if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
					d[fx][fy] += d[i][j];
					d[i][j] = 0;
					score += d[fx][fy];
				}
			}
		}
		for (int i = 3; i >= 0; --i) {
			for (int k = 0; k < 4; ++k) {
				for (int j = 2; j >= 0; --j) if (d[i][j + 1] == 0 && d[i][j]) {
					d[i][j + 1] ^= d[i][j] ^= d[i][j + 1] ^= d[i][j];
				}
			}
		}
	} else if (dir == 3) {
		for (int i = 0; i < 4; ++i) {
			for (int k = 0; k < 4; ++k) {
				for (int j = 1; j < 4; ++j) if (d[i][j - 1] == 0 && d[i][j]) {
					d[i][j - 1] ^= d[i][j] ^= d[i][j - 1] ^= d[i][j];
				}
			}
		}
		memcpy(cpd, d, sizeof d);
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				int fx = dx[dir] + i, fy = dy[dir] + j;
				if (fx >= 0 && fy >= 0 && fx < 4 && fy < 4 && cpd[fx][fy] == cpd[i][j] && cpd[fx][fy]) {
					d[fx][fy] += d[i][j];
					d[i][j] = 0;
					score += d[fx][fy];
				}
			}
		}
		for (int i = 0; i < 4; ++i) {
			for (int k = 0; k < 4; ++k) {
				for (int j = 1; j < 4; ++j) if (d[i][j - 1] == 0 && d[i][j]) {
					d[i][j - 1] ^= d[i][j] ^= d[i][j - 1] ^= d[i][j];
				}
			}
		}
	}
	ok = true;
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 4; ++j) if (cp[i][j] != d[i][j]) {
			ok = false;
		}
	}
	return score;
}
int main() {
	srand(time(0));
	get(), print();
	int score = 0, idx = 0;
	while (check()) {
		idx += 1, score += move();
		get(), print();
	}
	printf("游戏已经结束,您的得分是%d, 共用了%d步\n", score, idx);
}

标签:fx,int,fy,补码,++,C语言,标准,&&
From: https://www.cnblogs.com/sleeeeeping/p/18173634

相关文章

  • 标准C语言4
    一、函数什么是函数:function​函数就是一段具有某一项功能的代码集合,它是C语言中管理代码的最小单位,把具有某项功能的若干行代码封装在函数中方便管理代码且方便重复调用。函数的分类:标准库函数:​ C语言标准委员会为C语言以函数形式提供了一些基础功能,这些函数被封装在li......
  • 标准C语言3
    一、数组什么是数组:​ 数组就是变量的组合,是一种批量定义变量的方式如何定义数组:类型名数组名[数量]; intarr[8];// 相当于定义了8个int类型的变量 inta1,a2,a3,...;访问数组中的变量:数组名[下标]; 下标从0开始,范围0~数量-1遍历数组:与for循环配合,使用循环变量作......
  • 对C语言符号的一些冷门知识运用的剖析和总结
    符号目录符号注释奇怪的注释C风格的注释无法嵌套一些特殊的注释注释的规则建议反斜杠'\'反斜杠有续行的作用,但要注意续行后不能添加空格回车也能起到换行的作用,那续行符的意义在哪?反斜杠的转义功能单引号和双引号字面值,字符串,字符,字符变量的大小为什么sizeof('1')的大小是4?c......
  • 标准C语言2
    二、常量(了解)​ 常量就是程序运行过程中不能改变的量,C语言中常量有:字面值常量、宏常量、枚举常量。字面值常量100 int100l long100ll longlong100u unsignedint100lu unsignedlong100llu unsignedlonglong定义一个宏常量表示100年总共有多少秒,不考虑闰平年 #defin......
  • C语言 子进程段错误后变成僵尸进程
    空指针获取首元素时出现段错误,子进程异常退出,父进程没有处理。#include<stdio.h>#include<unistd.h>intmain(){pid_tpid;pid=fork();if(pid>0){printf("fatherprocessisPID:%d\n",getpid());while(1){......
  • 标准C语言1
    一、C语言介绍​ 丹尼斯.里奇和肯.汤普逊在1971~1973年美国贝尔实验室,在开发UNIX操作系统时,在BCPL语言的基础上(newB语言),发明第一款高级编程语言,取BCPL第二个字母作为名字,所以叫C语言​ BCPL->newB->C->UNIX->Minix->Linux​ 它是为了开发操作系统而研发的一款编程语言,它特......
  • C语言 父子进程不能共享全局变量
    父子进程不能共享全局变量。父子进程中的任何一方修改了全局变量,只是修改了副本,只对自己可见,对另一方不可见。C语言中即使加了static也不行。#include<stdio.h>#include<unistd.h>//初始值是0intflag;intmain(){pid_tpid;//父进程和子进程执行相同代码即......
  • Go-标准库秘籍(全)
    Go标准库秘籍(全)原文:zh.annas-archive.org/md5/F3FFC94069815F41B53B3D7D6E774406译者:飞龙协议:CCBY-NC-SA4.0前言感谢您给予本书机会!本书是一本指南,带您了解Go标准库的可能性,其中包含了许多开箱即用的功能和解决方案。请注意,本书涵盖的解决方案主要是对标准库实现的简......
  • C语言转写成MIPS指令集汇编以及MIPS指令集汇编中函数调用时栈的变化
    一、问候语欢迎你来到我的博客!二、C语言代码分析  这段C语言代码共有3个函数组成。set_array函数传入1个int类型的变量num,并创建了1个int类型临时变量i和1个临时int类型数组array,里面含有10个单位,此函数主要目的是调用compare函数,并将num和i传入该函数中,得到其函数返回值......
  • 05. C语言数组
    数组用于将多个数据集中存储,方便管理,此文将集中存储任何类型数据的语句都称为数组,数组根据存储数据的类型和方式分为同型数组、结构体、共用体、枚举。 【同型数组】同型数组也直接称为数组,用于存储多个类型相同的数据,数组内的数据称为数组元素,数组元素占用连续的虚拟地址,每个......