字符串的两道典型例题

目录

 

查找两个字符串的最大公共字串

不使用printf,将十进制数以二进制的形式输出


查找两个字符串的最大公共字串

指针的运用

#include <stdio.h>
#include <iostream>

using namespace std;

char *comonstring(char* str1, char* str2)
{
	char *shortstr, *longstr, *substr;
	if (str1 == NULL || str2 == NULL)
	{
		return NULL;
	}

	if (strlen(str1) >= strlen(str2))
	{
		longstr = str1;
		shortstr = str2;
	}
	else
	{
		shortstr = str1;
		longstr = str2;
	}

	if (strstr(longstr,shortstr))
	{
		return shortstr;
	}

	substr = (char *)malloc(sizeof(char)*(strlen(shortstr) + 1));

	for (int i = strlen(shortstr) - 1;i > 0;  i--)
	{
		for (int j = 0; j < strlen(shortstr) - i; j++)
		{
			memcpy(substr, &shortstr[j], i);
			substr[i] = '\0';
		}
		if (strstr(longstr, substr) == NULL)
		{
			return substr;
		}
	}
	return NULL;

}

int main()
{	
	char str1[] = "abvdafaadfaa";
	int a = strlen(str1);
	printf("a:%d\n", a);
	char str2[] = "cvda";
	char* s = comonstring(str1, str2);
	printf("%s", s);
	system("pause");
	return 0;
} 

不使用printf,将十进制数以二进制的形式输出

将一个十进制数转换为一个二进制数 ,看起来非常简单,但实现起来着实费了不少脑细胞,题目要求是以二进制形式输出,并没有说是要将一个十进制数给转换为一个二进制数,这就带来了一个bug级别的代码,如下:

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

char *get2String(long num)
{
	int i;
	char* buffer;
	char* temp;

	buffer = (char*)malloc(33);
	temp = buffer;
	for (i = 0; i < 32; i++)
	{
		temp[i] = num & (1 << (31 - i));
		temp[i] = temp[i] >> (31 - i);
		//printf("%d\n", temp[i]);
		temp[i] = (temp[i] == 0) ? '0' : '1';
	}

	buffer[32] = '\0';
	return buffer;
}

int main()
{	
	long num = 10;
	printf("input:%d\n", num);
	char *buffer = NULL;
	buffer = (char*)malloc(33);
	buffer = get2String(num);
	printf("output:%s\n", buffer);
	system("pause");
	return 0;
} 

整个过程简单,因为输入的是一个long型的数字,内存空间占4个字节,一个字节等于8位,所以是32位,因为最后转换到一个字符数组中去,所以字符数组要多留一位放“\0”,于是,就成了33位,思考到这一步还是很简单的,难的是代码中的:

	for (i = 0; i < 32; i++)
	{
		temp[i] = num & (1 << (31 - i));
		temp[i] = temp[i] >> (31 - i);
		//printf("%d\n", temp[i]);
		temp[i] = (temp[i] == 0) ? '0' : '1';
	}

这个循环,着实让人费解,到底是什么意思呢?待我慢慢道来,首先要说明白“<<”(左移运算符),“>>”(右移运算符)的作用是什么,不用管网上说的花里胡哨的,就只记住:

“a<<n”(左移运算符):就是把a转换为一个二进制数,然后,将其所有位整体向左移动n位,空出来的低位用0补上。

如:“2<<5”:2的二进制形式是“10”,那么左移后:“1000000”,后面的五个零就是向左移动五位之后空出来再用0补上的。

“b<<n”(右移运算符):就是把b转换为一个二进制数,然后,将其所有位整体向左移动n位,空出来的高位用0补上。

如:"2>>5":2的进制形式是“10”,那么右移后:"0000010",前面的五个零就是向右移动5位之后空出来再用0补上的。

就知道这么多就够了!

思路再拉回到本题:

上面的循环体,总体思路就是检测num的二进制形式中哪一位是1,如果是1,就保留,放进buffer数组。

“temp[i] = num & (1 << (31 - i));”:具体执行起来就是,将十进位数num,转换为二进制(因为执行&运算,编译器会自动转换为二进制数),然后,让这个 二进制数的每一位从左向右与“1”,做&运算(只有当1&1时,输出为1,其他都是0),当前位的&结果会被存起来。

“temp[i] = temp[i] >> (31 - i);”:因为这个结果的首位(从左向右看)必定与num对应位是一样的,然后就把这个结果的首位给提取出来,提取的方法就是让这个结果向右移动,直到首位被移动到了最右边位置。

“temp[i] = (temp[i] == 0) ? '0' : '1';”:这个时候把这个首位值给提取出来,无非是0或者1,把其分别放在对应的字符数组中,全部循环一遍之后,就完成了!

总结,其实,整个过程并不是一个将十进制数转换为二进制的过程,而是将一个二进制数表示出来的过程,这也就是之前说的为啥这是个bug级的存在,个人感觉实际用途并不大,在执行&操作的时候,就已经完成了十进制转二进制的操作,只不过无法读取而已,再之后,就是逐位的去判别是零还是一了,确定好了,把这一位个右移到最右边,进行输出。

 

 

Guess you like

Origin blog.csdn.net/qq_17846375/article/details/105034749