引子问题:
中国象棋将帅问题:
在一把象棋的残局中,象棋双方的将帅不可以相见,即不可以在中间没有其他棋子的情况下在同一列出现。而将、帅各被限制在己方的3*3的格子中运动。相信大家都非常熟悉象棋的玩法吧,这里就不详细说明游戏规则了。
用A、B代表将和帅,请写出一个程序,输出A、B所有合法的位置。要求在代码中只能用一个变量。
分析与解法:
这个问题的解法并不复杂。
遍历A的所有位置
遍历B的所有位置
如果A的位置和B的位置在同一列
输出结果
否则 继续寻找
地图可以用0-8表示A或B可能的9个位置
0------1------2
3------4------5
6------7------8
关键问题在于只使用一个变量来表示A和B的位置。所以可以使用位运算来解决。一个无符号字符类型的长度是1字节,也就是8位,8位可以表示2^8=256个值,对于A、B的9个位置来说足够。可以用前4位来表示A的位置情况,后4位表示B的位置情况。而4位可以表示16个数也足够表示A、B的位置情况了。
通过位运算可以对A、B的位置进行读取和修改。
几种基本的位运算:
(1)& 按位与运算
(2)| 按位或运算 "与"和"或"就不用说了吧
(3)^ 按位异或运算 相同为假,不同为真
(4)~ 按位取反 一元运算符
(5)<< 按位左移 如 0000 0111 << 2 = 0001 1100,将此数左移两位相当于将此数扩大两倍。
(6)>> 按位右移 如 0001 1000 >> 2 = 0000 0110,将此数右移两位相当于将此数缩小两倍。
令LMASK为1111 0000,另任意一个1字节的字符型变量与其做与运算,结果右移四位,便可得到此变量的高四位的值。
Example,
0110 1011
&1111 0000
= 0110 0000 >> 4 = 0000 0110
同理,令RMASK为0000 1111,即可得到它低四位的值。
Ex.
0110 1011
& 0000 1111
= 0000 1011
设置1字节字符型变量,比如对高四位进行设置,先将变量与RMASK相与,将要修改的变量左移四位后于前一结果进行“异或”或“或运算”。
Ex.将0110 1011高四位设置为1001.
0110 1011
& 0000 1111
= 0000 1011 0000 1001 << 4 = 1001 0000
^ 1001 0000
= 1001 1011
同样的方法设置低四位的值。
代码:
这是个关于如何利用位运算解决问题的一个简单的运用,可以看到位运算合理地利用一个变量解决象棋将帅问题。算法本身很简单,重点是位运算的应用。
<BOP>上还有两个更简洁的算法:
第一个:
可以把变量i想象成一个两位九进制的变量,而i在计算机中存储的值是i的十进制表示。则i/9的计算机处理结果,即结果直接去掉小数点后部分的结果即是此九进制数的第二位,而i%9即是此九进制数的个位。本程序用此九进制数的第二位保存A的位置,个位表示B的位置。最大值为88,即为十进制的80.程序从十进制的80,即九进制的88遍历到十进制的0,即九进制的0.将符合条件的位置全部输出。
第二个:
算法与上面的如出一辙。
其中unsigned char a:4表示结构体中a的位域只有4位,高位用作它用。只能在结构体里使用,建议尽量少用,会破坏程序的移植性。
当结构体中的元素的取值范围很小时,可以将几个字段按位合成一个字段来表示,起到节省内存空间的作用。
Ex:
将上面例子中的变量i的大小输出,结果为1字节。说明i.a和i.b各占4位。
结构体是C语言中的一种常用的自定义数据结构。
看下面的例子:
按理说结构体变量i的大小应该是sizeof(int)+sizeof(char),即5,而输出显示的结果为8。再看一个例子:
应该是6对吧?结果还是8.这是为什么呢?
这是因为在32位的操作系统上,操作系统组织数据是以32位(4个字节)作为一个标准,因此各种变量的size都一般都是4的倍数。而且结构体数据都是按照定义时所使用的顺序存放的,因此在第一个例子中尽管b变量只会占有一个字节,但是a + b = 5 > 4,因此第一个4个字节存放a,第二个4个字节用于存放b,这样实际上就浪费了3个字节。在第二个例子中第二个4个字节用来存放b和c。
所以,在结构体中要注意结构体中的变量定义的顺序,不同的顺序可能会造成占用空间的不同。这在嵌入式程序设计等系统资源比较少的情况下尤为重要。比如如下两种结构体:
对于结构体m来说,x变量的大小为12,而y变量的大小为8.编译器是按程序员在结构体中声明变量的顺序处理的。不当的顺序会造成空间的浪费。读者可以想到发生这样情况的原因的。所以建议声明结构体时,按照不同变量的类型,按占用空间的大小升序或降序声明会取得较好的空间占用。
分享到:
相关推荐
在C语言中,结构体(struct)是一种复合数据类型,它允许我们将多个不同类型的变量组合成一个新的类型。这种新类型可以包含整型、浮点型、字符型等基本类型,甚至是其他结构体类型。结构体在处理复杂数据时非常有用...
本主题聚焦于C语言中的两个核心概念:字符串和结构体,它们是C语言中非常重要的数据类型。下面将详细阐述这两个概念以及它们在实际编程中的应用。 首先,字符串在C语言中是字符数组,通常以空字符'\0'作为结束标志...
C语言教学课件:c语言结构体.ppt
大一c语言课程之c语言结构体。详细讲解了结构体数据类型,结构体变量的应用结构体数据类型的定义及其变量的申明和引用。
通过这两个结构体的示例,我们可以看到C语言中结构体的强大之处,它不仅能够组织和存储不同类型的数据,还能够通过简单的代码实现复杂的数据处理和分析功能。这对于任何涉及到大量数据管理的项目来说,都是非常有用...
有时候不确定文本文档内有多少行数据,且数据还有表头,有行号,这些为字符串型,而内容为double型,怎样读入呢?放入结构体就好啦,真心不错
本讲义主要聚焦于C语言中的两个关键概念:指针和结构体,它们是C语言编程的核心部分,对于理解和编写高级C程序至关重要。 一、数据类型 在C语言中,数据类型是编程的基础,它定义了变量可以存储的数据种类。常见的...
SPT-C语言基础-结构体和结构体数组.pptx
《C语言程序设计》是一门基础且至关重要的编程课程,尤其对于计算机科学和技术领域的学习者而言。这门课程旨在教授如何使用C语言进行程序开发,理解计算机底层工作原理,并掌握编程思维。C语言以其简洁、高效和灵活...
内容概要:本文详细介绍了C语言中的结构体概念及其用法,涵盖结构体的定义、变量声明和初始化、成员访问、结构体数组以及结构体指针的相关知识点。具体示例展示结构体作为复合数据类型,能够封装多种数据类型的优点...
在C语言中,尽管结构体是用来组织数据的一种方式,它本身并不支持直接在其中定义或封装函数,就像C++中的类。然而,通过巧妙地利用函数指针,我们可以模拟类的面向对象特性,实现类似的功能。下面将详细介绍如何在...
C语言中的结构体是编程中一个非常重要的概念,它允许我们把不同类型的数据组合在一起作为一个单一的实体处理。这种数据组织方式对于创建复杂的数据结构和对象非常有用,甚至可以说是C++面向对象特性的基础,因为当...
在C语言中,结构体(struct)是一种非常重要的数据类型,它允许我们将不同类型的数据组合成一个整体,方便管理和操作。在清华大学的C语言程序设计课程中,结构体是核心知识点之一,主要涵盖了以下内容: 1. **概述*...
结构体是C语言中用于组合不同类型数据的工具,它可以封装多个变量,形成一个复合类型。使用结构体的主要步骤如下: 1. **定义结构体**:使用`struct`关键字定义一个新的类型,如`struct Person { char name[20]; ...
C语言中没有复数运算,只有实数运行,为此,用结构体定义复数,并实现其四则运算
结构体是C语言中的复合数据类型,可以定义一个新的数据类型,该类型包含不同类型的成员。例如,我们可以定义一个名为`Student`的结构体,包括学生的姓名、学号、年龄和各科成绩等字段。定义结构体的基本语法是: `...
C语言中的结构体是一种自定义的数据类型,它允许我们将多个不同类型的数据项组合成一个复合实体。例如,假设我们有一个C语言的结构体如下: ```c struct Person { char name[20]; int age; float height; }; ```...
在C语言中,结构体(struct)是一种复合数据类型,它允许我们将多个不同类型的变量组合成一个单一的实体。这使得我们能够创建更复杂的数据结构,以更好地模拟现实世界中的对象或概念。以下是对“C语言 结构体范例...
在C语言中,结构体(struct)是一种复合数据类型,它允许我们将多个不同类型的变量组合成一个单一的实体。这使得我们能够以更模块化和组织化的方式处理数据。本篇将详细介绍C语言中结构体的实现方法以及规范的编码...