C++ 如何在ascii值超过127的字符串中查找8位子字符串?

C++ 如何在ascii值超过127的字符串中查找8位子字符串?,c++,string,search,substring,bit-manipulation,C++,String,Search,Substring,Bit Manipulation,我正在努力解决一个问题,我在尝试使用字符串中的按位子字符串时遇到了这个问题。在下面的示例中,这个简单的小函数对值0-127执行它应该执行的操作,但如果我尝试使用大于127的ASCII值,则会失败。我假设这是因为字符串本身是有符号的。但是,如果我将其设为无符号,我不仅会遇到问题,因为显然strlen()不处理无符号字符串,而且会收到一条警告,指出它是一个多字符常量。为什么有多重字符?我想我什么都试过了。我能做些什么来让这个值大于127 #include <iostream> #incl

我正在努力解决一个问题,我在尝试使用字符串中的按位子字符串时遇到了这个问题。在下面的示例中,这个简单的小函数对值0-127执行它应该执行的操作,但如果我尝试使用大于127的ASCII值,则会失败。我假设这是因为字符串本身是有符号的。但是,如果我将其设为无符号,我不仅会遇到问题,因为显然
strlen()
不处理无符号字符串,而且会收到一条警告,指出它是一个多字符常量。为什么有多重字符?我想我什么都试过了。我能做些什么来让这个值大于127

#include <iostream>
#include <cstring>

const unsigned char DEF_KEY_MINOR = 0xAD;

const char *buffer = { "jhsi≠uhdfiwuui73" };

size_t isOctetInString(const char *buffer, const unsigned char octet)
{
  size_t out = 0;
  for (size_t i = 0; i < strlen(buffer); ++i)
  {
    if(!(buffer[i] ^ octet))
    {
      out = i;
      break;
    }
  }
  return out;
}

int main() {
    std::cout << isOctetInString(buffer, 'i') << "\n";
    std::cout << isOctetInString(buffer, 0x69) << "\n";
    std::cout << isOctetInString(buffer, '≠') << "\n";
    std::cout << isOctetInString(buffer, 0xAD) << "\n";
    return 0;
}
编辑

3
3
0
0
根据注释,我尝试了一些不同的方法,包括将八位字节和缓冲区强制转换为unsigned int和wchar_t,以及从八位字节参数类型中删除unsigned char。有了这些,我得到的结果是

3
3
6
0
我甚至试着用≠ 在缓冲区中使用

const char *buffer = {'0xAD', "jhsiuhdfiwuui73"};
但是,我仍然收到关于多字节字符的警告


正如我之前所说,我主要关心的是能够在字符串中找到位序列0xAD,但现在我看到使用ascii字符或任何使用ascii字符集的构造都会导致问题。由于
0xAD
只有8位,因此必须有一种方法来实现这一点。有人知道这样做的方法吗?

符号扩展--buffer[i]^octet实际上是无符号的(int(buffer[i]))^unsigned(octet)。如果希望缓冲区[]为无符号字符,则必须以这种方式定义它。

问题中存在多个混淆源:

  • 可以使用
    strchr()
    在字符串中搜索
    unsigned char
    值,它将
    int
    参数和
    char
    数组中的字符转换为
    unsigned char
    进行比较

  • 您的函数使用
    if(!(缓冲区[i]^octet))
    检测匹配,如果对
    char
    进行了签名,这将不起作用,因为表达式的计算结果为
    if(!((int)缓冲区[i]^(int)octet))
    ,并且符号扩展仅对
    缓冲区[i]
    发生。一个简单的解决方案是:

      if ((unsigned char)buffer[i] == octet)
    
  • 请注意,字符
    可能在目标系统上编码为多个字节,包括在源代码和终端处理中,例如code pointis 8800或0x2260在UTF-8中编码为0xE2 0x89 0xA0。语法
    '≠'会造成问题。我不确定C++如何处理多字节字符常量,但C将接受具有特定实现值的值。

  • 要查看系统如何处理非ASCII字节,可以将以下行添加到
    main()
    函数中:

      std::cout << "≠ uses " << sizeof("≠") - 1 << "bytes\n";
      std::cout << "'≠' has the value " << (int)'≠' << "\n";
    

是7位编码,因此没有大于127的ASCII值。如何
在.cpp文件中编码和解释取决于您使用的文本编辑器和编译器。实际上,我只关心位。我只是想测试一下算法。该符号可能不可移植,但这是适用于此环境的正确符号。然后只需强制比较到单字节
(无符号字符)缓冲区[i]==(无符号字符)八位字节
。但是,关于“多字符常量”的警告表明可能涉及其他一些多字节编码,可能是UTF-8。
buffer
octet
都需要签名(或都不签名)。否则,
0xAD
的符号扩展将给出
0xffffad
(有符号,32位int)和
0x000000AD
(无符号,32位int)。执行这些异或运算将导致
0xFFFFFF00
。如果在您的平台上
char
有符号,则设置高位时的实际值将介于-128和-1之间。将此类值与128到255之间的数字进行XOR运算永远不会得到0。
  printf("≠ is encoded as");
  for (size_t i = 0; i < sizeof("≠") - 1; i++) {
      printf(" %02hhX", "≠"[i]);
  }
  printf(" and '≠' has a value of 0x%X\n", '≠');
≠ is encoded as E2 89 A0 and '≠' has a value of 0xE289A0
  notequal.c:8:48: error: character too large for enclosing character literal type
  printf(" and '≠' has a value of 0x%X\n", '≠');