目录
查找两个字符串的最大公共字串
指针的运用
#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级的存在,个人感觉实际用途并不大,在执行&操作的时候,就已经完成了十进制转二进制的操作,只不过无法读取而已,再之后,就是逐位的去判别是零还是一了,确定好了,把这一位个右移到最右边,进行输出。