目录
进制转换(itoa)
atoi函数的编写
使用指针编写strlen,strcmp(const char*str,const char*src), strcat, strcpy函数
1)itoa(此处负数除外)
进制转换的思路
将一个数字从十进制转换为2,8,16进制,学过进制转换的应该知道十进制转换其他进制数,均是辗转相除法,做法和思路一样,定义一个字符数组,为什么是字符数组,而不是一个数组呢,因为16进制的10~16为字母a~f,将原数字对要转换的进制数取余,余数存入字符数组中,取余之后原数字除以要转换的进制数,将得到的结果继续取余,取余的结果存入数组,继续除进制数,一直循环下去,知道除以进制数的结果为0,很显然,这样得到的数字是转换完成之后的逆序,因此对字符数组进行逆序便是需要的结果。
代码分析
上面可能说的比较绕,可以举一个例子理解一下,将数字15转换为2进制,首先对14除2取余,结果为0,然后除以2得到结果7,7除2取余结果为1,接着对数字7除以2得到3,3对2取余为1,3除以2为1,1对2取余为1,1除以2为0,很显然得到的数字依次存入字符数组结果为0111,正好是结果的逆序,对字符数组逆序得到1110。通过这个举例应该能更好的理解这一思路。接下来将代码展现出来,并且分析:
void my_itoa(int vlan, char*arr,int m)//vlan为要转换的数字,arr为目标字符数组,m为目的数字的进制
{
for (int i = 0; vlan != 0; i++)//因为不知道转换结果的位数,因此只能顺序将余数存入数组
{
if (vlan%m < 10) *(arr + i) = vlan%m + '0';
else *(arr + i) = vlan%m + 'A'-10;
/*因为16进制的10~15需要用字母a~f来代替,因此用了if语句做判断*/
vlan /= m;
}
int begin = 0; int end = strlen(arr) - 1; int mid = (begin + end+1) / 2;
char *my_begin = arr + begin; char*my_end = arr + end;
for (int j = begin; j <mid ; j++)//此处为对字符数组内的元素进行逆序
{
int temp = *my_begin;
*my_begin = *my_end;
*my_end = temp;
my_begin++; my_end--;
}
}
int main()
{
int vlan ;
int m;
printf("请输入原数字vlan");
scanf("%d", &vlan);
printf("请输入进制位数");
scanf("%d", &m);
char arr[128]="";
my_itoa(vlan, arr, m);
int c = strlen(arr);
for (int i = 0; i <c; i++)
printf("%2c", arr[i]);
}
该代码其实很简单,首先思考该函数需要传递的参数,参数有三个,原数字(10进制),目的数字的进制数,目的字符数组。 因为取余,相除的操作过多,而且不知道次数,肯定需要循环,直接进行循环,因为不知道目标数字的长度,因此只能将数组顺序遍历,即循环从0开始写起,循环终止条件为相除的结果等于0,循环的大致结构便是这样,内部循环体呢,因为首先取余赋值,然后再相除,这样循环下去,所以循环体也是这样,先取余赋值,最后相除,此处有一部分问题,转换16进制时有字母,所以此处应该加入if else条件判断,如果余数大于等于10时,赋值应该+a-10,这样便将所有余数赋值到数组中,最后对字符数组进行逆序便得到了想要的结果。(若逆序如有不理解可参考前几次文章)
2)atoi函数
该函数相比较于进制转换较为简单,将字符数组中的数字赋值给原字符数组,方法很简单,对原字符数组进行遍历,若为‘+’,’-‘,数字均从字符数组首位进行赋值。思路过于简单便不做进一步理解叙述,直接上代码:
int my_atoi(char*arr)
{
char*ar = arr;
int c = 0;
for (int i = 0; i < strlen(arr); i++)
{
if (*(arr + i) == '-' || *(arr + i) == '+' || ((*(arr + i) >= '0') && (*(arr + i) <= '9')))
{
*ar++ = *(arr + i);
c++;
}
}
return c;
}
int main()
{
char arr[] = " -123 97ugdsigdigs";
int c=my_atoi(arr);
for (int i = 0; i < c; i++)
printf("%2c", arr[i]);
}
3)strlen,strcmp(const char*str,const char*src), strcat, strcpy函数
此处对以上函数做以叙述,
strlen函数:用于求字符数组的长度,测量时再字符数组中找到'\0'结束,但是字符长度却不将其计算入内,思路便是遍历字符数组,遍历到'\0'结束,代码如下:
int my_strlen(char *arr)
{
int c = 0;
char*ar = arr;
while (*ar++!= '\0')
{
c++;
};
return c;
}
strcmp(const char*str,const char*src)函数:该函数用于两字符数组比大小,将两字符数组遍历,依次比较两数组中对应元素的大小,若字符数组长度不一样,且一个包含另一个,则长度长的数组大。代码如下:
int my_strcmp(const char*str, const char*src)
{
const char*p = str;
const char*q = src;
int len1 = strlen(str);
int len2 = strlen(src);
int c=0;
for (int i = 0; i < (len1<len2?len1:len2); i++)
{
if (*(p + i)>*(q + i))
{
c = 1;
break;
}
if (*(p + i) < *(q + i))
{
c = -1;
break;
}
}
if (c == 0)
{
if (len1>len2) c = 1;
else if (len1 < len2) c = -1;
else c = 0;
}
return c;
}
strcat函数:该函数为链接函数,将一个字符数组的元素链接到另一个字符数组后面,将需要链接的字符数组从有效位数开始遍历赋值,将需要链接的数组元素依次赋值,循环结束条件为遍历到两数组的有效长度之和。代码如下:
void my_strcat(char*arr, const char*brr)
{
char *ar = arr;
const char*br = brr;
int c=strlen(arr)+strlen(brr);
for (int i = strlen(arr); i < c; i++)
{*(arr + i) = *(brr++);
}
}
strcpy函数:拷贝函数,将一个字符数组中的字符串拷贝给另一个字符数组,数组便利,依次赋值
void my_strcpy( const char* arr, char* const brr, int len1, int len2)
{
assert(arr != NULL&&len1 <= len2);
const char*ar = arr;
char *br = brr;
for (int i = 0; i < len1; i++)
{
*br++ =*ar++;
}
}
注:因为最后几道题难度较低,不做过多思路讲解,望理解