第4章第1章基础知识1基础简介.docx
第4章第1章基础知识1.1基础简介蓝桥比赛中,前几题往往会考查学生的基础知识,基础知识包含的内容很多,这里 选择几个知识点介绍。一、计算机中数据的表示计算机中数据分为数值型数据和非数值型数据。计算机中的数字、字母、符号等信息都必须转换成二进制数据保存在计算机中。这 样才能被计算机识别。能够进行算术运算得到明确数值概念的信息称为计算机数值数据,其余如字符、文 字、图像、声音等均为非数值数据。1 .数值类型数据的表示计算机中常用的进制包括十进制、八进制、十六进制和二进制。十进制以正常数字1-9开头,八进制以数字0开头,十六进制以0x(或0X)开头, 二进制不能在C语言中直接书写,部分编译器支持以0b或0B开头的二进制数据表示。 例如:int a=12, b=012, c=0xl2;printf (%d %d %d,a, b, c);输出结果:12 10 18上述输出结果为十进制输出,数据要想以八进制或者十六进制的形式输出,需要改 变输出控制符,如下所示:printf (,z%d %o %x,a, b, c);输出结果:12 12 12那如何表示二进制数据呢?常用的方法就是采用字符数组的方式,下面例子实现了 如何将一个十进制数转换成二进制数并存储在字符数组中:while (num0) 辗转取余arr n+=num % 2+'O'num/=2;).非数值类型数据非数值类型数据也是以二进制数据形式保存在计算机中。最简单的就是字符数据, 其采用的编码是ASCH编码。ASCII码也是以整数形式存储在计算机中的,这个整数为 编码,常用的编码和字符对应如下:F号编码字符备注10NUL (NULL)多用于字符串结束标志213CR回车键3480其它字符广9的编码是依次是4957将一段字符转换成整数存放到一个变量中,常用的方法是: int chnum(char str)465A大写字母B'Z的编码依次是6690597a小写字母bz的编码依次是98122int i, n, num=O;for(i=0;stri!=' 0' ;i+)if (stri>=, O' &&stri<=,9')num=num*10+stri'O'return num;)另外,汉字的表示是采用国家标准的汉字字符集GB2312-80,对收录字符进行分区 管理:字库分成94个区,每个区有94个汉字(按位编排),每一个汉字在字库中有确 定的区和位编号,即所谓的两个字节表示的区位码,区位码第一个字节表示区号,第二 个字节表示位号,由区位码即可获取汉字在字库中的地址。GB2312内码范围:A1A1-FEFE, 其中汉字的编码范围是B0A1-F7FE,第一字节0xB0-0xF7,对应区号16-87;第二个字 节OxAl-OxFE,对应位号01-94。例:“啊”是GB2312中的第一个汉字,区位码是1601。 下面代码实现了汉字十六进制和十进制区位码的计算:char a5;strcpy (a,“啊);printf Cz%XH%XHn,z, (unsigned char)aO, (unsigned char)al);int b=(unsigned char)a0*256+(unsigned char)a1;printf(%d,b);输出结果:B0HA1H45217每个汉字在字库中以点阵字模形式存储,一般为16X16点阵形式。每个点用一个 二进制位表示,存1的点,可以在屏幕上显示一个亮点,存0的点则不显示,存字的 16*16点阵信息在显示器上显示,即可出现对应汉字。二、进制转换不同进制的转换方式很多,基本上分为三类:十进制转其它进制,其它进制转十进 制,其它进制之间的相互转换。这里以十进制转其它进制为例,介绍一下进制转换的思 想。十进制整数转换为其它进制(以2进制为例,其它进制都类似),采用方法是: 除2取余,逆排序法。具体做法是:用2去除十进制整数,可以得到一个商和余数; 再用2去除商,又会得到一个商和余数,如此进行,直到商为零时为止,然后把所有余 数按逆序排列,也就是把先得到的余数作为二进制数的低位有效位,后得到的余数作为 二进制数的高位有效位,依次排列起来。这就是所谓“除2取余,逆序排列”。十进制转换成其它n进制的方法也是类似,可以称之为“除n取余,逆排序。具 体十进制转换成n进制的案例程序如下:char Hex16二' 0',' 1',' 2','A',' B',' C',' D',' E',' F'scanf (d,&num); 十进制数scanf (姒; 要转换的进制2、16doresulti+=num%jz;num二num/jz;while(num!=O);for(i-; i=0; i-)输出结果printf (%c, Hex result i);三、闰年计算地球绕太阳的运行周期为365天5小时48分46秒(合365. 24219天),即一回归 年(tropical year)。公历的平年只有365天,比回归年短约0. 2422天,每四年累积 约一天,把这一天加于2月末(即2月29日),使当年的时间长度变为366天(广12 月分别为31天、29天、31天、30天、31天、30天、31天、31天、30天、31天、30 天、31天),这一年就是闰年。按照每四年一个闰年计算,平均每年就要多算出0.0078 天,经过400年就会多出大约3天来,因此,每400年中要减少3个闰年。闰年的计算, 归结起来就是通常说的:四年一闰;百年不闰,四百年再闰。利用逻辑表达式表示:year%4=0 && year%100!=0year%400=0而对于每月天数的表示,由于也没有规律性,所以常用的表示方式是利用数组来表 示。如:int days13 = 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);四、文件操作在程序中,经常会遇到需要读取的数据量比较大的情况,如果用键盘输入,则输入 时间较长,这时就需要用到文件操作了。常用的文件操作分成以下四步:一是打开文件;二是判断文件打开是否成功;三是 读取(写入)文件;四是关闭文件。例如:FILE *fp;fp=fopen(D:,r);if(fp=NULL)(printf (,zfail to open! n/z);return 0;while(!feof (fp)chi+=fgetc(fp);fclose (fp);由于程序竞赛中,往往只需要从文件中读入程序数据即可,为了简化读入过程,读 取文件数据最常用的方法就是文件重定向技术。常用的方式是使用freopenO函数,其 声明为:FILE *freopen (const char ilename, const char *mode, FILE *stream);重定向技术的使用方法如下:将输入重定向到文件,后面的输入语句直接到文件中读取数据freopen(,r,stdin);将输出重定向到文件,后面的输出语句直接将数据输出到文件中freopen (,w,stdout);从文件中读取数据,存入变量中int a, b;scanf(%d %d, &a,&b);printf (%dn,a+b);关闭文件fclose (stdin);fclose (stdout);1.2购物单(2017试题A)【题目描述】小明刚刚找到工作,老板人很好,只是老板夫人很爱购物。老板忙的时候经常让小明帮 忙到商场代为购物。小明很厌烦,但又不好推辞。这不,XX大促销又来了!老板夫人开出了长长的购物单,都是有打折优惠的。小明也有个怪癖,不到万不得已,从不刷卡,直接现金搞定。现在小明很心烦,请你帮他计算一下,需要从取款机上取多少现金,才能搞定这次购物。取款机只能提供100元面额的纸币。小明想尽可能少取些现金,够用就行了。你的任务是计算出,小明最少需要取多少现金。以下是让人头疼的购物单,为了保护隐私,物品名称被隐藏了。180.9088折10. 2565折56. 149 折104. 659折100.3088折297. 15 半价26. 7565折130.62 半价240.2858折270. 628折115. 8788折247. 3495折73.219折101.00半价79.54半价278. 447 折199.26半价12. 979折166.3078折125. 5058折84. 989折113. 3568折166.57 半价42. 569 折81.9095 折131.788 折255. 8978折109. 179折146.6968折139.3365折141. 1678折154.748折59. 428 折85. 4468折293.7088折261.7965折11.3088折268.2758折128.2988折251.038 折208.3975折128.8875折62. 069 折225. 8775折12.8975折34. 2875折62.1658折129. 12半价218.37半价289. 698 折需要说明的是,88折指的是按标价的88%计算,而8折是按80%计算,余者类推。特别地,半价是按50%计算。请提交小明要从取款机上提取的金额,单位是元。答案是一个整数,类似4300的样子,结尾必然是00,不要填写任何多余的内容。特别提醒:不许携带计算器入场,也不能打开手机。【解析】该题的计算不算复杂,难点在于如何将数据读入到数组中。这里利用了 C+中的文件读 取技术:文件重定向。程序的具体步骤是:(1)对数据进行预处理由于原始数据有数字,也有中文,需要进行预处理。将数据复制到文本文件中,利用替 换工具将“半价”替换成“50”,然后将“折”替换成“”(空)。最后将文件保存为:。(2)读取数据到数组利用文件重定向技术:freopen,将数据输入改成到文件中读取。然后利用循环语句读 取文件数据。(3)计算数据并输出将读取的数据进行计算,这里注意的是:折扣如果小于10的话,需要进行乘10处理。 【参考程序】ttinclude <iostream> using namespace std; float price100; int discount100; int main () ( int i;freopen r,stdin); i=0;while(cin>>pricei>>discount i) i+; i=0;float sum=0; while(pricei!=0) if(discounti<10)sum+=pricei*discounti/10; elsesum+=pri cei*d iscounti/100; i+; ) cout<<sum<<endl;return 0; 1.3第几天(2018试题A)【问题描述】2000年的1月1日,是那一年的第1天。那么,2000年的5月4日,是那一年的第几天?注意:需要提交的是一个整数,不要填写任何多余内容。【参考答案】 125【解析】本题考查的闰年的判断。因为该题的数据量比较小,也可以直接计算: 31+29+31+30+4=125在实际编程过程中,如果涉及到较多的年份,即需要编写一个函数来判断闰年,是则二 月是29天,否则是28天。【参考代码】ttinclude <iostream> using namespace std; bool leap(int year)return (year%4=0 && year%100!=0 | | year%400=0);)int main ()(int feb;if(leap (2000)feb=29;elsefeb=28;cout«31+feb+31+30+4«endl;return 0;1.4明码(2018试题B)【问题描述】汉字的字形存在于字库中,即便在今天,16点阵的字库也仍然使用广泛。16点阵的字库把每个汉字看成是16x16个像素信息。并把这些信息记录在字节中。一个字节可以存储8位信息,用32个字节就可以存一个汉字的字形了。把每个字节转为2进制表示,1表示墨迹,0表示底色。每行2个字节,一共16行,布局是:1 第1字节,第2字节2 第3字节,第4字节3 .4 第31字节,第32字节这道题目是给你一段多个汉字组成的信息,每个汉字用32个字节表示,这里给出了字 节作为有符号整数的值。题目的要求隐藏在这些信息中。你的任务是复原这些汉字的字形,从中看出题目的要求, 并根据要求填写答案。这段信息是(一共10个汉字):4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 016 64 16 64 34 68 127 126 66 -124 67 4 66 4 66 -124 126 100 66 36 66 4 66 4 664 126 4 66 40 0 164 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 00 -128 64 -128 48 -128 17 8 1 -4 2 8 8 80 16 64 32 64 -32 64 32 -96 32 -96 33 16 34 8 36 14 40 44 0 3 0 1 0 0 4 -1 -2 4 0 4 16 7 -8 4 16 4 16 4 16 8 16 8 16 16 16 32 -96 646416 64 20 72 62 -4 73 32 5 16 1 0 63 -8 1 0 -1 -2 0 64 0 80 63 -8 8 64 4 64 164 0 -1280 16 63 -8 10101014 -1-2 2 0 2 0 7 -16 8 32 24 64 37 -128 2 -128 12 -128 113 -4 2 8 12 16 18 32 33 -641 0 14 0 112 01 0 1 0 1 0 9 32 9 16 17 12 17 4 33 16 65 16 1 32 1 64 0 -128 1 0 2 0 12 0 11200 0 0 0 7 -16 24 24 48 12 56 12 0 56 0 -32 0 -64 0 -128 00001 -128 3 -641 -128 0 0注意:需要提交的是一个整数,不要填写任何多余内容。【解析】汉字的字形码表示方法如下图所示。要得到字形信息,需要进行两步转换:一是将字模 信息转换成二进制的位代码;二是再将位代码转化成中文字模。中文字模位代码字模信息o Oo OOOOOOo OOOOOOOOOOOOOOxOoj 0x08 0x08, 0x11, Oxll, 0x32, 0x54, 0x10, Ox 10, 0x10, 0x11, 0x123 0x10, 0x103 0x10, 0x10,0x80 0x80 0x80Oxf e 0x020x040x200x200xa80xa40x260x220x200x20 OxaO0x40本题的解题万法有两种:(1)自己编写转换函数自己编写转换函数,需要弄明白一点:数据在计算机中是以补码形式存储的。正数的补 码跟原码相同,转换比较容易,直接转换即可。负数的补码相对复杂一点,是原码(除符号 位外)各位变反加1。例如:4直接转换:。-1的原码:,转换成补码(2)利用bitset模板类bitset模板类包含在C+的bitset头文件中,它是一种类似数组的结构,它的每一个 元素只能是0或1 ,每个元素仅用1 bit空间。该模板类可以实现整数到二进制数的自动转 换,一般用法如下:ttinclude <bitset>bitset<8> t (24); 把24转换成一个8位的二进制数t=30;把30转换成一个8位的二进制【参考程序1include <stdio. h>int main ()int n,num=0, offset=l;char ch16 16; 存储 16*16 字模 for(int k=0;k<32;k+) scanf(d”, &n);if (n<0) n=n+128;for (int i=1;i二8;i+)(int mod=n%2;n=n/2;chnum/28*offset-i=mod+48;num+;if(num%2=0) offset=l;else offset=2;for(int i=0;i<16;i+) for(int j=0;j<16;j+) printf("%c, chij);printf(n);)return 0;)【参考程序2】ttinclude <iostream>ttinclude <bitset>using namespace std;int main()(int n,num=0;for (int k=0;k<32;k+) scanf(%d,&n);if (n<0) n=n+128;bitset<8> b(n);cout<<b;num+;if (num%2=0) cout<<endl;return 0;