C语言结构体使用memcmp比较是否相等

标题C语言对结构体使用memcmp

在软件开发中,经常会遇到对字符串,内存比较的处理,我们通常很少会自己手写一遍比较函数,会调用C语言库函数进行处理,如strcmp,strncmp,memcmp等。
面试的时候,面试官经常会问过类似这样一个题目,这个题目考的内容就是基础的字节对齐问题的扩展,觉得有必要写一下。
问题描述:
有如下结构体:

struct test
{
	int member_a;
	char member_b;
};

问,在32位机器上,sizeof(struct test) = ?
那毫无疑问,答案是8;
很典型的字节对齐问题,再比如将上诉结构体的两个成员变量上下两个数据类型互换之后,结果是多少?就是char在前,int在后。这都是一个类型的问题。这里不展开讲字节对齐问题,有很多大牛讲的已经很详细了。那这个问题的扩展问题是什么呢。如下:
struct test testA,和stauct test testB两个结构体,能否用memcmp比较这两个结构体是否相等,memcmp(testA, testB, sizeof(struct test));?
先不说结果,先写段代码测试一下:

#include <stdio.h>
#include <stdlib.h>

typedef struct Test
{
    int     member_a;
    char    member_b;
}test;

int main(int argc, char **argv)
{
    test *test1 = (test*)malloc(sizeof(test));
    if (!test1)
    {
        printf("alloc fail\n");
        return -1;
    }
    test1->member_a = 0x12345678;
    test1->member_b = 0x01;
    
    test *test2 = (test*)malloc(sizeof(test));
    if (!test2)
    {
        printf("alloc fail\n");
        return -1;
    }
    test2->member_a = 0x12345678;
    test2->member_b = 0x01;
    
    int ret = memcmp(test1, test2, sizeof(test));
    printf("ret = %d\n", ret);
    
    free(test1);
    test1 = NULL;
    
    free(test2);
    test2 = NULL;
    return 0;
}

老样子,编译,执行:
在这里插入图片描述
ret=0;就说明这两个结构体相等,这样看起来没有什么问题。
那么我们回头来看,这个结构体是不是有效的字节数只有sizeof(int)+sizeof(char)=5,但是sizeof(struct test) = 8, 那么这相差的3个字节去哪了,我们知道malloc是不会对申请的内存进行初始化的,那么如果这三个字节之前的地址有别的内容的话,这里是不是就会出现问题?我们换一种思路,既然这个结构体有效部分只有5个字节,那么其他的三个字节是不是就可以任意处理了?操作一把,在申请到内存之后,把结构体初始化一下,稍作修改:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct Test
{
    int     member_a;
    char    member_b;
}test;

int main(int argc, char **argv)
{
    test *test1 = (test*)malloc(sizeof(test));
    if (!test1)
    {
        printf("alloc fail\n");
        return -1;
    }
    memset(test1, 0, sizeof(test)); //初始化全0
    test1->member_a = 0x12345678;
    test1->member_b = 0x01;
    
    test *test2 = (test*)malloc(sizeof(test));
    if (!test2)
    {
        printf("alloc fail\n");
        return -1;
    }
    memset(test2, 1, sizeof(test)); //初始化全1
    test2->member_a = 0x12345678;
    test2->member_b = 0x01;
    
    int ret = memcmp(test1, test2, sizeof(test));
    printf("ret = %d\n", ret);
    
    free(test1);
    test1 = NULL;
    
    free(test2);
    test2 = NULL;
    return 0;
}

编译、执行:
在这里插入图片描述
是不是就出问题了,但是这个结构体不影响使用,原有的成员变量还是可以正常操作的。只不过这里的memcmp就出问题了。
所以这个问题的答案就是,不能针对这个结构体进行memcmp比较是否相等,有风险。
那么问题又来了,如果我非要使用memcmp来比较呢,要怎么处理?
内心os:我看你是诚心想刁难我胖虎。
好吧,看下memcmp函数原型吧:
在这里插入图片描述
Man pages的关于memcmp的描述,针对开始的n个字节的内存进行比较,记中重点,要考的。上面我们是怎么传参数的, memcmp(test1, test2, sizeof(test)); 这里的第三个参数肯定是8啊,多了3个无关的字节啊。想个办法?当然不建议直接去搞他啊,那要换个结构体还得重新算一遍,万一算错了呢,万一不知道多少位的机器呢。还是保留这个sizeof吧。能不能对结构体操作一波?当然能。
不信你去百度搜一下结构体强制对齐,会出现一大把内容:
我选择其中一种方式,#pragma pack(1) //让编译器对这个结构体1字节对齐, #pragma pack() //取消强制对其。修改代码,如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#pragma pack(1) 
typedef struct Test
{
    int     member_a;
    char    member_b;
}test;
#pragma pack()

