前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6.1 C/C++ 封装字符串操作

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

作者头像
微软技术分享
发布2023-10-11 15:53:40
4740
发布2023-10-11 15:53:40
举报

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

6.1.1 封装字符串操作

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

代码语言:javascript
复制
#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()函数对特定字符串使用特定符号进行的切割,切割后的数据分别放入新的数组中.

代码语言:javascript
复制
#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;
}

字符串分块: 循环将传入的字符串按照指定长度切片处理,切片后返回到一个二维数组中存储.

代码语言:javascript
复制
#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;
}

字符串过滤: 用户传入一个字符串,以及传入需要过滤的字符,自动过滤掉字符串内的所有过滤字符.

代码语言:javascript
复制
#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;
}

字符串替换: 在一个字符串中查找特定字符串,只要找到自动将其替换为新的字符串.

代码语言:javascript
复制
#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()函数功能,格式化一段字符串.

代码语言:javascript
复制
#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;
}

字符串去空格: 函数接收字符串指针,并循环去除该字符串中左右两端的空格,回写到原空间.

代码语言:javascript
复制
#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互转: 将一段字符串转为一段十六进制数(字符串格式),或将十六进制数转为字符串.

代码语言:javascript
复制
#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()功能实现.

代码语言:javascript
复制
#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语言中的字典数据结构的基本操作,与字典操作保持一致.

代码语言:javascript
复制
#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字符串进行编码与解码的函数过程实现.

代码语言:javascript
复制
#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字符串之间的相互转换.

代码语言:javascript
复制
#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++直接实现了解析字符串格式的文本为字典,能够直接当字典解析.

代码语言:javascript
复制
#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;
}

字符串正反向对比与截取: 实现了字符串反向对比以及截取指定位置字符串对比功能.

代码语言:javascript
复制
#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 内存填充: 设置某个范围内每字节的值,通常用来清空结构体或者清空某块内存。

代码语言:javascript
复制
#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指定的对象中。

代码语言:javascript
复制
#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指向的对象中。

代码语言:javascript
复制
#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指向的数组中。

代码语言:javascript
复制
#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指向的数组中。

代码语言:javascript
复制
#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指向的串的末尾。

代码语言:javascript
复制
#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指向的串的末尾。

代码语言:javascript
复制
#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结尾的字符串长度。

代码语言:javascript
复制
#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 字符串比较: 字符串比较函数,用于比较两个字符串的区别。

代码语言:javascript
复制
#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个字符。

代码语言:javascript
复制
#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不会检查字符串是否到结束。

代码语言:javascript
复制
#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本地库有关的字符串比较函数,在开始比较之前会按照特定的方式转换字符串然后在进行比较。

代码语言:javascript
复制
#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()则用于比较指定的前几个中文字符。

代码语言:javascript
复制
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 *适合各种数据类型,不过只能查找一个字节。

代码语言:javascript
复制
#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 字符串中查找: 字符串中查找字符,并返回这个字符第一次出现的地址。

代码语言:javascript
复制
#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 字符串中反向查找: 字符串反向查找字符,返回这个字符最后一次出现的位置。

代码语言:javascript
复制
#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。

代码语言:javascript
复制
#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 根据标识查找字符串: 通过标识来查找字符串,需要注意的是这个会修改原来字符串的值。

代码语言:javascript
复制
#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不同的字符下标。

代码语言:javascript
复制
#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中第一次出现的位置。

代码语言:javascript
复制
#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返回的是地址。

代码语言:javascript
复制
#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;
}

本文作者: 王瑞 本文链接: https://www.lyshark.com/post/feee755.html 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 6.1.1 封装字符串操作
  • 6.1.2 复制与剪切函数
  • 6.1.3 字符串比较函数
  • 6.1.4 字符串查找函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档