6.1 C/C++ 封装字符串操作

C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。

6.1.1 封装字符串操作

字符串与整数: 将字符串转为数值可以使用sscanf()函数,将数值转为字符串可以使用sprintf()函数.

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
// int -> string
char szBuf[32] = { 0 };
int number = 100;

sprintf(szBuf, "%d", number);
std::cout << "字符串: " << szBuf << std::endl;

// string -> int
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];

// 以空格进行切割字符串并将结果存入dst
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;

// 每次剪切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.h>

using 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);
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)
{
// 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;
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;
}

// 将单一字符 转 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;
}
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;
}
}

// 按主键查找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_cast<unsigned char>(c) / 16];
result[i + 2] = hex[static_cast<unsigned 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?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/wcharstring字符串之间的相互转换.

#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(L"hello 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_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转为string
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());
}

// 传入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::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, ":");

// std::cout << "key = " << two_split[0] << " value = " << two_split[1] << std::endl;

// 寻找key所对应的value
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;
}

// 从字符串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字节内存全部初始化为0
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;

// 如果 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;
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;
// 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;
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);
// 返回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 *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;
}