int main(int argc, char **argv)
{
    test *test1 = (test*)malloc(sizeof(test));
    if (!test1)
    {
        printf("alloc fail\n");
        return -1;
    }
    memset(test1, 0, sizeof(test)); //初始化全0
    test1->member_a = 0x12345678;
    test1->member_b = 0x01;
    
    test *test2 = (test*)malloc(sizeof(test));
    if (!test2)
    {
        printf("alloc fail\n");
        return -1;
    }
    memset(test2, 1, sizeof(test)); //初始化全1
    test2->member_a = 0x12345678;
    test2->member_b = 0x01;
    
    printf("sizeof(test) = %d\n", sizeof(test));
    
    int ret = memcmp(test1, test2, sizeof(test));
    printf("ret = %d\n", ret);
    
    free(test1);
    test1 = NULL;
    
    free(test2);
    test2 = NULL;
    return 0;
}

编译运行:
在这里插入图片描述
完成,强制对齐的方式还有__attribute__,这里不展开讲了,小伙伴们可以自己去学习一下,溜了溜了。如果面试官再问你这个题目,知道怎么回答了吧。
attribute比较强大,只是再别人的代码中看见过,自己至今也是没用过,等抽空学习一下再来说这个吧。

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第1章 C语言概述 1 1.5 参照本章例题,编写一个C程序,输出以下信息: 1 1.6 写一个程序,输入a,b,c三个值,输出其最大者。 1 第2章 程序的灵魂——算法 2 2.1 什么叫结构化的算法?为什么要提倡结构化的算法? 2 2.7 什么叫结构化程序设计?它的主要内容是什么? 2 第3章 数据类型、运算符与表达式 2 3.3请将下面各数用八进制和十六进制数表示: 2 3.4将以下三各整数分别赋给不同类型的变量,请画出赋值后数据在内存的存储形式。 2 3.5字符常量和字符串常量有什么区别? 3 3.6写出以下程序运行的结果: 3 3.7要将“China”译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。例如,字母“A”后面第4个字母是“E”,用“E”代替“A”。因此,“China”应译为“Glmre”。请编一程序,用赋初值的方法使c1,c2,c3,c4,c5这5个变量的值分别为’C’,’h’,’i’,’n’,’a’,经过运算,使c1,c2,c3,c4,c5的值分别变为’G’,’l’,’m’,’r’,’e’,并输出。 4 3.8例2.6能否改成如下: 4 3.9求下面算术表达式的值。 4 3.10写出程序运行的结果。 5 3.11写出下面赋值的结果。格写了数值的是要将它赋给其他类型的变量,将所有空格填上赋值后的数值。 5 3.12 出下面表达式运算后a的值,设原来a=12。设a和n都已定义为整型变量。 5 第4章 最简单的C程序设计——顺序程序设计 6 4.4 若a=3,b=4,c=5,x=1.2,y=2.4,z=-3.6,u=51247,n=128765,c1=’a’,c2=’b’,想得到以下的输出格式和结果,请写出程序(包括定义变量类型和设计输出)。 6 4.5请写出下面程序的输出结果: 7 4.6 用下面的scanf函数输入数据,使a=3,b=7,x=8.5,y=71.82,c1=’A’,c2=’a’。问在键盘上如何输入? 7 4.7下面的scanf函数输入数据,使a=10,b=20,c1=’A’,c2=’a’,x=1.5,y=-3.75,z=67.8,请问在键盘上如何输入数据? 8 4.8圆半径r=1.5,圆柱高h=3,求圆周长,圆面积,圆球表面积,圆球体积,圆柱体积。用scanf输入数据,输出计算结果,输出时要求有文字说明,取小数点后2位数字。请编程序。 8 4.9输入一个华氏温度,要求输出摄氏温度,公式为C=(5/9)(F-32) 9 输出要有文字说明,取2位小数。 9 第5章 选择结构程序设计 10 5.2语言如何表示“真”和“假”?系统如何判断一个量的“真”和“假”? 10 5.3写出下面各逻辑表达式的值。设a=3,b=4,c=5。 10 5.4有3个整数a,b,c,由键盘输入,输出其最大的数。 10 5.5有一函数: 11 5.6给出一百分制成绩,要求输出成绩等级’A’、’B’、’C’、’D’、’E’。90分以上为’A’,80~89分为’B’,70~79分为’C’,60~69分为’D’,60分以下为’E’。 12 5.7给定一个不多于5位的正整数,要求:①求它是几位数;②分别打印出每一位数字;③按逆序打印出各位数字。例如原数为321,应输出123。 13 5.8企业发放的奖金根据利润提成。利润I低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元(100000<I≤200000)时,其10万元按10%提成,高于10万元的部分,可提成7.5%;200000 <I≤400000时,其20万元仍按上述办法提成(下同),高于20万元的部分按5%提成;400000<I≤600000时,高于40万元的部分按3%提成;6000001000000时,超过100万的部分按1%提成。从键盘输入当月利润I,求应发放奖金总数。 14 5.9输入4个整数,要求按由小到大的顺序输出。 16 5.10有4个圆塔,圆心分别为(2,2),(-2,2),(2,-2),(-2,-2),圆半径为1。见图4.4。这4个塔的高度分别为10m。塔以外无建筑物。今输入任一点的坐标,求该点的建筑高度(塔外的高度为0)。 16 第6章 循环控制 17 6.1输入两个正整数m和n,求其最大公约数和最小公倍数。 17 6.2输入一行字符,分别统计出其英文字母,空格,数字和其它字符的个数。 18 6.3 18 6.4求∑n!(即求1+2!+…+20!)。 19 6.5求 19 6.6打印出所有的“水仙花数”。 20 6.7一个数如果恰好等于它的因子之和,这个数就称为“完数“。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000以内的所有“完数”,并按下面的格式输出其因子:6 Its factors are 1,2,3 20 6.8有一分数序列: 23 6.9一球从100米高度自由落下,每次落地后反跳回原高度的一半,再落下。求它在第10次落地时,共经过多少m?第10次反弹多高? 23 6.10猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上再想吃时,见只剩一个桃子了。求第一天共摘多少桃子。 24 6.11用迭代法求 24 6.12用牛顿迭代法求方程2x3-4x2+3x-6=0在1.5附近的根。 25 6.13用二分法求方程2x3-4x2+3x-6=0在(-10,10)之间的根。 26 6.14打印出以下图案: 27 6.15两个乒乓球队进行比赛,各出3人。甲队为A、B、C3人,乙队为X、Y、Z3人。已抽签决定比赛名单。有人向队员打听比赛名单。A说他不和X比,C说他不和X、Z比。请编程找出3对赛手的名单。 28 第7章 数组 28 7.1用筛法求100之内的素数。 28 7.2用选择法对10个整数排序(从小到大)。 30 7.3求一个3×3矩阵对角线元素之和。 31 7.4有一个已排好序的数组,今输入一个数,要求按原来排序的规律将它插入数组。 32 7.5将一个数组的值按逆序重新存放。例如原来顺序为:8,6,5,4,1。要求改为:1,4,5,6,8。 34 7.6打印出以下的杨辉三角形(要求打印出10行)。 35 7.7输出魔方阵。所谓魔方阵是指这样的方阵(方阵的阶数应为奇数),它的每一行、每一列和对角线之和均相等。 36 7.8找出一个二维数组的鞍点,即该位置上的元素在该行上最大,在该列上最小。也可能没有鞍点。 38 7.9有15个数按从小到大的顺序存放在一个数组。输入一个数,要求用折半查找法找出该数是数组第几个元素的值。如果该数不在数组,输出“不在表”。 39 7.10有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其英文大写字母,小写字母,数字,空格以及其它字符的个数。 41 7.11打印以下图案: 42 7.12有一行电文,已按下面规律译成密码: 43 7.13编一个程序,将两个字符串连接起来,不要用strcat函数。 45 7.14编一个程序,将两个字符串s1和s2进行比较。如果s1>s2,输出一个正数;s1=s2,输出0;s1<s2,输出一个负数。不要用strcmp函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相应字符的ASCII码的差值。例如,’A’与’C’相比,由于’A’<’C’,应输出负数,由于’A’与’C’的ASCII码的差值为2,因此,应输出”-2”。同理:’’And’’和”Aid”比较,根据第2个字符比较结果,’n’比’i’大5,因此应输出’5’。 45 7.15编写一个程序,将字符数组s2的全部字符拷贝到字符数组s1,不用strcpy函数。拷贝时,’\0’也要拷过去,’\0’后面的字符不拷贝。 46 第8章 函数 47 8.1写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果,两个整数由键盘输入。 47 8.2 47 8.3写一个判素数的函数,在主函数输入一个整数,输出是否素数的信息。 49 8.4写一函数,使给定的一个二维数组(3×3)转置,即行列互换。 49 8.5写一函数,使输入的一个字符串按反序存放,在主函数输入和输出字符串。 50 8.6写一函数,将两个字符串连接。 51 8.7写一函数,输入一个4位数字,要求输出这4个数字字符,但每两个数字之间有一个空格。如输入1990,应输出”1 9 9 0”。 52 8.8编写一函数,有实参传来一个字符串,统计此字符串字母,数字,空格和其它字符的个数,在主函数输入字符串以及输出上述的结果。 52 8.10写一函数,用“起泡法”对输入的10个字符按由小到大的顺序排列。 54 8.11用弦截法求根。 55 8.12输入10个学生5门课的成绩,分别用函数求:(1)每个学生的平均分;(2)每门课的平均分;(3)找出最高的分数所对应的学生和课程;(4)求出平均分方差; 57 8.13写几个函数:(1)输入10个职工的姓名和职工号;(2)按职工号由小到大排序,姓名顺序也随之调整;(3)要求输入一个职工号,用折半查找法找出该职工的姓名。 61 8.14写一函数,输入一个十六进制数,输出相应的十进制数。 64 8.15给出年,月,日,计算该日是该年的第几天。 65 第9章 预处理命令 66 9.1定义一个代参数的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参。输出已交换后的两个值。 66 9.2输入两个整数,求它们相除的余数。用带参的宏来实现,编程序。 67 9.3 67 9.4给年份year定义一个宏,以判断该年份是否为闰年。 68 9.5请分析以下一组宏所定义的输出格式: 68 9.6请设计输出实数的格式。实数用“6.2f”格式输出。 69 9.7分别用函数和带参的宏,从3个数找出最大数。 70 9.8试述“文件包含”和程序文件的连接(link)的概念,二者有何不同? 71 9.9用条件编译法实现以下功能: 71 第10章 指针 72 10.1输入3个整数,按由小到大的顺序输出。 72 10.2输入3个字符串,按由小到打的顺序输出。 73 10.3输入10个整数,将其最小的数与第一个数对换,把最大的一个数与最后一个对换。写3个函数:(1)输入10个数;(2)进行处理;(3)输出10个数。 74 10.4有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成前面m个数。 75 写一函数实现以上功能,在主函数输入n个整数,并输出调整后的n个数。 75 10.5有一字符串,包含n个字符。写一个函数,将此字符串从第m个字符开始的全部字符复制成为另一个字符串。 76 10.6输入一行文字,找出其大写字母,小写字母,空格,数字及其他字符各有多少。 77 10.7写一个函数,将一个3×3的矩阵转置。 77 9.8将一个5×5的矩阵最大的元素放在心,4个角分别放在4个最小的元素(按从左到右,从上到下的顺序,依次从小到大存放),写一个函数实现之,并用main函数调用。 78 10.9在主函数输入10个等长的字符串。用另一个函数对它们排序,然后在主函数输出这10个已排好序的字符串。 80 10.10用指针数组处理上一题目,字符串不等长。 81 10.11将n个数按输入输出顺序的逆序排列,用函数实现。 82 10.12有一个班4个学生,5门课。(1)求第一门课的平均分;(2)找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均成绩;(3)找出平均成绩在90分以上或全部课程成绩在85分以上的学生。分别编3个函数实现上3个要求。 83 10.13输入一个字符串,内有数字和非数字字符,如: 86 10.14写一函数,实现两个字符串的比较。即自己写一个strcmp函数,函数原型为: 88 10.15编写一个程序,打入月份号,输出该月的英文月名。例如,输入”3”,则输出”March”,要求用指针数组处理。 89 10.16用指向指针的指针的方法对5个字符串排序并输出。 89 10.17用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。n和正整数在主函数输入。最后在主函数输出。 90 第11章 结构体与共用体 91 11.1定义一个结构体变量(包括年,月,日)。计算该日在本年是第几天,注意闰年问题。 91 11.2写一个函数days,实现上面的计算。由主函数将年,月,日传递给days函数,计算后将日数传回主函数输出。 93 11.3编写一个函数print,打印一个学生的成绩数组,该数组有5个学生的数据记录,每个记录包括num,name,score[3],用主函数输入这些记录,用print函数输出这些记录。 95 11.4在上题的基础上,编写一个函数input,用来输入5个学生的数据记录。 97 11.5有10个学生,每个学生的数据包括学号,姓名,3门课的成绩,从键盘输入10个学生的数据,要求打印出3门课的总平均成绩,以及最高分的学生的数据(包括学号,姓名,3门课成绩,平均分数)。 97 11.6编写一个函数new,对n个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间。new(n)表示分配n个字节的内存空间。 100 11.7写一函数free,将上题new函数占用的空间释放free(p)表示将p(地址)指向的单元以后的内存段释放。 101 11.8已有a,b两个链表,每个链表的结点包括学号,成绩。要求把两个链表合并,按学号升序排列。 101 11.9有两个链表a和b,设结点包含学号,姓名。从a链表删去与b链表有相同学号的那些结点。 104 11.10建立一个链表,每个结点包括:学号,姓名,性别,年龄。输入一个年龄,如果链表的结点所包含的年龄等于此年龄,则将此结点删去。 106 第12章 位运算 109 12.1编写一个函数getbits,从一个16位的单元取出某几位()即该几位保留原值,其余位为0)。函数调用形式为: 109 12.2写一个函数,对一个16位的二进制数取出它的奇位数(即从左边起第1,3,5,…,15位)。 109 12.3编一程序,检查一下你所用的计算机系统的C编译在执行右移时是按照逻辑位移的原则,还是按照算术右移的原则。如果是逻辑右移,请编一函数实现算术右移;如果是算术右移,请编一函数实现逻辑右移。 110 12.4编一函数用来实现左右循环移位。函数名为move,调用方法为:move(value,n) 112 其value为要循环位移的数,n为位移的位数。如n0为右移。如n=4,表示要右移4位;n=-3,表示要左移3位。 112 第13章 文件 113 13.3从键盘输入一个字符串,将其的小写字母全部转换成大写字母,然后输出到一个磁盘文件”test”保存。输入的字符串以”!”结束。 113 13.4有两个磁盘文件“A”和“B”,各存放一行字母,要求把这两个文件的信息合并(按字母的顺序排列),输出到一个新文件“C”。 114 13.5有5个学生,每个学生有3门课的成绩,从键盘输入以上数据(包括学生号,姓名,三门课成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件stud。 115 13.7将上题已排序的学生成绩文件进行插入处理。插入一个学生的3门课成绩,程序先计算新插入学生的平均成绩,然后将它按平均成绩高低顺序插入,插入后建立一个新文件。 122 13.8将上题的结果仍存入原有的stu_sort文件而不另建立新文件。 123 13.9有一磁盘文件emploee,内存放职工的数据。每个职工的数据包括:职工姓名,职工号,性别,年龄,住址,工资,健康状况,文化程度。要求将职工名和工资的信息单独抽出来另建一个简明的职工工资文件。 125 13.10从上题的“职工工资文件”删去一个职工的数据,再存回原文件。 127
基于arm开发板的2048游戏的实现:实现功能及其原理如下: 2048是平面二维游戏,在4*4图片方格内,通过对滑动方向(上、下、左、右)的判断实 现对各个图片的移动、合并(在沿滑动方向上,两相邻元素值相等或者两相等元素值之间 的元素内容为空(即为0),即要进行合并)等操作。 首先:需要实现的是在屏幕上显示出相应界面,这涉及到对lcd屏幕的操作,arm开发版运行 的是linux系统,通过对设备文件(路径为/dev/fb0 的文件)进行操作,实现现屏幕显示功能。 因为是系统内的文件,采用系统IO函数实现,主要是open、read、write、lseek函数。同时 为了提高显示效率,还采用了mmap映射函数。 其次:该游戏需要判断出滑动的方向,来实现对相应图片的移动、合并操作,所以还需要对 触摸屏设备文件(路径名为/dev/input/event0 的设备文件)进行操作。要判断出滑动类型, 获取点下屏幕时的坐标点x1、y1以及离开屏幕时的坐标点x2、y2。根据两值只差可判断出 滑动方向(差值绝对值大的,滑动方向就是哪边) 实现对图画的移动、合并操作,这是本游戏设计的一大难点,本项目 采用如下方法实现该功能: 该游戏本质上是对二维数组的操作,该项目,定义了如下量 //该节点用来保存4*4二维数组每一个元素的信息 struct position { int x; int y; int data; char *names; }; struct position * pos[4][4] = {0}; char *name[12]; //指向要显示图片的路径名 结构体用来保存二维数组每一个元素的信息,x、y保存的是显示图片的位置信息, data保存的是图片对应的值(根据此值可以显示出相应的图片,如果值为8,则显示值 为8的图片),names是一个字符型指针,指向的是要显示图片的路径名信息(该信息保 存在char *name[12]的指针数组,该数组指针保存了路径名信息)。 据此,便可以显示出相应的图片,接下来便是操作 pos[4][4]是一个二维数组,当朝着一个方向滑动时,便需要根据pos->data 值进行 相关操作 ,研滑动方向上,判断第一个元素值是否为0(空白图片表示值为0),如果为0 则继续找,直到找到下一个不为0的元素,然后将该值赋值给开头元素,该元素置0, 如果开头元素不为0,那么就往后面寻找,直到找到一个不为0的元素,如果该元素与开头元素 值相等,则合并(开头元素值乘以2,然后该元素置0)。以上便是一轮判断,然后开头元素再 往后挪一个,按照同样的方法判断,进行相关操作。 然后,还需要有产生随机数的功能, 定义了两个值XX ,YY,用rand函数产生小于4的两个数,然后对二维数组pos进行遍历, 如果pos[i][j]->data == pos[XX][YY]->data 那么就可以在改位置产生随机数,否则,就重新产 生一次随机数,直到产生为止,产生不了则游戏结构 最后, 为了实现计分功能,通过计算,在像素坐标点为(50,20)(75,20)(100,20)(125,20)的位置显示出0到9的数字, 通过计分,可以将所得分数在该四个点显示出
实验1:顺序表基本操作 一、实验目的 1.学会定义线性表的顺序存储类型,实现C程序的基本结构,对线性表的一些基本操作和具体的函数定义。 2.掌握顺序表的基本操作,实现顺序表的插入、删除、查找以及求并集等运算。 3.掌握对多函数程序的输入、编辑、调试和运行过程。 二、实验要求 1.预习C语言结构体的定义与基本操作方法。 2.对顺序表的每个基本操作用单独的函数实现。 3.编写完整程序完成下面的实验内容并上机运行。 4.整理并上交实验报告。 三、实验内容: 1.编写程序实现顺序表的下列基本操作: (1)初始化顺序表La。 (2)将La置为空表。 (3)销毁La。 (4)在La插入一个新的元素。 (5)删除La的某一元素。 (6)在La查找某元素,若找到,则返回它在La第一次出现的位置,否则返回0。 (7)打印输出La的元素值。 2.编写程序完成下面的操作: (1)构造两个顺序线性表La和Lb,其元素都按值非递减顺序排列。 (2)实现归并La和Lb得到新的顺序表Lc,Lc的元素也按值非递减顺序排列。 (3)假设两个顺序线性表La和Lb分别表示两个集合A和B,利用 union_Sq操作实现A=A∪B。 四、思考与提高 假设两个顺序线性表La和Lb分别表示两个集合A和B,如何实现A=A ∩B ? 实验2:单链表基本操作 一、 实验目的 1. 学会定义单链表的结点类型,实现对单链表的一些基本操作和具体的函数定义,了解并掌握单链表的类定义以及成员函数的定义与调用。 2. 掌握单链表基本操作及两个有序表归并、单链表逆置等操作的实现。 二 、实验要求 1.预习C语言结构体的定义与基本操作方法。 2.对单链表的每个基本操作用单独的函数实现。 3.编写完整程序完成下面的实验内容并上机运行。 4.整理并上交实验报告。 三、实验内容 1.编写程序完成单链表的下列基本操作: (1)初始化单链表La。 (2)在La第i个元素之前插入一个新结点。 (3)删除La的第i个元素结点。 (4)在La查找某结点并返回其位置。 (5)打印输出La的结点元素值。 2 .构造两个带有表头结点的有序单链表La、Lb,编写程序实现将La、Lb合并成一个有序单链表Lc。 合并思想是:程序需要3个指针:pa、pb、pc,其pa,pb分别指向La表与Lb表当前待比较插入的结点,pc 指向Lc表当前最后一个结点。依次扫描La和Lb的元素,比较当前元素的值,将较小者链接到*pc之后,如此重复直到La或Lb结束为止,再将另一个链表余下的内容链接到pc所指的结点之后。 3.构造一个单链表L,其头结点指针为head,编写程序实现将L逆置。(即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点,如此等等。) 四、思考与提高 1.如果上面实验内容2合并的表内不允许有重复的数据该如何操作? 2.如何将一个带头结点的单链表La分解成两个同样结构的单链表Lb,Lc,使得Lb只含La表奇数结点,Lc含有La表的偶数结点? 实验3:循环队列基本操作 一 、实验目的 1.熟悉并能实现循环队列的定义和基本操作。 2.了解用队列解决实际应用问题。 二、实验要求 1.进行队列的基本操作时要注意队列“先进先出”的特性。 2.复习关于队列操作的基础知识。 3.编写完整程序完成下面的实验内容并上机运行。 4.整理并上交实验报告。 三、实验内容 1.任意输入队列长度和队列的元素值,构造一个顺序循环队列,对其进行清空、插入新元素、返回队头元素以及删除队头元素操作。 2.约瑟夫环的实现:设有n个人围坐在圆桌周围,现从某个位置 i 上的人开始报数,数到 m 的人就站出来。下一个人,即原来的第m+1个位置上的人,又从1开始报数,再是数到m的人站出来。依次重复下去,直到全部的人都站出来,按出列的先后又可得到一个新的序列。由于该问题是由古罗马著名的史学家Josephus提出的问题演变而来,所以通常称为Josephus 问题。 例如:当n=8,m=4,i=1时,得到的新序列为: 4,8,5,2,1,3,7,6 编写程序选择循环队列作为存储结构模拟整个过程,并依次输出出列的各人的编号。 实验4:矩阵的压缩存储及相关操作 (第11周星期三7、8节) 一 、实验目的 1.掌握下三角矩阵的输入、输出、转置算法。 2.理解稀疏矩阵的三元组表类型定义,掌握稀疏矩阵的输入、输出、转置算法。 二 、实验要求 1.认真阅读和掌握本实验的算法思想。 2.编写完整程序完成下面的实验内容并上机运行。 三、实验内容 1.所谓上(下)三角矩阵是指矩阵的下(上)三角的元素均为常数或零的n阶矩阵。此时除了存储上(下)三角矩阵的元素之外再加一个存储常数的空间即可。三角矩阵的重复元素c可共享一个存储空间,其余的元素正好有n×(n+1)/2个,因此,三角矩阵可压缩到向量Sa[0……n×(n+1)/2],其c存放在向量的最后一个分量。用向量Sa[0……n×(n+1)/2]压缩存储下三角矩阵,编写程序任意输入一个下三角矩阵,对其进行转置,输出转置后的矩阵。 2.用三元组顺序表压缩存储稀疏矩阵,编写程序任意输入一个稀疏矩阵,对其进行转置,输出转置后的矩阵。 四、思考与提高 如何计算一个三元组表表示的稀疏矩阵对角线元素之和以及两个三元组表表示的稀疏矩阵的乘积? 实验5:二叉树的建立及遍历 (第十三周星期三7、8节) 一 、实验目的 1.学会实现二叉树结点结构和对二叉树的基本操作。 2.掌握对二叉树每种操作的具体实现,学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。 二 、实验要求 1.认真阅读和掌握和本实验相关的教材内容。 2.编写完整程序完成下面的实验内容并上机运行。 3.整理并上交实验报告。 三、实验内容 1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归遍历算法(前序、序、后序)对这棵二叉树进行遍历并计算出二叉树的高度。 2 .编写程序生成下面所示的二叉树,并采用序遍历的非递归算法对此二叉树进行遍历 四、思考与提高 1.如何计算二叉链表存储的二叉树度数为1的结点数? 2.已知有—棵以二叉链表存储的二叉树,root指向根结点,p指向二叉树任一结点,如何求从根结点到p所指结点之间的路径? 实验6:二分查找、Hash查找算法的程序实现 (第十五三周星期三7、8节) 一、 实验目的 1 .熟练掌握二分查找算法并能在有序表进行查找操作。 2. 掌握Hash表的相关算法。 二 、实验要求 1.认真阅读和掌握和本实验相关的教材内容。 2.复习顺序表及二叉树的基本操作过程。 3.编写完整程序完成下面的实验内容并上机运行。 4.整理并上交实验报告。 三、实验内容 1.二分查找又称为折半查找,它要求要查找的顺序表必须是有序表,即表结点按关键字有序.并且要用顺序存储结构。 基本思想是:首先将给定值key与表间位置记录的关键字相比较,若二者相等,则查找成功,否则根据比较的结果确定下次查找的范围是在间记录的前半部分还是后半部分,然后在新的查找范围内进行同样的查找,如此重复下去,直到在表找到关键字与给定值相等的记录,或者确定表没有这样的记录。 编写程序构造一个有序表La,从键盘接收一个关键字key,用二分查找法在La 查找key,若找到则提示查找成功并输出key所在的位置,否则提示没有找到信息。 2.编写程序实现Hash表的建立、删除、插入以及查找操作。 程序应包含的主要功能函数有: Hash( ):计算哈希地址 InitialHash( ):初始化哈希表 SearchHash( ):在哈希表查找关键字 InsertHash( ):向哈希表插入关键字 DeleteHash( ):删除哈希表某一关键字 PrintHash ( ):打印输出哈希表 四、思考与提高 如何利用二分查找算法在一个有序表插入一个元素x,并保持表的有序性? 实验7:至少三种排序算法的程序实现 (第十六周星期三7、8节) 一、 实验目的 1.掌握简单插入排序、冒泡排序、快速排序、堆排序以及归并排序的算法并加以应用。 2.对各种查找、排序技术的时间、空间复杂性有进一步认识。 二 、实验要求 1.认真阅读和掌握和本实验相关的教材内容。 2.编写完整程序完成下面的实验内容并上机运行。 3.整理并上交实验报告。 三、实验内容 编写程序实现下述五种算法至少三种,并用以下无序序列加以验证: 49,38,65,97,76,13,27,49 1.简单插入排序 2.冒泡排序 3.快速排序 4.归并排序 5.堆排序 四、思考与提高 1.设有1000个无序的元素,希望用最快的速度挑出其前10个最大的元素,采用哪一种排序方法最好?为什么? 2.如何构造一种排序方法,使五个整数至多用七次比较就可以完成排序任务? 实验8:集成实验 一、 实验目的 目的:扩大编程量,完成模块化程序设计的全过程。 二 、实验要求 1.认真阅读和掌握和本实验相关的教材内容。 2.编写完整程序完成下面的实验内容并上机运行。 3.整理并上交实验报告。 三、实验内容 将已经实现的模块装配在一起,由菜单进行管理,形成一个小型多功能软件。 while(1){ menuList(); scanf(&n); switch(n){ case 1:……;break; case 2:……;break; . . case 0:return; } } 如: • MenuSelect( ){ int select; SqList A , B , C ; MenuList( ); /* 打印菜单 */ scanf(“%d”,&select;); switch(select){ case 1: InitList_Sq( &A ); break; case 2: InitList_Sq( &B ); break; case 3: Insert(&A);break; case 4: Insert(&B );break; case 5: Union(&A ,B);break; ………….. default: printf(“\n ERROR\n”); } } 四、思考与提高 1. 优化已完成的程序,使整个实验形成至少三级菜单管理; 2.美化输出界面,使得操作友好。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lyx_wmt

能白嫖就绝不打赏

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

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

打赏作者

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

抵扣说明:

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

余额充值