如何查找字符串中带有文件路径的非ASCII字符

7

检测文件路径中是否有非ASCII字符

我有一个Unicode字符串,采用UTF-8编码存储文件路径,例如 C:\Users\myUser\Downloads\ü.pdf。我已经确认该字符串在本地文件系统中是正确的文件路径,但由于我将该字符串发送到只支持ASCII的不同进程,因此我需要确定该字符串是否包含任何非ASCII字符。

我该如何做?


1
将字符串转换为ASCII码,再转换回UTF-8编码,然后将原始字符串与转换两次的字符串进行比较。如果比较成功,则发送ASCII字符串。 - Richard Critten
2个回答

8
一个ASCII字符只使用一个char的低7位(值0-127)。UTF-8编码的非ASCII Unicode字符使用的是所有char元素的最高位设置。所以,你可以简单地迭代char元素,查看是否有任何元素的值超过了127,例如:
bool containsOnlyASCII(const std::string& filePath) {
  for (auto c: filePath) {
    if (static_cast<unsigned char>(c) > 127) {
      return false;
    }
  }
  return true;
}

关于类型转换的注意事项:std::string 包含 char 元素。标准并未定义 char 是有符号还是无符号。如果它是有符号的,那么我们可以按照标准规定的方式将其转换为无符号。

7

正如几个评论所建议的,并且由 @CrisLuengo 的答案强调,我们可以迭代字符,查找其中任何一个设置了上位比特位的字符(现场实例):

#include <iostream>
#include <string>
#include <algorithm>

bool isASCII (const std::string& s)
{
    return !std::any_of(s.begin(), s.end(), [](char c) { 
        return static_cast<unsigned char>(c) > 127; 
    });
}

int main()
{
    std::string s1 { "C:\\Users\\myUser\\Downloads\\Hello my friend.pdf" };   
    std::string s2 { "C:\\Users\\myUser\\Downloads\\ü.pdf" };

    std::cout << std::boolalpha << isASCII(s1) << "\n";
    std::cout << std::boolalpha << isASCII(s2) << "\n";
}


2
尽管这可能不是解决方案,但该函数可以缩短为return std::all_of(filepath.begin(), filepath.end(), ::isprint); - PaulMcKenzie
1
@1201ProgramAlarm https://dev59.com/qGEh5IYBdhLWcg3w_Xr5 这里的强制类型转换是为了避免由于负值而导致未定义行为,尽管在这种特定情况下不会发生。 - FrankS101
@PaulMcKenzie 您是正确的,这样会更短,但为什么这可能不是解决方案呢?一个反例会很有帮助。 - FrankS101
2
请注意,isprint函数的行为取决于当前的 C 区域设置。如果有人更改了区域设置,则它将不再检查“可打印ASCII”字符。至少,我会更改函数名称以避免混淆。 - Adrian McCarthy
我可能会使用类似于 bool isASCII = std::all_of(filepath.begin(), filepath.end(), [](char c){ return static_cast<unsigned char>(c) <= 127; }); 或者 bool isASCII = !std::any_of(filepath.begin(), filepath.end(), [](char c){ return static_cast<unsigned char>(c) > 127; }); 这样的代码。 - Remy Lebeau
那么根据你的代码,NUL、SOH和**'\x01\02\x03"**是ASCII字符吗? - Haseeb Mir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接