嵌入式面试中常见的编程题目

以下内容源于网络资料的学习整理,如有侵权,请告知删除。

目录

1、将字符串反转

2、数字翻转和回文判断

3、大小端问题

(1)判断大小端

(2)大小端转换

4、实现函数memcpy(), strcpy(), strcmp(), strcat()

5、实现最简单的hello world字符设备驱动

6、设计函数 int atoi(char *s),void itoa(int n, char s[])

7、链表操作(单链表的插入、删除节点、遍历、反转)


 

1、将字符串反转

void reserverString(char str[])
{
	char tmp;
	int i, j;
	for (i = 0, j = strlen(str) - 1; i < j; i++, j--)
	{
		tmp = str[i];
		str[i] = str[j];
		str[j] = tmp;
	}
}

char* reserverString1(char* str)
{
	char* start = str;
	char* end = str + strlen(str) - 1;
	char tmp;
	if (NULL != str)
	{
		do
		{
			tmp = *start;
			*start++ = *end;
			*end-- = tmp;
		} while (start

 

2、数字翻转和回文判断

 

 

3、大小端问题

(1)判断大小端

方法一:

int main(void)
{
	int a = 0x1234;
	char b = *((char*)&a);
	if (b == 0x12)
		printf("BIGEND\n");
	if (b == 0x34)
		printf("littleEND\n");
	system("PAUSE");
	return 0;
}

方法二:用联合体

(2)大小端转换

//对于字数据16bit
#define BIG2LITTLE(A)   ((((A)&0xff00)>>8) | (((A)&0x00ff)<<8))  

//对于双字数据32bit
#define BIG2LITTLE(A)  (((A)&0xff000000)>>24) | (((A)&0x000000ff)<<24) | (((A)&0x0000ff00)<<8) | (((A)&0x00ff00)>>8))

 

4、实现函数memcpy(), strcpy(), strcmp(), strcat()

(1)函数原型 :void *memcpy(void *dest, const void *src, size_t n);

功能:从源src所指的内存地址的起始位置开始,拷贝n个字节到目标dest所指的内存地址的起始位置中,函数返回dest的值。

void *memcpy(void *dest, const void *src, size_t n)
{
	if (NULL == dest || NULL == src)
		return NULL;

	char* tmp = (char*)dest;
	const char* s = (const char*)src;//这里注意下
	while (n--)
	{
		*tmp++ = *s++;
	}
	return dest;
}

(2)函数原型 :void strcpy (char *dest,const char*src);

功能:将src拷贝到dest中

void strcpy(char *dest, const char*src)
{
	while(*dest++=*src++)
	{
	}
}

(3)函数原型 :int strcmp(const char *s,const char * t);
功能:比较字符串s和t,并且根据s按照字典顺序小于,等于或大于t的结果分别返回负整数,0,正整数。

int strcmp(const char *s, const char * t)
{
	for (; *s == *t; s++, t++)//注意for循环,能循环下去的条件的两者元素对应相等,一旦不相等立即退出
		if (*s == '\0')
			return 0;//表示相等
	return *s - *t;
}

(4)函数原型 :char *strcat(char *dest,char *src);
功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0',返回指向dest的指针

char* strcat(char *dest,const char *src)
{
	char* tmp = dest;
	assert((NULL != dest) && (NULL != src));
	while (*tmp)
	{
		tmp++;
	}//循环结束时,指针指向字符'\0',后面会覆盖
	while (*tmp++ = *src++) 
	{
	}
	return dest;
}

5、实现最简单的hello world字符设备驱动

//1、头文件的包含
#include 
#include 

//许可的声明
MODULE_LICENSE("Dual BSD/GPL");

//3、函数注意static、返回值、printk、KERN
static int hello_init(void)
{
	printk(KERN_ALERT "Hello World!\n");
	return 0;
}
static void hello_exit(void)
{
	printk(KERN_ALERT "Goodbye, cruel world\n");
}
//4、注意这两个宏函数的使用
module_init(hello_init);
module_exit(hello_exit);

6、设计函数 int atoi(char *s),void itoa(int n, char s[])

(1)int atoi(char *s)

描述:把字符串转换成整型数的一个函数。int atoi(const char *nptr) 函数会扫描参数 nptr字符串,跳过前面的空白字符(例如空格,tab缩进)等,可以通过isspace( )函数来检测),直到遇上数字或正负符号才开始做转换,而在遇到非数字或字符串结束符('\0')才结束转换,并将结果返回。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回0。特别注意,该函数要求被转换的字符串是按十进制数理解的。

int atoi(char s[])
{
	int i, n, sign;
	for (i = 0; isspace(s[i]); i++); /*跳过空白符:空格时会一直循环,直到遇到不是空格*/

	sign = (s[i] == '-') ? -1 : 1;//遇到的如果不是-号,比如是数字,则说明不是负数

	if (s[i] == '+' || s[i] == '-') /* 跳过符号 */
		i++;

	for (n = 0; isdigit(s[i]); i++)
		n = 10 * n + (s[i] - '0');
	return sign * n;
}//注意判断空格、是否是数字的函数,你懂写吗?

(2)void itoa(int n, char s[])

功能:将整型数字转换为字符串

void itoa(int n, char s[])
{
	int i, sign;

	if ((sign = n) < 0) //记录符号
		n = -n; //使n成为正数
	
	i = 0;
	do 
	{ //以反序生成数字          //假设n=987654
		s[i++] = n % 10 + '0'; //n % 10 + '0'表示数字对应的字符,比如第一次的数字是4,变成字符4,是4+'0'
		                       
	} while ((n /= 10) > 0);   //此时n变成了98765
	
	if (sign < 0)
		s[i++] = '-';
	s[i] = '\0';
	
	reverse(s);
}

7、链表操作(单链表的插入、删除节点、遍历、反转)

https://blog.csdn.net/oqqHuTu12345678/article/details/78899439

#include 
#include 
#include 


typedef struct node 
{
	int data;
	struct node* next;
}Node;

/*********************************************************************
1、函数功能:将链表反转
2、实现方法:遍历+头插入,即每遍历一个元素,立即将该元素头插入
3、函数返回:反转后链表头结点的指针
4、之前遇到的、有头结点的链表,头或尾插入一个数都很简单;
5、现在多个数连续插入稍微难处理,而且这主要运用在反转链表中。
2018.925 xjh
*********************************************************************/

Node* reserverLinklist(Node* PH)
{
	Node* p = PH->next;//p表示当前节点指针
	Node* pnext = NULL;//pnext表示当前节点的下一个节点指针
	Node* head = NULL;//用来实现头插入的临时变量

	//特殊情况处理:当链表没有有效节点或者只有一个有效节点时,逆序不用做任何操作
	if ((NULL == p) || (NULL == p->next))
		return PH;

	while (NULL!=p)//如果当前节点不为空
	{
		pnext = p->next;//后面因为新链表头插入,破坏了p->next,因此先要备份p->next,否则丢失原链表的信息

		//新链表头插入
		p->next = head;
		head = p;

		//恢复p,以便进入到下一个元素(p没有改变,但p->next改变了,因此不能直接p=p->next)
		p = pnext;

	}//这个结束时,p为NULL,head指向原链表的最后一个元素,该元素在新链表中是第一个元素,下面在该元素前添加头结点
	PH->next = head;
	
	return PH;
}

struct node * create_node(int data)
{
	struct node *p = (struct node *)malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error.\n");
		return NULL;
	}
	p->data = data;
	p->next = NULL;
	
	return p;
}

void insert_head(Node *pH, Node *newNode)
{
	newNode->next = pH->next;
	pH->next = newNode;
}

void traverse(Node* pH)
{
	struct node *p = pH;
	printf("-----------开始遍历-----------\n");
	while (NULL != p->next)	
	{
		p = p->next;
		printf("node data: %d.\n", p->data);
	}
	printf("-----------遍历结束-----------\n");
}

int main(void)
{
	Node *pHeader0 = create_node(0);//创建头结点
	Node *pHeader1 = NULL;
	
	insert_head(pHeader0, create_node(11));//11,12,13是所创建的节点数据,这里采用头插法。
	insert_head(pHeader0, create_node(12));
	insert_head(pHeader0, create_node(13));//此步过后,数据应该为0,13,12,11
	traverse(pHeader0);//打印13,12,11
	
	pHeader1 = reserverLinklist(pHeader0);
	traverse(pHeader1);//打印11,12,13

	system("PAUSE");
	return 0;
}

 

 

 

 

你可能感兴趣的:(面试/笔试经历)