缅甸网站网站代理怎么做,一个专门做破解的网站,苏州高端网站设计定制,上海网站开发建设C/C语言是一种通用的编程语言#xff0c;具有高效、灵活和可移植等特点。C语言主要用于系统编程#xff0c;如操作系统、编译器、数据库等#xff1b;C语言是C语言的扩展#xff0c;增加了面向对象编程的特性#xff0c;适用于大型软件系统、图形用户界面、嵌入式系统等。…C/C语言是一种通用的编程语言具有高效、灵活和可移植等特点。C语言主要用于系统编程如操作系统、编译器、数据库等C语言是C语言的扩展增加了面向对象编程的特性适用于大型软件系统、图形用户界面、嵌入式系统等。C/C语言具有很高的效率和控制能力但也需要开发人员自行管理内存等底层资源对于初学者来说可能会有一定的难度。
6.1.1 封装字符串操作
字符串与整数: 将字符串转为数值可以使用sscanf()函数,将数值转为字符串可以使用sprintf()函数.
#include iostream
#include stringint main(int argc, char* argv[])
{// int - stringchar szBuf[32] { 0 };int number 100;sprintf(szBuf, %d, number);std::cout 字符串: szBuf std::endl;// string - intsscanf(szBuf, %d, number);std::cout 整数: number std::endl;return 0;
}字符串切割: 模拟实现Split()函数对特定字符串使用特定符号进行的切割,切割后的数据分别放入新的数组中.
#include iostream
#include Windows.h
#include string.h// 实现字符串切割
int split(char dst[][80], char* str, const char* spl)
{int n 0;char* result NULL;result strtok(str, spl);while (result ! NULL){strcpy(dst[n], result);result strtok(NULL, spl);}return n;
}int main(int argc,char *argv[])
{char src_string[] what is you name? hello lyshark ?;char dst[10][80];// 以空格进行切割字符串并将结果存入dstint cnt split(dst, src_string, );for (int i 0; i cnt; i){std::cout 切割后: dst[i] std::endl;}return 0;
}字符串分块: 循环将传入的字符串按照指定长度切片处理,切片后返回到一个二维数组中存储.
#include iostream
#include Windows.husing namespace std;// 实现对字符串指定位置进行剪切
char* Cat(char* buffer, int offset, int length)
{char Split[100] { 0 };memset(Split, 0, 100);strncpy(Split, buffer offset, length);return Split;
}// 循环剪切字符串
int CatSplit(char *buf, char len ,OUT char Split[][1024])
{int count 0;// 每次剪切len大小for (int x 0; x strlen(buf); x len){char* ref Cat(buf, x, len);strcpy(Split[count], ref);count 1;}return count;
}int main(int argc, char* argv[])
{char buf[1024] The National Aeronautics and Space Administration;char Split[100][1024] { 0 };// 切割并获取切割计数器int count CatSplit(buf, 100, Split);std::cout 切割次数: count std::endl;// 输出切割计数器for (int x 0; x count; x){std::cout Split[x] std::endl;}return 0;
}字符串过滤: 用户传入一个字符串,以及传入需要过滤的字符,自动过滤掉字符串内的所有过滤字符.
#include iostream
#include windows.h// 删除指定字符
void del_char(char Buffer[], char ch)
{int i, j;for (i 0, j 0; *(Buffer i) ! \0; i){if (*(Buffer i) ch){continue;}else{*(Buffer j) *(Buffer i);j;}}*(Buffer j) \0;
}void del_char_list(char Buffer[], char list[], int list_count)
{for (int x 0; x list_count; x){del_char(Buffer, list[x]);}
}int main(int argc, char* argv[])
{char szBuffer[8192] [ 192.168.1.1 , root , 123456 , 22 ];char del[3] { [,], };// 删除列表中的字符del_char_list(szBuffer, del,3);std::cout 删除后的数据: szBuffer std::endl;return 0;
}字符串替换: 在一个字符串中查找特定字符串,只要找到自动将其替换为新的字符串.
#include iostream
#include string
#include Windows.husing namespace std;// C语言版 实现字符串替换
char* str_replace(char* src, char* rep, char* with)
{char* index;char* result, * tmp, * next;int count 0, len_front;int len_with strlen(with);int len_rep strlen(rep);next src;for (count 0; tmp strstr(next, rep); count){next tmp len_rep;}tmp result (char*)malloc(strlen(src) count * (len_rep - len_with) 1);if (!result)return NULL;while (count--){index strstr(src, rep);len_front index - src;tmp strncpy(tmp, src, len_front) len_front;tmp strcpy(tmp, with) len_with;src len_front len_rep;}strcpy(tmp, src);return result;
}// C版
string replace_all_distinct(string str, const string old_value, const string new_value)
{for (string::size_type pos(0); pos ! string::npos; pos new_value.length()){if ((pos str.find(old_value, pos)) ! string::npos)str.replace(pos, old_value.length(), new_value);elsebreak;}return str;
}int main(int argc, char* argv[])
{char text[128] hello lyshark hello lyshark hello lyshark;char* rep str_replace(text, (char*)lyshark, (char*)abcd);std::cout 替换后的字符串: rep std::endl;// ---------------------------------------------------------string str hello lyshark,hello lyshark, hello,lyshark;string new_str replace_all_distinct(str, world, lyshark);std::cout 替换后的字符串: new_str std::endl;return 0;
}字符串格式化: 利用可变参数列表,实现类似于Python中的format()函数功能,格式化一段字符串.
#include iostream// 格式化字符串
std::string format_string(const char* format, ...)
{std::string::size_type size 1024;std::string buffer(size, \0);char* buffer_p const_castchar*(buffer.data());int expected 0;va_list ap;while (true){va_start(ap, format);expected vsnprintf(buffer_p, size, format, ap);va_end(ap);if (expected -1 expected static_castint(size)){break;}else{if (expected -1)size static_castsize_t(expected 1);elsesize * 2;buffer.resize(size);buffer_p const_castchar*(buffer.data());}}return std::string(buffer_p, expected 0 ? expected : 0);
}// 可变参数
void print_args(int count, ...)
{va_list arg_ptr;va_start(arg_ptr, count);for (int x 0; x count; x){int value va_arg(arg_ptr, int);std::cout 下标: x 数值: [ value ] std::endl;}va_end(arg_ptr);
}int main(int argc,char *argv[])
{// 输出元素数print_args(9, 1, 2, 3, 4, 5, 6, 7, 8, 9);// 格式化并输出for (int x 0; x 1000; x){std::string ref format_string(address 192.168.1.%d -- port %d, x, x10);std::cout 生成地址: ref std::endl;}return 0;
}字符串去空格: 函数接收字符串指针,并循环去除该字符串中左右两端的空格,回写到原空间.
#include iostream
#include stringusing namespace std;// 去除字符串首尾的空格
bool trim(char* szStr)
{int i 0, j 0, iFirst -1, iLast -1;int iLen strlen(szStr);char szTemp[256] { 0 };// 从前往后遍历,获取第一个不为 空格 的下标for (i 0; i iLen; i){if ( ! szStr[i]){iFirst i;break;}}// 从后往前遍历,获取第一个不为 空格 的下标for (i (iLen - 1); 0 i; i--){if ( ! szStr[i]){iLast i;break;}}// 字符串全为 空格if (-1 iFirst || -1 iLast){return false;}// 获取去除 空格 部分for (i iFirst; i iLast; i){szTemp[j] szStr[i];j;}szTemp[j] \0;strcpy(szStr, szTemp);return true;
}int main(int argc, char* argv[])
{char szBuffer[4096] hello lyshark ;bool ref trim(szBuffer);std::cout 去空格后: szBuffer std::endl;return 0;
}字符串与HEX互转: 将一段字符串转为一段十六进制数(字符串格式),或将十六进制数转为字符串.
#include iostream
#include Windows.h// 将十六进制字符 转 十进制
int hexCharToValue(const char ch)
{int result 0;if (ch 0 ch 9){result (int)(ch - 0);}else if (ch a ch z){result (int)(ch - a) 10;}else if (ch A ch Z){result (int)(ch - A) 10;}else{result -1;}return result;
}// 将十进制整数 转 字符
char valueToHexCh(const int value)
{char result \0;if (value 0 value 9){// 48为ascii编码的0字符编码值result (char)(value 48);}else if (value 10 value 15){// 减去10则找出其在16进制的偏移量,65为ascii的A的字符编码值result (char)(value - 10 65);}return result;
}// 将一段字符串转换为十六进制
int strToHex(char* ch, char* hex)
{int high, low;int tmp 0;if (ch NULL || hex NULL)return -1;if (strlen(ch) 0)return -2;while (*ch){tmp (int)*ch;// 取字符的高4位high tmp 4;// 取字符的低4位low tmp 15;// 先写高字节*hex valueToHexCh(high);// 其次写低字节*hex valueToHexCh(low);ch;}*hex \0;return 0;
}// 将一段十六进制转为字符串
int hexToStr(char* hex, char* ch)
{int high, low;int tmp 0;if (hex NULL || ch NULL)return -1;if (strlen(hex) % 2 1)return -2;while (*hex){high hexCharToValue(*hex);if (high 0){*ch \0;return -3;}// 指针移动到下一个字符上hex;low hexCharToValue(*hex);if (low 0){*ch \0;return -3;}tmp (high 4) low;*ch (char)tmp;hex;}*ch \0;return 0;
}// 将十六进制字符串 转 byte字节码
int hexChartoByte(char* hex, char* byte)
{int i, n 0;for (i 0; hex[i]; i 2){if (hex[i] A hex[i] F)byte[n] hex[i] - A 10;elsebyte[n] hex[i] - 0;if (hex[i 1] A hex[i 1] F)byte[n] (byte[n] 4) | (hex[i 1] - A 10);elsebyte[n] (byte[n] 4) | (hex[i 1] - 0);n;}return n;
}// 将单一字符 转 ascii 码
unsigned char ChartoAscii(const unsigned char cha)
{unsigned char ascii;if ((cha 0x0A) (cha 0x0F)){ascii cha A - 10;}else{ascii cha 0;}return ascii;
}int main(int argc, char* argv[])
{char hex[1024] { 0 };char str[1024] { 0 };char byte[1024] { 0 };int ref 0;// 实现字符串与十六进制互转ref strToHex((char*)hello lyshark, hex);if (ref 0){std::cout 字符串 - Hex: hex std::endl;}ref hexToStr(hex, str);if (ref 0){std::cout Hex - 字符串: str std::endl;}ref hexChartoByte(hex, byte);if (ref ! 0){std::cout Hex - Byte: byte std::endl;}std::cout 字符 - Ascii: ChartoAscii(12) std::endl;
}字符串实现拼接: 将单独的字符串拼接为连续的字符串,类似于strcat()功能实现.
#include Windows.h
#include iostream// 组合字符串
char *join(const char *a, const char *b)
{// char *c (char *)ExAllocatePool(NonPagedPool, strlen(a) strlen(b) 1);char *c (char *)malloc(strlen(a) strlen(b) 1);if (c NULL){return NULL;}char *tempc c;while (*a ! \0){*c *a;}while ((*c *b) ! \0) { ; }return tempc;
}int main(int argc, char *argv[])
{char * HttpBuffer;char DataBuffer[128] {0};char PostData[128] { 0 };HttpBuffer join(POST /, www.lyshark.com);HttpBuffer join(HttpBuffer, HTTP/1.1\n);HttpBuffer join(HttpBuffer, Host: );HttpBuffer join(HttpBuffer, www.baidu.com);HttpBuffer join(HttpBuffer, \n);HttpBuffer join(HttpBuffer, Proxy-Connection: keep-alive\n);HttpBuffer join(HttpBuffer, User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0\n);strcpy(PostData, {a:1,b:2});sprintf(DataBuffer, Content-Length: %d\n, (int)strlen(PostData));HttpBuffer join(HttpBuffer, DataBuffer);HttpBuffer join(HttpBuffer, Content-Type: application/x-www-form-urlencoded\n\n);HttpBuffer join(HttpBuffer, PostData);printf(%s \n, HttpBuffer);return 0;
}字符串实现模拟字典: 通过使用链表结构模拟实现了Python语言中的字典数据结构的基本操作,与字典操作保持一致.
#include iostream
#include stdlib.h
#include string.h
#include errno.h static int N1 30;
static int N2 30;typedef struct Data { char key[30]; char value[30]; }Data;
typedef struct Dict
{Data data;struct Dict* next;size_t size;
}Dict;errno_t append(Dict* dict, const char* key, const char* value);
errno_t repair(Dict* dict, const char* key, const char* value);// 初始化
Dict* __init__(Dict* dict)
{if (dict NULL){dict (Dict*)calloc(1, sizeof(Dict));dict-size 0;}elsedict-next NULL;return dict;
}// 删除元素
void clear(Dict* dict, const char* key)
{Dict* q dict;Dict* p dict-next;while (p ! NULL){if (strcmp((p-data).key, key) 0){q-next p-next;dict-size - 1;free(p);return;}q p;p p-next;}
}// 按主键查找Key是否存在
Dict* _findkey(Dict* dict, const char* key)
{Dict* p dict-next;while (p ! NULL){if (strcmp((p-data).key, key) 0){return p;}p p-next;}return NULL;
}// 将记录按姓名字母升序插入链表
void _insert_n(Dict* dict, Dict* q)
{Dict* p dict;while (p-next ! NULL strcmp((p-next-data).key, (q-data).key) 0){p p-next;}q-next p-next;p-next q;dict-size 1;
}// 释放整个链表空间
void __destroy__(Dict* dict)
{Dict* p dict;while (p-next ! NULL){p p-next;free(dict);dict p;}if (p ! NULL)free(p);
}// 添加字典元素
errno_t append(Dict* dict, const char* key, const char* value)
{Dict* p, * r; _set_errno(0);if ((r _findkey(dict, key)) NULL){// 判断记录是否已存在// 申请Dict空间并初始化p (Dict*)calloc(1, sizeof(Dict)); if (p ! NULL){strcpy_s((p-data).key, N1, key);strcpy_s((p-data).value, N2, value);_insert_n(dict, p);}}else{repair(dict, key, value);}return errno;
}// 修改字典元素
errno_t repair(Dict* dict, const char* key, const char* value)
{Dict* r, * p; p dict;_set_errno(0);if ((r _findkey(dict, key)) ! NULL){strcpy_s(r-data.key, N1, key);strcpy_s(r-data.value, N2, value);}else{append(dict, key, value);}return errno;
}// 获取字典元素
const char* get(Dict* dict, const char* key)
{Dict* p dict-next;while (p ! NULL){if (strcmp((p-data).key, key) 0){return p-data.value;}p p-next;}return ;
}// 设置字典
void set(Dict* dict, const char* key, const char* value)
{repair(dict, key, value);
}// 判断key是否存在
bool existkey(Dict* dict, const char* key)
{Dict* p dict-next;bool result 0;while (p ! NULL){if (strcmp((p-data).key, key) 0){result 1; return p;}p p-next;}return result;
}// 显示所有记录
void view(Dict* dict)
{int i 0;Dict* p dict-next;printf({);while (p ! NULL){printf(size:%d %s:%s,, dict-size, (p-data).key, (p-data).value);p p-next;i;}printf(}\n);
}int main(int argc, char *argv[])
{Dict* dict NULL;dict __init__(dict);// 追加键值对append(dict, address, 192.168.1.1);append(dict, username, root);append(dict, password, 1233);append(dict, port, 22);// 替换预设值repair(dict, password, 123456);set(dict, password, 123456789);// 判断并输出if (existkey(dict, address)){std::cout 获取数据: get(dict, address) std::endl;std::cout 获取数据: get(dict, password) std::endl;}// 清理记录clear(dict, address);clear(dict, username);clear(dict, password);clear(dict, port);__destroy__(dict);return 0;
}字符串URL编码与解码: 将一段URL字符串进行编码与解码的函数过程实现.
#include iostream// 编码URL
std::string encode_url(const char* url, size_t url_length, bool space2plus)
{static char hex[] 0123456789ABCDEF;std::string result(url_length * 3 1, \0);int i 0;while (*url ! \0){char c *url;if ( c){if (space2plus){result[i] ;}else{// 新标准将空格替换为加号result[i 0] %;result[i 1] 2;result[i 2] 0;i 3;}}else if ((c 0 c 9) ||(c a c z) ||(c A c Z) ||(c -) || (c _) ||(c .) || (c ~)){// RFC 3986标准定义的未保留字符 (2005年1月)result[i] c;}else{// 有符号的c值可能是负数result[i 0] %;result[i 1] hex[static_castunsigned char(c) / 16];result[i 2] hex[static_castunsigned char(c) % 16];i 3;}}result.resize(i);return result;
}// 解码URL
std::string decode_url(const char* encoded_url, size_t encoded_url_length)
{std::string result(encoded_url_length 1, \0);int i 0;while (*encoded_url ! \0){char c *encoded_url;if (c ){result[i] ;}else if (c ! %){result[i] c;}else{if (!isxdigit(encoded_url[0]) ||!isxdigit(encoded_url[1])){result[i] %;}else{char hex[3];hex[0] encoded_url[0];hex[1] encoded_url[1];hex[2] \0;char x strtol(hex, NULL, 16);result[i] x;encoded_url 2;}}}result.resize(i);return result;
}int main(int argc, char* argv[])
{const char* szUrl https://www.lyshark.com/index.php?uid102;std::string encode encode_url(szUrl, strlen(szUrl), false);std::cout 编码后: encode std::endl;std::string decode decode_url(encode.c_str(), strlen(encode.c_str()));std::cout 解码后: decode std::endl;return 0;
}字符串编码互相转换: 在C语言中通过多种方式实现wstring/wchar与string字符串之间的相互转换.
#include iostream
#include Windows.h
#include comutil.h
#include codecvt#pragma comment(lib, comsuppw.lib)using namespace std;// 将string转换成wstring
wstring string2wstring(string str)
{wstring result;//获取缓冲区大小并申请空间缓冲区大小按字符计算 int len MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);TCHAR* buffer new TCHAR[len 1];// 多字节编码转换成宽字节编码 MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);buffer[len] \0;// 删除缓冲区并返回值 result.append(buffer);delete[] buffer;return result;
}// 将wstring转换成string
string wstring2string(wstring wstr)
{string result;//获取缓冲区大小并申请空间缓冲区大小事按字节计算的int len WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);char* buffer new char[len 1];//宽字节编码转换成多字节编码WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);buffer[len] \0;//删除缓冲区并返回值result.append(buffer);delete[] buffer;return result;
}// 采用ATL封装_bstr_t wstring 转string
string ws2s(const wstring ws)
{_bstr_t t ws.c_str();char* pchar (char*)t;string result pchar;return result;
}// 采用ATL封装_bstr_t string 转wstring
wstring s2ws(const string s)
{_bstr_t t s.c_str();wchar_t* pwchar (wchar_t*)t;wstring result pwchar;return result;
}// 将 wchar string
void WcharToString(std::string szDst, wchar_t* wchar)
{wchar_t* wText wchar;DWORD dwNum WideCharToMultiByte(CP_OEMCP, NULL, wText, -1, NULL, 0, NULL, FALSE);char* psText;// psText 为 char* 的临时数组 作为赋值给std::string的中间变量psText new char[dwNum];WideCharToMultiByte(CP_OEMCP, NULL, wText, -1, psText, dwNum, NULL, FALSE);szDst psText;delete[]psText;
}int main(int argc, char* argv[])
{std::string stringA(hello lyshark);std::wstring wstringA(Lhello lyshark);// 使用原生API进行转换std::wcout string - wstring: string2wstring(stringA) std::endl;std::cout wstring - string: wstring2string(wstringA) std::endl;// 使用ATL进行转换std::wcout string - wstring: s2ws(stringA) std::endl;std::cout wstring - string: ws2s(wstringA) std::endl;// 使用C标准库转换wstring_convertcodecvtwchar_t, char, mbstate_t converter(new codecvtwchar_t, char, mbstate_t(CHS));string narrowStr converter.to_bytes(wstringA);wstring wstr converter.from_bytes(narrowStr);std::cout wstring - string: narrowStr std::endl;wcout.imbue(locale(chs));std::wcout string - wstring: wstr std::endl;// 将wchar转为stringWCHAR selfFile[MAX_PATH];//获取当前进程路径GetModuleFileName(NULL, selfFile, MAX_PATH);// 当前程序存放路径string Current_Path;WcharToString(Current_Path, selfFile);std::cout wchar - string: Current_Path std::endl;return 0;
}解析字符串字典: 与模拟Python字典不同,如下是通过C直接实现了解析字符串格式的文本为字典,能够直接当字典解析.
#include iostream
#include string
#include vector// 切割字符串
void SplitString(const std::string s, std::vectorstd::string vect, const std::string c)
{std::string::size_type pos1, pos2;pos2 s.find(c);pos1 0;while (std::string::npos ! pos2){vect.push_back(s.substr(pos1, pos2 - pos1));pos1 pos2 c.size();pos2 s.find(c, pos1);}if (pos1 ! s.length())vect.push_back(s.substr(pos1));
}// 删除左右两边空格
void Del_Trim(std::string s)
{if (s.empty()){return;}s.erase(0, s.find_first_not_of( ));s.erase(s.find_last_not_of( ) 1);
}// 删除所有空格
void Del_Space(std::string res)
{int r res.find(\r\n);while (r ! std::string::npos){if (r ! std::string::npos){res.replace(r, 1, );r res.find(\r\n);}}res.erase(std::remove_if(res.begin(), res.end(), std::isspace), res.end());
}// 删除字符串中的指定符号
void Del_Char(std::string res ,char ch)
{int r res.find(ch);while (r ! std::string::npos){if (r ! std::string::npos){res.replace(r, 1, );r res.find(ch);}}res.erase(std::remove_if(res.begin(), res.end(), std::isspace), res.end());
}// 传入key返回value
std::string get_value(std::string szDict, std::string key)
{// 去掉空格Del_Space(szDict);// 去掉特殊字符Del_Char(szDict, \);Del_Char(szDict, {);Del_Char(szDict, });// 先使用逗号切割第一次std::vectorstd::string one_split;SplitString(szDict, one_split, ,);for (int x 0; x one_split.size(); x){// 循环切割第二次std::vectorstd::string two_split;SplitString(one_split[x], two_split, :);// std::cout key two_split[0] value two_split[1] std::endl;// 寻找key所对应的valueif (strcmp(two_split[0].c_str(), key.c_str()) 0){return two_split[1];}}return None;
}int main(int argc, char* argv[])
{std::string szDict {address : 192.168.1.1 , username : root , password : 123123 , port: 22};std::string address_value get_value(szDict, address);std::cout 返回地址: address_value std::endl;std::string username_value get_value(szDict, username);std::cout 返回用户: username_value std::endl;return 0;
}字符串正反向对比与截取: 实现了字符串反向对比以及截取指定位置字符串对比功能.
#include windows.h
#include iostream// 将字符串逆序
char* reverse(char str[])
{int n strlen(str);int i;char temp;for (i 0; i (n / 2); i){temp str[i];str[i] str[n - i - 1];str[n - i - 1] temp;}return str;
}// 从字符串src中的count位置出开始复制,复制长度为len
bool strnrcpy(char* src, char dst, int count, int len)
{int str strlen(src);std::cout str std::endl;for (int x 0; x strlen(src); x){if (x count){strncpy(dst , src count 1, len 1);break;}}return true;
}int main(int argc, char *argv[])
{char szBuf[1024] Internet Explorer;char szRef[1024] { 0 };// 反向对比字符串if (strcmp(reverse(szBuf), rerolpxE tenretnI) 0){std::cout 先逆序排列,在对比 std::endl;}// 字符串提取位置并对比reverse(szBuf);bool ref strnrcpy(szBuf, *szRef, 8, 8);if (ref true){std::cout 提取字符串: szRef std::endl;if (strcmp(szRef, Explorer) 0){std::cout 数据一致 std::endl;}}return 0;
}6.1.2 复制与剪切函数
memset 内存填充: 设置某个范围内每字节的值通常用来清空结构体或者清空某块内存。
#include stdio.h
#include malloc.h// 标准库
void* memset(char* s, int c, size_t n)
{const unsigned char uc c;char* su;for (su s; 0 n; su, --n)*su uc;return (s);
}int main(int argc, char* argv[])
{// 获取10字节的内存char* p (char*)malloc(sizeof(char) * 10);// 将该10字节内存全部初始化为0memset(p, 0, sizeof(char) * 10);return 0;
}memcpy 内存拷贝: 函数memcpy从s2指向的对象中复制n个字符到s1指定的对象中。
#include iostream
#include string.h// 标准库
void* memcpy(char* s1, const char* s2, size_t n)
{char* su1;const char* su2;for (su1 s1, su2 s2; 0 n; su1, su2, --n){*su1 *su2;}return s1;
}// 自实现
void* _memcpy(char* s1, char* s2, size_t n)
{char* start, * src;start s1;src s2;while (n 0 (*start *src) ! \0)n--;while (n-- 0)*start \0;*start \0;return s1;
}int main(int argc, char const* argv[])
{char text[20] {0};std::cout 标准库: text 地址: memcpy(text, hello lyshark, 13) std::endl;std::cout 自实现: text 地址: _memcpy(text, (char *)hello lyshark, 13) std::endl;return 0;
}memmove 内存移动: 函数memmove从s2指向的对象中复制n个字符串到s1指向的对象中。
#include iostream
#include string.h// 标准库
void* memmove(char* s1, const char* s2, size_t n)
{char* sc1;const char* sc2;sc1 s1;sc2 s2;// 如果 sc1 的地址比 sc2 要低并且两者相处不足 n 字节if (sc2 sc1 sc1 sc2 n){// 逆向复制for (sc1 n, sc2 n; 0 n; --n){*--sc1 *--sc2;}}else{// 正向复制for (; 0 n; --n){*sc1 *sc2;}}return s1;
}// 自实现
void* _memmove(char* s1, const char* s2, size_t n)
{char* su1;const char* su2;int i;if (s1 s2 s2 - s1 n){// 加了 n 忘记减一了for (su1 s1 n, su2 s2 n; n 0; --n, --su1, --su2){*su1 *su2;}}else{// i 多余了for (i 0, su1 s1, su2 s2; i n; i, su1, su2){*su1 *su2;}}return s1;
}int main(int argc, char const* argv[])
{char text[20] {0};std::cout 标准库: text 地址: memmove(text, hello lyshark, 13) std::endl;std::cout 自实现: text 地址: _memmove(text, (char *)hello lyshark, 13) std::endl;return 0;
}strcpy 字符串拷贝: 把s2指向的串包括终止的空字符复制到s1指向的数组中。
#include stdio.h// 标准库
char* strcpy(char* s1, const char* s2)
{char* s s1;for (s s1; (*s *s2) ! \0; );return s1;
}// 自实现
char* _strcpy(char* s1, const char* s2)
{char* start s1;while (*s1 *s2);return start;
}int main(int argc, char const* argv[])
{char text[20] {0};strcpy(text, hello lyshark);return 0;
}strncpy 字符串前N字节拷贝: 把s2指向的串包括终止的空字符复制到s1指向的数组中。
#include stdio.h// 标准库
char* (strncpy)(char* s1, const char* s2, size_t n)
{char* s;// 当n不为0 且s2为拷贝完时复制字符过去for (s s1; 0 n *s2 ! \0; s)*s *s2;// 若n有多出则补零for (; 0 n; --n)*s \0;return s1;
}// 自实现
char* _strncpy(char* s1, const char* s2, size_t n)
{char* start s1, count 0;while ((count n) (*s1 *s2)){count, s1, s2;// printf(第%d个 已拷贝n, count);}while (count n){*s1 \0;// printf(第%d个 已补零n, count);}return start;
}int main(int argc, char const* argv[])
{char text[20] {0};strncpy(text, hello lyshark,5);_strncpy(text, hello lyshark, 6);return 0;
}strcat 字符串连接: 函数strcat把s2指向的串包括终止的空字符的副本添加到s1指向的串的末尾。
#include stdio.h// 标准库
char* strcat(char* s1, const char* s2)
{char* s;// 指针移动到s1的结尾for (s s1; *s ! \0; s);// 如果s2未结尾则拷贝for (; (*s *s2) ! \0; s, s2);return (s1);
}// 自实现
char* _strcat(char* s1, const char* s2)
{char* start s1;while (*s1)s1;while (*s1 *s2);return start;
}int main(int argc, char const* argv[])
{char text[20] hello ;printf(%s \n, _strcat(text, lyshark));return 0;
}strncat 字符串连接前N个字节: 函数strncat从s2指向的数组中将最多n个字符空字符及其后面的字符不添加添加到s1指向的串的末尾。
#include stdio.h// 标准库
char* strncat(char* s1, const char* s2, size_t n)
{char* s;// 指针移动到s1的结尾for (s s1; *s ! \0; s);// 如果s2未结尾则拷贝for (; 0 n *s2 ! \0; --n)*s *s2;// 字符串s1结尾补\0*s \0;return (s1);
}// 自实现
char* _strncat(char* s1, const char* s2, size_t n)
{char* start s1;while (*s1)s1;while ((0 n--) (*s1 *s2)){;// printf(第%d个 已赋值n, n);}while (0 n--){*s1 \0;// printf(第%d个 已补零n, n);}return start;
}int main(int argc, char const* argv[])
{char text[20] hello ;printf(%s \n, strncat(text, lyshark, 5));printf(%s \n, _strncat(text, lyshark,8));return 0;
}6.1.3 字符串比较函数
strlen 字符串取长度: 字符串长度获取函数用于获取一段以0结尾的字符串长度。
#include stdio.h// 标准库
int strlen(const char* s)
{const char* sc;for (sc s; *sc ! \0; sc);return (sc - s);
}// 自实现
int _strlen(const char* dest)
{const char* start dest;while (*dest)dest;return (dest - start);
}int main(int argc, char const* argv[])
{printf(%d, _strlen(hello lyshark));return 0;
}strcmp 字符串比较: 字符串比较函数用于比较两个字符串的区别。
#include stdio.h// 标准库
int strcmp(const char* s1, const char* s2)
{for (; *s1 *s2; s1, s2)if (*s1 \0)return (0);return ((*(unsigned char*)s1 *(unsigned char*)s2) ? -1 : 1);
}// 自实现
int _strcmp(const char* dest, const char* src)
{int res 0;while (res 0 *src ! \0)res *dest - *src;return res;
}int main(int argc, char const* argv[])
{char text[20] hello ;if (_strcmp(text, hello ) 0){printf(相等);}return 0;
}strncmp 比较前N个字符: 比较两个字符串的前n个字符。
#include stdio.h// 标准库
int strncmp(const char* s1, const char* s2, size_t n)
{for (; 0 n; s1, s2, --n)if (*s1 ! *s2)return ((*(unsigned char*)s1 *(unsigned char*)s2) ? -1 : 1);else if (*s1 \0)return 0;return 0;
}// 自实现
int _strncmp(const char* s1, const char* s2, size_t n)
{const char* dest s1, * src s2;while (n-- 0 *dest ! \0)if (*dest - *src)return *dest - *src;return 0;
}int main(int argc, char const* argv[])
{char text[20] hello ;if (_strncmp(text, he, 2) 0){printf(相等);}return 0;
}memcmp 内存字节比较: 该函数与strcmp类似,区别在于memcmp不会检查字符串是否到结束。
#include stdio.h// 标准库
int memcmp(const char* s1, const char* s2, size_t n)
{const char* su1, * su2;for (su1 s1, su2 su2; 0 n; su1, su2, --n)if (*su1 ! *su2)return ((*su1 *su2) ? -1 : 1);return 0;
}// 自实现
int _memcmp(const char* s1, const char* s2, size_t n)
{const char* dest s1, * src s2;while (n-- 0)if (*dest - *src)return *dest - *src;return 0;
}int main(int argc, char const* argv[])
{char text[20] hello ;if (_memcmp(text, he, 2) 0){printf(相等);}return 0;
}strcoll/strxfrm 中文字符串比较: 该函数主要实现中文字符串的比较。
与locale.h本地库有关的字符串比较函数在开始比较之前会按照特定的方式转换字符串然后在进行比较。
#include stdio.h
#include string.h
#include limits.h#define ST_CH 0x00ff
#define ST_STATE 0x0f00
#define ST_STOFF 8
#define ST_FOLD 0x8000
#define ST_INPUT 0x4000
#define ST_OUTPUT 0x2000
#define ST_ROTATE 0x1000
#define _NSTATE 16/* 类型定义 */
typedef struct {const unsigned short* _Tab[_NSTATE];
} _Statab;/* 声明*/
extern _Statab _Costate, _Mbstate, _Wcstate;/* type definnitions 类型定义 */
typedef struct {unsigned char _State;unsigned short _Wchar;
} _Cosave;/* declarations 声明 */
size_t _Strxfrm(char*, const unsigned char**, size_t, _Cosave*);/* 设置默认为 0 的本地配置项 */
_Statab _Costate, _Mbstate, _Wcstate;// _Cosave 存储状态信息
size_t _Strxfrm(char* sout, const unsigned char** psin,size_t size, _Cosave* ps)
{// 翻译字符串到可校对的格式char state ps-_State;int leave 0;int limit 0;int nout 0;const unsigned char* sin *psin;// 宽字节字符累加器unsigned short wc ps-_Wchar;for (; ; ){// 执行状态转换unsigned short code;const unsigned short* stab;if (_NSTATE state|| (stab _Costate._Tab[state]) NULL|| (_NSTATE * UCHAR_MAX) limit|| (code stab[*sin] 0))break;state (code ST_STATE) ST_STOFF;if (code ST_FOLD)wc wc ~UCHAR_MAX | code ST_CH;if (code ST_ROTATE)wc wc CHAR_BIT UCHAR_MAX | wc CHAR_BIT;if (code ST_OUTPUT ((sout[nout] code ST_CH ? code : wc) \0|| size nout))leave 1;if (code ST_INPUT)if (*sin ! \0)sin, limit 0;elseleave 1;if (leave){// 现在返回*psin sin;ps-_State state;ps-_Wchar wc;return nout;}}// 错误返回sout[nout] \0;*psin sin;ps-_State _NSTATE;return nout;
}定义好以上转换过程,就可以进行比较了,函数_strcoll()主要用于比较完整中文字符串,而_strxfrm()则用于比较指定的前几个中文字符。
typedef struct
{char buf[32];const unsigned char* s1, * s2, * sout;_Cosave state;
} Sctl;static size_t getxfrm(Sctl* p)
{size_t i;do{p-sout (const unsigned char*)p-buf;i _Strxfrm(p-buf, p-s1, sizeof(p-buf), p-state);if (0 i p-buf[i - 1] \0)return (i - 1);else if (*p-s1 \0)p-s1 p-s2;} while (i 0);return i;
}// 比较全部中文字符串
int _strcoll(const char* s1, const char* s2)
{size_t n1, n2;Sctl st1, st2;static const _Cosave initial { 0 };st1.s1 (const unsigned char*)s1;st2.s2 (const unsigned char*)s1;st1.state initial;st2.s1 (const unsigned char*)s2;st2.s2 (const unsigned char*)s2;st2.state initial;for (n1 n2 0; ; ){int ans;size_t n;if (n1 0)n1 getxfrm(st1);if (n2 0)n2 getxfrm(st2);n n1 n2 ? n1 : n2;if (n 0)return (n1 n2 ? 0 : 0 n2 ? -1 : 1);else if ((ans memcmp(st1.sout, st2.sout, n)) ! 0)return ans;st1.sout n, n1 - n;st2.sout n, n2 - n;}
}// 指定比较行
size_t _strxfrm(char* s1, const char* s2, size_t n)
{size_t nx 0;const unsigned char* s (const unsigned char*)s2;_Cosave state { 0 };while (nx n){// 转化 并 传递size_t i _Strxfrm(s1, s, n - nx, state);s1 i, nx i;if (0 i s1[-1] \0)return nx - 1;else if (*s \0)s (const unsigned char*)s2;}for (; ; ){char buf[32];size_t i _Strxfrm(buf, s, sizeof(buf), state);nx i;if (0 i buf[i - 1] \0)return nx - 1;else if (*s \0)s (const unsigned char*)s2;}
}int main(int argc, char *argv[])
{char hi[] 中文;if (_strcoll(hi, 中文) 0){printf(相等);}if (_strxfrm(hi, 中, 1) 0){printf(相等);}return 0;
}6.1.4 字符串查找函数
memchr 内存中查找: 内存中查找参数void *适合各种数据类型不过只能查找一个字节。
#include stdio.h
#include string.h// 标准库
void *memchr(const void *s, int c, size_t n)
{const unsigned char uc c;const unsigned char *su;for (su s; 0 n; su, --n)if (*su uc)return ((void *)su);return (NULL);
}// 自实现
void *_memchr(const void *s, int c, size_t n)
{const unsigned char *pstr s;const unsigned char search (unsigned char)c;while(n-- 0){if (*pstr search){return (void *)pstr;}pstr;}return NULL;
}int main(int argc, char *argv[])
{char *p;p _memchr(hello lyshark, w, 8);printf(%sn, p);return 0;
}strchr 字符串中查找: 字符串中查找字符并返回这个字符第一次出现的地址。
#include stdio.h
#include string.h// 标准库
char *strchr(const char *s, int c)
{const char ch c;for (; *s ! \0; s)if (*s \0)return NULL;return ((char *)s);
}// 自实现
char *_strchr(const char *s, int c)
{const unsigned char *pstr s;const unsigned char search (unsigned char)c;while(*pstr ! \0){if (*pstr search){return (char *)pstr;}pstr;}return NULL;
}int main(int argc, char *argv[])
{char *p;p _strchr(hello lyshark, o);printf(%s, p);return 0;
}strrchr 字符串中反向查找: 字符串反向查找字符返回这个字符最后一次出现的位置。
#include stdio.h
#include string.h// 标准库
char *strrchr(const char *s, int c)
{const char ch c;const char *sc;for (sc NULL; ; s){if (*s ch)sc s;if (*s \0)return ((char *)sc);}
}// 自实现
char *_strrchr(const char *s, int c)
{const unsigned char *pstr NULL, search (unsigned char)c;do{if (*s search){pstr s;}} while (*s);return (char *)pstr;
}int main(int argc, char *argv[])
{char *p;p strrchr(hello lyshark, o);printf(%s, p);return 0;
}strstr 字符中查找字符串: 字符串中查找字符串如果能找到则返回其地址找不到则返回NULL。
#include stdio.h
#include string.h// 标准库
char *strstr(const char *s1, const char *s2)
{if(*s2 \0)return ((char *)s1);for( ; (s1 strchr(s1, *s2)) ! NULL; s1){const char *sc1, *sc2;for(sc1 s1, sc2 s2; ; )if(*sc2 \0)return ((char *)s1);else if(*sc1 ! *sc2)break;}return NULL;
}// 自实现
char *_strstr(const char *s1, const char *s2)
{while ( (s1 strchr(s1, *s2)) ! NULL )if(strcmp(s1, s2) 0)return (char *)s1;elses1;return NULL;
}int main(int argc, char *argv[])
{printf(%s, _strstr(that this think, think));return 0;
}strtok 根据标识查找字符串: 通过标识来查找字符串需要注意的是这个会修改原来字符串的值。
#include stdio.h
#include string.hchar * strtok(char *s1, const char *s2)
{char *sbegin, *send;static char *ssave ;sbegin s1 ? s1 : ssave;// printf(1.sbegin: %sn, sbegin);// printf(2.strspn(sbegin, s2): %dn, strspn(sbegin, s2));sbegin strspn(sbegin, s2);if (*sbegin \0){ssave ;return NULL;}// printf(3.sbegin: %sn, sbegin);send sbegin strcspn(sbegin, s2);// printf(4.sbegin: %sn, sbegin);// printf(5.send: %sn, send);if (*send ! \0)*send \0;ssave send;// printf(6.send: %sn, send);return (sbegin);
}int main(int argc, char *argv[])
{char input[] program,hello,world;char *p;/* 截取到第一个标识符之前 */p strtok(input, e);if(p){printf(%sn, p);}/* 截取第一个标识符之后一段 */p strtok(NULL, e);if(p){printf(%sn, p);}// 源字符串被截断printf(最后input : %s, input);return 0;
}strspn 范围之内查找: 字符串范围查找在s1中找s2从s1的开头依次与s2比较返回第一个与s2不同的字符下标。
#include string.h
#include stdio.h// 函数说明 strspn 返回字符串中第一个不在指定字符串中出现的字符下标
size_t _strspn(const char *s1,const char *s2)
{const char *sc1 s1, *sc2 s2;for(sc1 s1, sc2 s2; *sc1 ! \0; sc1, sc2)if (*sc2 \0)return (sc1 - s1);else if (*sc1 *sc2)continue;elsebreak;return sc1 - s1;
}size_t strspn(const char *s1,const char *s2)
{const char *sc1, *sc2;printf(sc2: [%s] , s2);for(sc1 s1; *sc1 ! \0; sc1)for (sc2 s2; ; sc2)if (*sc2 \0)return (sc1 - s1);else if (*sc1 *sc2)break;return (sc1 - s1);
}int main(int argc, char const *argv[])
{char *str what do you think about this this program? 1;printf(%dn, _strspn(str,w));printf(%dn, _strspn(str,what));printf(%dn, _strspn(str,what ));printf(%dn, _strspn(str,what d));printf(%dn, _strspn(str,what do));printf(%dn, _strspn(str,what do ));printf(%dn, _strspn(str,what do y));printf(%dn, _strspn(str,what do yo));printf(%dn, _strspn(str,what do you));printf(%dn, _strspn(str,you));printf(%dn, _strspn(str,1234567890));return 0;
}strcspn 范围之外查找: 在字符串s1中搜寻与s2中字符的第一个相同字符包括结束符NULL返回这个字符在S1中第一次出现的位置。
#include stdio.h
#include string.h// 标准库
size_t strcspn(const char *s1,const char *s2)
{const char *sc1, *sc2;for (sc1 s1; *sc1 ! \0; sc1)for(sc2 s2; *sc2 ! \0; sc2)if (*sc1 *sc2)return (sc1 - s1);// 返回NULL即字符串结束return (sc1 - s1);
}int main(int argc, char *argv[])
{char *str Linux was first developed for 386/486-based pcs. ;printf(字符串长度为 %dn, strlen(str));printf(%dn, strcspn(str, ));printf(%dn, strcspn(str, /-));printf(%dn, strcspn(str, 1234567890));printf(%dn, strcspn(str, ));return 0;
}strpbrk可以理解为找到目标(string)中的字符后中断(break)并返回其地址(pointer)其功能与strcspn相同区别只是strpbrk返回的是地址。
#include stdio.h
#include string.h/*依次检验字符串s1中的字符当被检验字符在字符串s2中也包含时则停止检验并返回该字符地址空字符NULL不包括在内。
*/// 标准库
char * strpbrk(const char * s1,const char * s2)
{const char *sc1, *sc2;for(sc1 s1; *sc1 !\0; sc1)for(sc2 s2; *sc2 !\0; sc2)if(*sc1 *sc2)return ((char *)sc1);return NULL;
}int main(int argc, char *argv[])
{char *s1Welcome To Beijing;char *s2BIT;char *p;p strpbrk(s1,s2);if(p)printf(%sn,p);elseprintf(Not Found!n);p strpbrk(s1, Daj);if(p)printf(%s,p);elseprintf(Not Found!n);return 0;
}本文作者 王瑞 本文链接 https://www.lyshark.com/post/feee755.html 版权声明 本博客所有文章除特别声明外均采用 BY-NC-SA 许可协议。转载请注明出处