C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。
6.1.1 封装字符串操作
字符串与整数: 将字符串转为数值可以使用sscanf()
函数,将数值转为字符串可以使用sprintf()
函数.
#include <iostream> #include <string>
int main(int argc, char* argv[]) { char szBuf[32] = { 0 }; int number = 100;
sprintf(szBuf, "%d", number); std::cout << "字符串: " << szBuf << std::endl;
sscanf(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];
int cnt = split(dst, src_string, " "); for (int i = 0; i < cnt; i++) { std::cout << "切割后: " << dst[i] << std::endl; } return 0; }
|
字符串分块: 循环将传入的字符串按照指定长度切片处理,切片后返回到一个二维数组中存储.
#include <iostream> #include <Windows.h>
using 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;
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.h>
using namespace std;
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; }
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); else break; } 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_cast<char*>(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_cast<int>(size)) { break; } else { if (expected > -1) size = static_cast<size_t>(expected + 1); else size *= 2;
buffer.resize(size); buffer_p = const_cast<char*>(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, x+10); std::cout << "生成地址: " << ref << std::endl; }
return 0; }
|
字符串去空格: 函数接收字符串指针,并循环去除该字符串中左右两端的空格,回写到原空间.
#include <iostream> #include <string>
using 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) { result = (char)(value + 48); } else if (value >= 10 && value <= 15) { 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;
high = tmp >> 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; }
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; else byte[n] = hex[i] - '0'; if (hex[i + 1] >= 'A' && hex[i + 1] <= 'F') byte[n] = (byte[n] << 4) | (hex[i + 1] - 'A' + 10); else byte[n] = (byte[n] << 4) | (hex[i + 1] - '0'); ++n; } return n; }
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 *)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; } else dict->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; } }
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) {
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); }
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>
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 == '~')) { result[i++] = c; } else { result[i + 0] = '%'; result[i + 1] = hex[static_cast<unsigned char>(c) / 16]; result[i + 2] = hex[static_cast<unsigned char>(c) % 16]; i += 3; } }
result.resize(i); return result; }
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?uid=102";
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;
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; }
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; }
string ws2s(const wstring& ws) { _bstr_t t = ws.c_str(); char* pchar = (char*)t; string result = pchar; return result; }
wstring s2ws(const string& s) { _bstr_t t = s.c_str(); wchar_t* pwchar = (wchar_t*)t; wstring result = pwchar; return result; }
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 = 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(L"hello lyshark");
std::wcout << "string -> wstring: " << string2wstring(stringA) << std::endl; std::cout << "wstring -> string: " << wstring2string(wstringA) << std::endl;
std::wcout << "string -> wstring: " << s2ws(stringA) << std::endl; std::cout << "wstring -> string: " << ws2s(wstringA) << std::endl;
wstring_convert<codecvt<wchar_t, char, mbstate_t>> converter(new codecvt<wchar_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 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::vector<std::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()); }
std::string get_value(std::string szDict, std::string key) { Del_Space(szDict);
Del_Char(szDict, '\''); Del_Char(szDict, '{'); Del_Char(szDict, '}');
std::vector<std::string> one_split; SplitString(szDict, one_split, ",");
for (int x = 0; x < one_split.size(); x++) { std::vector<std::string> two_split; SplitString(one_split[x], two_split, ":");
if (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; }
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[]) { char* p = (char*)malloc(sizeof(char) * 10);
memset(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;
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) { for (su1 = s1 + n, su2 = s2 + n; n > 0; --n, --su1, --su2) { *su1 = *su2; } } else { 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; for (s = s1; 0 < n && *s2 != '\0'; ++s) *s++ = *s2++; 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++; }
while (count++ < n) { *s1++ = '\0'; }
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; for (s = s1; *s != '\0'; ++s) ; 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; for (s = s1; *s != '\0'; ++s) ; for (; 0 < n && *s2 != '\0'; --n) *s++ = *s2++; *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++)) { ; }
while (0 < n--) { *s1++ = '\0'; } 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;
typedef struct { unsigned char _State; unsigned short _Wchar; } _Cosave;
size_t _Strxfrm(char*, const unsigned char**, size_t, _Cosave*);
_Statab _Costate, _Mbstate, _Wcstate;
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; else leave = 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; else s1++; return NULL; }
int main(int argc, char *argv[]) { printf("%s", _strstr("that this think", "think")); return 0; }
|
strtok 根据标识查找字符串: 通过标识来查找字符串,需要注意的是这个会修改原来字符串的值。
#include <stdio.h> #include <string.h>
char * strtok(char *s1, const char *s2) { char *sbegin, *send; static char *ssave = ""; sbegin = s1 ? s1 : ssave; sbegin += strspn(sbegin, s2); if (*sbegin == '\0') { ssave = ""; return NULL; } send = sbegin + strcspn(sbegin, s2); if (*send != '\0') *send++ = '\0'; ssave = 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>
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; else break; 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); 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>
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 *s1="Welcome To Beijing"; char *s2="BIT"; char *p; p = strpbrk(s1,s2); if(p) printf("%sn",p); else printf("Not Found!n"); p = strpbrk(s1, "Daj"); if(p) printf("%s",p); else printf("Not Found!n"); return 0; }
|