自定義函數篇
1 不使用C/C++字符串庫函數,如何自行編寫strcpy()函數?
char * strcpy(char *strDest, const char *strSrc)
{
assert((strDest!=NULL) && (strSrc!=NULL));
char *address = strDest;
while( (*strDest++ = *strSrc++) != '\0');
return address ;
}
返回類型為char *主要是為了實現鏈式表達式。例如:
int length=strlen(strcpy(strDest, "hello world"));
strcpy(strDest, strcpy(strDest1, strSrc));
可以將strSrc復制到strDest1與strDest中,也就是說,可以將函數的返回值做為另一個函數的參數。
2 如何把數字轉換成字符串?
C語言中常用到字符串與數字之間的相互轉換,常見的此類庫函數有atof (字符串轉換成浮點數)、atoi (字符串轉換成整型數)、atol (字符串轉換成長整型數)、itoa (整型數轉換成字符串)、ltoa (長整型數轉換為字符串)等。
以自定義Myatoi()與Myitoa()函數為例,分別實現自定義字符串轉換為整型數函數與自定義整型數轉換為字符串函數。以下為自定義Myatoi()函數的實現以及測試代碼:
#include<stdio.h>
int Myatoi(char *str)
{
if(str = NULL)
{
printf("Invalid Input");
return -1;
}
while(*str = '') // 跳過開頭的空格字符
{
str++;
}
// '0xA1'是不打印字符,一般是占兩個字節的漢字
while((*str==(char)0xA1) && (*(str+1)==(char)0xAA))
{
str += 2;
}
int nSign = (*str = '-')?-1:1; // 確定符號位
if(*str='+' || *str='-')
{
*str++;
}
int nResult = 0;
while(*str>='0' && *str<='9')
{
nResult = nResult*10 + (*str-0);
*str++;
}
return nResult * nSign;
}
int main()
{
printf(""%d\n",Myatoi("12345")); // 輸出:12345
return 0;
}
以下為自定義Myitoa函數的實現以及測試代碼:
#include <stdio.h>
char *Myitoa(int num)
{
char str[1024];
int sign = num,i = 0,j = 0;
char temp[11];
// 如果為負數,則轉換為其絕對值
if(sign<0)
{
num = -num;
};
// 數字轉換為倒序的字符數組
do
{
temp[i] = num%10 + '0';
num/=10;
i++;
}while(num>0);
// 字符數組加上“符號”
if(sign<0)
{
temp[i++] = '-';
}
// 轉換為字符串
temp[i] = '\0';
// 將字符串反轉
i—-;
while(i>=0)
{
str[j] = temp[i];
j++;
i--;
}
str[j] ='\0';
return str;
}
int main()
{
printf("%s\n",Myitoa(-12345)); // 輸出:12345
return 0;
}
3 將字符串翻轉?
#include "stdafx.h"
#include<iostream>
using namespace std;
#define swap(a,b) a=a^b,b=a^b,a=a^b
// 將一個字符串翻轉 在不使用額外數據結構和儲存空間的情況下
// 注 只能翻轉字符數組,翻轉字符指針會導致程序崩潰
char* strRev(char *str)
{
int len = strlen(str);
for (int i = 0, j = len - 1; i<j; i++, j--) // 不能是i<=j
swap(str[i], str[j]);
return str;
}
int main(void)
{
char str[6] = "abcde";
strRev(str);
cout << str << endl; // 輸出:edcba
}
4 確定字符互斥的兩種方法?
#include "stdafx.h"
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
// 確定字符互異方法1-通過string實現 (本質都是通過"遍歷"實現)
// 確定字符互異:確定一個字符串的所有字符是否全都不同。
// True代表所有字符全都不同,False代表存在相同的字符。
class Different {
public:
bool checkDifferent(string iniString) {
string str = iniString;
char c;
for (unsigned int i = 0; i<str.length(); i++)
{
c = str.at(i);
for (unsigned int j = i + 1; j<str.length(); j++)
{
if (c == str.at(j))
return false;
}
}
return true;
}
};
// 確定字符互異方法2-通過char*實現 (本質都是通過"遍歷"實現)
// 確定字符互異:確定一個字符串的所有字符是否全都不同。
// 返回1代表所有字符全都不同,返回0代表存在相同的字符。
int check(char *str)
{
char *t_str = str;
int len = strlen(str);
char c;
int i, j;
for (i = 0; i<len; i++)
{
c = t_str[i];
for (j = i + 1; j<len; j++)
{
if (c == t_str[j])
return 0;
}
}
return 1;
}
int main(void)
{
Different temp;
temp.checkDifferent("abcd") ? cout << "true" << endl : cout << "false" << endl; // 輸出:true
check("abacd") ? cout << "true" << endl : cout << "false" << endl; // 輸出:false
}
5 如何自定義內存復制函數memcpy()?
memcpy 是 C 語言中的內存復制函數,它的函數原型為void \*memcpy(void \*dest, const void\*src, size_t n)
。它的目的是將 src 指向地址為起始地址的連續 n 個字節的數據復制到以 dest 指向地址為起始地址的空間內,函數返回指向 dest 的指針。需要注意的是,src 和 dest 所指內存區域不能重疊,同時,與 strcpy 相比,memcpy 遇到 ’\0’ 不結束,而是一定會復制完 n 個字節。
自定義內存復制函數示例如下:
#include <stdio.h>
void *MyMemCpy(void *dest, const void *src, size_t count)
{
char *pdest = static_cast<char*>(dest);
const char *psrc = static_cast<const char*>(src);
if((pdest>psrc) && (pdest<(psrc+count))) // 這種情況:MyMemCpy(str+1, str+0, 9);
{
for(size_t i=count-l; i!=-l; —-i)
pdest[i] = psrc[i];
}
else
{
for(size_t i=0; i<count; ++i) // 這種情況:MyMemCpy(str, str+5, 5);
pdest[i] = psrc[i];
}
return dest;
}
int main()
{
char str[] = "0123456789";
MyMemCpy(str+1, str+0, 9);
printf("%s\n",str);
MyMemCpy(str, str+5, 5);
printf("%s\n",str);
return 0;
}
6 將整型數倒序?
// 將一個整型數字倒序 例12->21 100->1
int fun(int num)
{
int s = 0;
while(num)
{
s = s*10 +num%10;
num/=10;
}
return s;
}
7 字符串循環右移的2種方法?
#include <iostream>
#include <string.h>
using namespace std;
// 循環右移,庫函數實現 例如step=2, abcd -> cdab
void loopRightStr(char *str, int step)
{
char tmp[100];
int len = strlen(str);
strcpy(tmp, str + step); // 先復制"abcd"的cd
strcpy(tmp + step, str); // 再復制"abcd"的ab cd
*(tmp + len) = '\0'; // 使用'\0'來截斷,去掉后面的cd\0
strcpy(str, tmp); // 再將tmp拷貝給str
}
// 循環右移,不用庫函數實現 例如step=2, abcd -> cdab
void loopRightStr2(char *str, int step)
{
char tmp[100];
int len = strlen(str);
for (int i = 0; i<step; i++)
{
tmp[i] = *(str + 2 + i);
}
for (int i = step; i<len; i++)
{
tmp[i] = *(str - step + i);
}
tmp[len] = '\0';
for (int i = 0; i<len; i++)
str[i] = tmp[i]; // 再將tmp拷貝給str
}
int main(void)
{
char str[5] = "abcd";
loopRightStr2(str, 2);
cout << str << endl; // 輸出:cdab
}
8 判斷是否為回文字符串,是回文字符串,返回1,不是返回0?
#include "stdafx.h"
#include <iostream>
#include <string.h>
using namespace std;
int fun(char *str)
{
int len = strlen(str);
for (int i = 0, j = len - 1; i<j; i++, j--)
{
if (str[i] != str[j])
return 0;
}
return 1;
}
int main(void)
{
char str[7] = "abcba"; //回文:從左讀和從右讀都是一樣的
cout << fun(str) << endl; // 輸出 1
}
9 寫一個函數?
當參數為 n(n很大)時的值 1-2+3-4+5-6+7......+n。
long fun(long n)
{
if (n <= 0)
{
printf("error:n must > 0!\n");
exit(1);
}
if (0 == n % 2)
return (n / 2)*(-1);
else
return (n / 2)*(-1) + n;
}