
C和指针
文章平均质量分 52
C和指针课后习题片段
乌龟盖瑞
这个作者很懒,什么都没留下…
展开
-
2007年美国M公司面试题
2007年11月美国著名软件企业M公司面试题下面程序哪一行会崩溃?struct S { int i; int *p;};int main() { struct S s; int *p = &s.i; p[0] = 4; p[1] = 3; s.p = p; s.p[1] = 1; s.p[0] = 2; return 0;}我们逐行分析一下:struct S s;int *p = &a..原创 2021-03-09 16:28:25 · 207 阅读 · 1 评论 -
ADT(抽象数据类型)--二叉树
二叉树是树的一种特殊形式,它的每个子节点至多具有2个孩子,分别是左孩子和右孩子,另外,每个节点的值比它的左子树的所有节点都大,但比它的右子树的所有节点都小,所以有了这个规则,树中就不会有重复的元素,这个特性也使二叉搜索树成为一种用关键值快速查找数据的优秀工具。...原创 2021-03-05 14:42:56 · 1727 阅读 · 1 评论 -
ADT(抽象数据类型)--队列
队列是先进先出,直接和排队类比即可,队列的实现较堆栈要麻烦一些,比如用静态数组来实现队列,每次移除数据后原来的位置就空起了,使用一个指针front指向队列头部,用另一个指针rear指向队列尾部,比如一个5个元素的数组,删除3个元素后,本来数组还可以继续存入3个元素,但那3个元素则无法再次利用了。为此,提出了环数组的概念:即当尾部下标移出数组时,就设置为0。front不再是固定的,而是跟随移除数据往后移动,front 和rear都是动态变化的,添加数据时rear也递增移动,删除数据时front向前移动原创 2021-03-03 17:03:27 · 546 阅读 · 0 评论 -
ADT(抽象数据类型)--堆栈
堆栈很简单,先进后出,用静态数组和动态内存分配实现:版本一:静态数组版本define STACK_SIZE 100typedef int STACK_TYPE;//堆栈数组static STACK_TYPE stack[STACK_SIZE];//栈顶offset indexstatic int top_element = -1;//pushvoid push(STACK_TYPE value) { assert(!is_full()); top_element +原创 2021-03-02 16:19:42 · 317 阅读 · 0 评论 -
C函数指针的常见2大应用:回调函数和转移表
函数指针在实际的代码中还是很常见,一般有2大应用:1、回调函数(Callback Functions)我们先看一下之前我们在链表中查找一个节点的做法:typedef struct NODE { int value; struct NODE *link;} Node;void display(Node *list) { Node *p = list; do { printf("%d ", p->value); } while(原创 2021-02-24 20:08:47 · 269 阅读 · 0 评论 -
用链表实现索引单词表
【12.8-7】编写一个函数,把一个新单词插入到问题7所描述的索引表中。函数接受两个参数,一个指向list指针的指针和一个字符串,该字符串假定包含单个单词,如果这个单词原先并未存在索引表中,它应该复制一块动态分配的节点并插入到这个索引表中,如果成功插入返回真,如果该字符原先已经存在于索引表中,或字符串不是以字符开头或其他错误返回假。函数应该维护一个一级链表,节点的排序以字母为序,其余的二级链表则以单词为序排列。第一步构建一个索引列表:typedef struct WORD { str原创 2021-02-24 15:03:49 · 665 阅读 · 0 评论 -
双链表删除节点
编写一个程序,从双链表中移除一个节点,函数的原型如下int dll_remove(struct NODE *rootp, struct NODE *node);你可以假设节点数据结构在头文件double_linked_list_node.h文件中定义,函数第一个参数是一个指向包含链表根指针的节点的指针,第二个参数是个指向欲移除的节点的指针,如果链表并不包含欲移除的指针,函数就返回假,否则函数移除该节点并返回真。遇到链表操作的题目,第一步就是画一个链表图,然后理清指针指向然后再转化成代码原创 2021-02-22 16:29:08 · 6654 阅读 · 0 评论 -
单链表移除节点
【12.8-5】编写一个程序,从一个单链表中移除一个节点,函数的原型如下:int sll_remove(struct NODE **rootp, struct NODE *node);你可以假设节点数据结构在头文件singly_linked_list_node.h中定义,函数的第一个参数是一个指向链表根指针的指针,第二个参数是一个指向欲移除的节点的指针,如果链表并不包含该指针,函数就返回假,否则它就移除这个节点并返回真,把一个欲移除的节点的指针而不是欲移除的值作为参数传递给函数有哪些优点?这个原创 2021-02-22 15:19:01 · 293 阅读 · 1 评论 -
高频面试考点:反序排列单链表
【12.8 4】编写一个函数,反序排列一个单链表中所有的节点。函数应该具有下面的原型:struct NODE *sll_reverse(struct NODE *first);在头文件singly_linked_list_node.h中声明节点数据结构。函数的参数指向链表的第一个节点。当链表被重排之后,函数返回一个指向链表新头节点的指针,链表最后一个节点的link字段的值应设置为NULL,在空链表(first == NULL)上执行这个函数将返回NULL。实现单链表的反转方法有很多种,这里就原创 2021-02-22 14:20:31 · 301 阅读 · 0 评论 -
双链表进化-实现一个最优的双链表插入算法
(注意:这里第一个结点的bwd为NULL,最后一个节点的fwd位NULL。)要将一个节点插入到双链表中,有几种情况:1、插入链表中间位置2、插入链表起始位置3、插入链表结束位置4、原链表为空,相当于既要插入起始位置,又插入结束位置。每种情况有4个指针必须修改:在1,2 两种情况下新节点fwd字段必须设置为指向链表的下一个节点,链表下一个节点的bwd字段必须指向这个新节点。在3,4两种情况下,新节点的fwd字段字段必须设置为NULL,根节点的fwd必须指向这个新节...原创 2021-02-19 13:36:51 · 287 阅读 · 0 评论 -
单链表进化-实现一个最优的单链表插入算法
实现如下有序的单链表:创建数据结构:typedef struct NODE { int value; struct NODE *link;} Node;版本一:int ssl_inset(Node *current, int new_value) { Node *previous; Node *new_node; while(current->value < new_value) { previous = cu原创 2021-02-18 18:01:16 · 400 阅读 · 0 评论 -
最简单的数据链表雏形
【11-4】编写一个程序,按照下图中的样子创建数据结构,最后三个对象都是动态分配的结构。第一个对象则可能是一个静态的指向结构的指针。你不必使这个程序过于全面--我们将在下一章讨论这个结构。这个题目就是定义一个最简单的数据链表,实际应用中我们会写大量类似的代码,在后面的链表结构的时候在重点讨论。typedef struct NODE { int value; struct NODE *next;} Node;Node *new_node(int value) { N原创 2021-02-09 17:37:27 · 161 阅读 · 0 评论 -
从标准输入读取字符串
【11-3】编写一个函数,从标准输入读取一个字符串,把字符串复制到动态内存分配的内存中,并返回该字符串的拷贝,这个函数不应该对读入字符串的长度作任何限制!这个问题比较简单,需要注意字符串输入的结束处理和内存空间的申请的时机。#include <stdio.h>#include <string.h>#include <assert.h>typedef short int int16_t;typedef int int32_t;#define TRU原创 2021-02-09 15:25:25 · 802 阅读 · 1 评论 -
从标准输入读取一系列数字的处理
【11-2】编写一个函数,从标准输入读取一列整数,把这些值存储于一个动态分配的数组中并返回这个数组,函数通过观察EOF判断输入是否结束,数组的第一个数是数组包含的值的个数,它的后面就是这些整数值。这个题目看起来很简单,但是有一个地方不好处理,scanf到达尾部EOF的时候才返回,那这些缓冲区的数据如何存储?这些缓冲区的数据包含了数组大小和实际的数据内容。...原创 2021-02-08 18:46:49 · 1145 阅读 · 0 评论 -
C语言结构体的位段替代方法
【10-11】如果不使用位段,你怎样实现下面这段代码的功能?假定你使用的是一台16位的机器,它从左向右为位段分配内存。struct { int a: 4; int b: 8; int c: 3; int d: 1;} x;....x.a = aaa;x.b = bbb;x.c = ccc;x.d = ddd;这个题目的思路很重要,特别是对嵌入式开发来讲,在C语言中,不管是什么结构,解析为内存地址映射后就比较好理解。比如这个题目这个结构体变量x,它原创 2021-02-05 18:14:21 · 440 阅读 · 1 评论 -
C语言结构体数组的指针运用
【10-7】考虑下面这些声明和数据。struct NODE{ int a; struct NODE *b; struct NODE *c;};struct NODE nodes[5] = { {5, nodes + 3, NULL}, {15, nodes + 4, nodes + 3}, {22, NULL, nodes + 4}, {12, nodes + 1, nodes}, {18, nodes + 2, nodes .原创 2021-02-05 15:02:54 · 668 阅读 · 0 评论 -
C实现有效位处理的通用字符串格式化
【9-17】这个程序与前两个练习类似,但更加一般化了,它允许调用程序把逗号放在大数的内部,去除多余的前导0以及提供一个浮动的美元符号等。这个函数的操作类似于IBM370机器上的Edit和Mark指令。它的原型如下:char *edit(char *pattern, char const *digits);它的基本思路很简单,模式(pattern)就是一个图样,处理结果看上去应该向它的样子。数字字符串中的字符根据这个图样所提供的方式从左向右复制到模式字符串。数字字符串的第一位有效数字很重要,结原创 2021-02-04 21:26:19 · 226 阅读 · 1 评论 -
C实现通用字符串格式化
【9-16】这个程序与前一个练习相似,但它更为通用。它按照一个指定的格式字符串对一个数字字符串进行格式化,类似许多BASIC编码器所提供的“print using”语句。函数的原型如下:int format(char *format_string, char const *digit_string);digit_string中的数字根据一开始在format_string中找到的字符从右到左逐个复制到format_string中。注意被修改后的format_string就是这个处理过程的结果,当你原创 2021-02-04 17:40:18 · 1669 阅读 · 0 评论 -
战争谍报加密算法
【9-12】有一种技巧可以对数据进行加密,并使用一个单词作为它的密钥。下面是它的工作原理:首先,选择一个单词作为密钥,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第一个,其余几个丢弃。现在,修改过的那个单词列于字母表的下面,如下所示:最后,底下那行字母表中剩余的字母填充完整(不能和前面的重复):在对信息进行加密时,信息中的每个字母被固定于顶上那行,并用下面那行的对应字母一一取代原文的字母。因此,使用这个密钥,ATTACK AT DAWN(黎明时攻击)就会被加密为TPPTAD原创 2021-02-02 22:03:11 · 761 阅读 · 0 评论 -
回文检测
编写函数int palindrome(char *string);如果参数字符串是个回文,函数就返回真,否则返回假。回文就是指一个字符串从左向右和从右向左读是一样的。函数应该忽略所有的非字母字符,而且在进行字符比较时不用区分大小写。其实回文本身的检测逻辑其实很简单,就是将一个指针指向最后,一个指针指向头部,不断靠近对比。但这个题目加了一些额外条件:1、忽略所有非字母字符2、忽略大小写大的检测逻辑没有变化,只是说判断的时候需要添加额外条件。#define TRUE 1#原创 2021-02-02 15:28:16 · 706 阅读 · 0 评论 -
实现查找字符指定第几次出现的函数my_strnchr
编写一个名叫my_strnchr的函数,它的原型如下:char *my_strnchr(char comst *str, int ch, int which);这个函数类似于strchr,但它的第三个参数指定ch字符在str字符串中第几次出现,例如,第三个参数为1,这个函数的功能就和strchr一样,如果参数为2,这个函数就返回一个指向ch字符在str字符串中第二次出现的位置的指针。char *my_strnchr(char const *str, int ch, int which)原创 2021-02-01 18:28:03 · 976 阅读 · 0 评论 -
实现字符串拷贝函数my_strcpy
【8-3】编写一个名为my_strcpy的函数,它类似与strcpy函数,但它不会溢出目标数组。复制的结果必须是一个真正的字符串。目标字符数组,是空的,要想保证其不溢出,有什么可以作为判断条件呢? 只有传入一个长度,也就是strncpy的实现。char * my_strcpy(char *dst, const char *src, int size) { strncpy(dst, src, size); *(dst + size - 1) = NUL; return ds原创 2021-02-01 16:54:13 · 827 阅读 · 1 评论 -
实现字符串长度函数my_strlen
【9-2】编写一个名叫my_strlen的函数,它类似与strlen函数,但它能够处理由于使用strn--函数而创建的未以NUL字节结尾的字符串。你需要向函数传递一个参数,它的值就是保存了需要进行长度测试的字符串的数组的长度。这个题目比较简单就2个条件:字符串以'\0'结束,或者到达了传入的len长度:#define NUL '\0'int my_strlen(char * str, int len) { int count = 0; while( *str++ != NU原创 2021-02-01 16:01:09 · 708 阅读 · 0 评论 -
strtok、strtok_r 、strsep函数的问题
首先看第一个strtok:虽然strtok有诸多问题,已经被Linux kernel淘汰,由strsep替代,但了解这个函数的实现对我们理解C语言的运用极有裨益,也有过知名企业的面试中甚至出现了strtok函数的实现考察。C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。这个函数陷阱很多,我们先看一下这个函数一个实现(来源于apple opensource):#include &l.原创 2021-01-27 17:52:04 · 796 阅读 · 0 评论 -
字符串查找strstr实现
通过对C的库函数strstr的实现,可以加深对字符串和指针的理解。函数定义:char * strstr (const char *s1, const char *s2)我们很容易就可以想到一个嵌套循环查找:版本一:外层循环用于定位在是s1中的查找起点,当内侧循环未完全匹配的时候,外侧循环的指针就后移一位,再次通过内侧循环测试。而内层循环一旦对应相等则不断比较测试后面的字符,直到s2子串的尾部,如果p2到达尾部说明完全相等。内层循环如果发现有不等的字符就跳出内层循环重新从s1的下一位开原创 2021-01-26 17:24:08 · 457 阅读 · 0 评论 -
八皇后问题
【8-8】皇后是国际象棋中威力最大的棋子,在下面所示的棋盘上,皇后可以攻击位于箭头所覆盖位置的所有棋子。我们能不能把8个皇后放在棋盘上,它们中任何一个都无法攻击其余的皇后?这个问题被称为八皇后问题,你的任务是编写一个程序,找到八皇后问题的所有答案,看看一共有多少种答案。提示:如果你采用一种叫做回溯法的技巧,就很容易编写出这个程序,编写一个函数,把皇后放在某行的第一列,然后检查它是否与棋盘上的其他皇后互相攻击,如果存在互相攻击,函数把皇后移到该行的第二列再进行检查,如果每列都存在互相攻击的情况,函原创 2021-01-25 17:51:35 · 710 阅读 · 0 评论 -
C语言虚拟伪数组
如你所知,C编译器为数组分配下标时总是从0开始,而且当程序使用下标访问数组元素时,它并不检查下标的有效性,在这个项目中,你将要编写一个函数,允许用户访问“伪数组”,它的下标范围可以任意指定,并伴以完整的错误检查。下面是你将要编写的这个函数的原型:int array_offset(int arrayinfo[],...);这个函数接受一些用于描述伪数组的维数信息以及一组下标值,使用这个函数,用户既可以以向量的形式分配内存空间,也可以使用mallco分配空间,但按照多维数组的形式访问这些空间,这个数原创 2021-01-21 19:46:37 · 935 阅读 · 3 评论 -
矩阵乘法C实现
如果A是个x行y列的矩阵,B是个y行z列的矩阵,把A和B相乘,其结果将是另一个x行z列的矩阵C。这个矩阵的每个元素是由下面的公式决定的:结果矩阵中14这个值是通过2 × -2 加上 -6 × -3得到的。编写一个函数,用于执行两个矩阵的乘法。函数的原型如下:void matrix_multiply(int *m1, int *m2, int *r, int x, int y, int z);m1是一个x行y列的矩阵,m2是一个y行z列的矩阵,这两个矩阵应该相乘,结果存储于r中,它是一原创 2021-01-20 19:42:10 · 959 阅读 · 1 评论 -
判断单位矩阵
单位矩阵就是一个正方形矩阵,它除了主对角线元素值为1以外,其余元素的值均为0,例如:1 0 00 1 00 0 1就是一个3×3单位矩阵,编写一个名叫identity_matrix的函数,它接受一个10×10整型矩阵为参数,并返回一个布尔值,提示该矩阵是否为单位矩阵。 这个算法非常简单,简单的2层循环就可以搞定,直接看代码吧:#define TRUE 1#define FALSE 0int identity_matrix(int matrix[10][10]) { i.原创 2021-01-20 14:35:54 · 2068 阅读 · 0 评论 -
多维数组的特定位置初始化
编写一个数组的声明,把数组的某些特定位置初始化为特定的值。这个数组的名字应该叫char_value,它包含3×6×4×5个无符号字符。下面的表中列出的这些位置应该用相应的值进行静态初始化。那些在上表未提到的位置应该被初始化为二进制值0而不是字符’\0',注意:应该使用静态初始化,在你的解决方案中不应该存在任何可执行代码!尽管并非解决方案的一部分,你可能很想编写一个程序,通过打印数组的值来验证它的初始化,由于某些值并不是可打印的字符,所以请把这些字符用整型的形式打印出来(用八进制或十六进制输出会更原创 2021-01-19 17:22:15 · 496 阅读 · 0 评论 -
C语言陷阱之逗号表达式
多维数组的各个下标必须单独出现在一对方括号内,在什么条件下,下列这些代码段可以通过编译而不会产生任何警告信息。int array[10][20];...i = array[3,4];咋一看array[3,4] 不合法,实际上这是合法的,因为C语言里面这个是逗号表达式。逗号运算符是二元运算符:表达式1 , 表达式2逗号运算符确保操作数被顺序地处理:先计算左边的操作数,再计算右边的操作数。右操作数的类型和值作为整个表达式的结果。左操作数只是为了副作用需要而被计算,它其值会被丢弃原创 2021-01-18 16:21:19 · 608 阅读 · 0 评论 -
多维数组的指针表达式与下标表达式转换
给定下列声明int array[4][5][3];给定下列声明 把下列各个指针表达式转化为下标表达式。指针表达式 下标表达式 *array *(array+2) *(array+1)+4 *(*(array+1)+4) *(*(*(array+3)+1)+3) *(*(*array+1)+2) *...原创 2021-01-18 15:27:58 · 908 阅读 · 0 评论 -
多维数组的存储地址关系
.给定下列声明:int array[4][2][3][6]; 表达式 值 X的类型 array array+2 array[3] array[2]-1 array[2][1] array[1][0]+1 array[...原创 2021-01-15 18:20:47 · 1802 阅读 · 1 评论 -
二维数组的存储地址关系
给定下列声明 :int array[4][2];请写出下面每个表达式的值,假定数组的起始位置为1000,整型值在内存中占据了2个字节的空间。(这里的1000是十进制)计算以下表达式值:array array+2 array[3] array[2]-1 &array[1][2] &array[2][0]首先我们看一下这个表达式定义int array[4][2];表示一个4行2列的数组。1000 1002 1004 1006 10.原创 2021-01-08 18:13:47 · 3111 阅读 · 0 评论 -
C语言数组与指针的定义与声明不一致会发生什么?
下面的声明取自某个源文件:int a[10];int *b = a;但在另一个源文件中,却发现了这样的代码:extern int *a;extern int b[];int x,y;...x = a[3];y = b[3];请解释一下,当两条赋值语句执行时会发生什么?(假定整型和指针的长度都是4个字节。)int a[10];int *b = a;与extern int *a;extern int b[];声明和定义并不一致。先看一下程序跑的结果吧.原创 2021-01-07 11:04:11 · 412 阅读 · 0 评论 -
数组中的地址深入理解
根据下面给出的声明和数据,对每个表达式进行求值并写出他的值。在每个表达式进行求值是使用原来给出的值(也就是说,某个表达式的结果不影响后面的表达式)。假定ints数组在内存中的起始位置是100,整型值和指针的长度都是4字节。 int ints[20] = {10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200}; int *ip = ints + 3;根据以上定义,计算以下表达式:表达式 .原创 2020-12-29 18:30:14 · 4840 阅读 · 0 评论 -
多维数组中的下标引用如何工作的?
如果要标示一个多维数组的某个元素,必须按照与数组声明时相同的顺序为每一维都提供一个下标,而且每个下标都单独位于一对方括号内:int matrix[3][10];表达式:matrix[1][5]访问这个元素:但是下标引用实际上只是间接访问表达式的一种伪装形式,在多维数组中也是如此。表达式:matrix它是 指向包含10个整型元素的数组的指针,指向包含10个整型元素的第1个子数组。表达式:matrix+1也是 指向包含10个整型元素的数组的指针,指向mat..原创 2020-12-22 16:31:32 · 669 阅读 · 0 评论 -
数组迭代循环中使用下标和指针的区别
我们来看一下2组例子:第一组例子:下标表达式:a = get_value();array[a] = 0;指针表达式:a = get_value();*(array + a) = 0;第二组例子:下标表达式:int array[10], a;for(a=0; a<10; a+=1) { array[a] = 0;}指针表达式:int array[10], *ap;for(a=array; a < array + 10; ap++)原创 2020-12-15 12:03:17 · 586 阅读 · 0 评论 -
C语言可变参数如何使用
编写一个名叫max_list的函数,它用于检查任意数目的整型参数并返回它们中最大值,参数列表必须以负值结尾,提示列表结束。这个题目的重点是任意数目的整型参数,所以并不确定传入的参数数量,这里就可以使用可变参数。#include <stdio.h>#include <stdarg.h>int max_list(int x, ...) { int max = x; va_list var_list; va_start(var_list, x);原创 2020-12-11 17:36:01 · 303 阅读 · 1 评论 -
C语言字符串转换为整数
为下面这个函数原型编写函数定义:int ascii_to_integer(char *string);这个字符串参数必须包含一个或多个数字,函数应该把这些数字字符转换为整数并返回这个整数,如果字符串参数包含了任何非数字字符,函数就返回零。请不必担心算数溢出。提示:这个技巧很简单,你每发现一个数字,把当前值乘以10,并把这个值和新数字所代表的值相加。这个算法要求即是将比如 “899”转换为899返回。设数据为x = 0,发现第一个数字8,则x += 8,x为8;发现第二..原创 2020-12-11 16:11:48 · 6393 阅读 · 0 评论