C语言C++字符串 C++20 string_view

一、C-Type string

  1. 在C语言中,字符串表示为字符数组,最后面加 \0

  1. strlen获得字符串实际大小

sizeof不要使用sizeof获取字符串大小

char* copyString(const char* str)
{
    char* result { new char[strlen(str)] }; // BUG! Off by one!
    strcpy(result, str);
    return result;
}

char* copyString(const char* str)
{
	FIGURE 2-1
	Dynamic Strings ❘ 89
 	char* result { new char[strlen(str) + 1] };  //正确做法
 	strcpy(result, str);
 	return result;
}

char* appendStrings(const char* str1, const char* str2, const char* str3)
{
     char* result { new char[strlen(str1) + strlen(str2) + strlen(str3) + 1] };
     strcpy(result, str1);
     strcat(result, str2);
     strcat(result, str3);
     return result;
}
char text1[] { "abcdef" };
size_t s1 { sizeof(text1) }; // is 7
size_t s2 { strlen(text1) }; // is 6

const char* text2 { "abcdef" };
//sizeof const char* 的大小
size_t s3 { sizeof(text2) }; // is platform-dependent  32位 4 64位 8 
size_t s4 { strlen(text2) }; // is 6

二、 字符串常量(String Literals )

cout << "hello" << endl;    //字符串常量 "hello" 存在只读内存中
//“array of n const char

//字符串常量赋值给字符指针时 不可修改
char* ptr { "hello" }; // Assign the string literal to a variable.
ptr[1] = 'a'; // Undefined behavior!

const char* ptr { "hello" }; // Assign the string literal to a variable.
ptr[1] = 'a'; // Error! Attempts to write to read-only memory

//字符串常量赋值给字符数组时 可修改 
//编译器会常量字符串给字符数组 
char arr[] { "hello" }; // Compiler takes care of creating appropriate sized
 // character array arr.
arr[1] = 'a'; // The contents can be modified.

三、原始字符串字面值(raw string literal)

原始字符串简单来说,“原生的、不加处理的”,字符表示的就是自己(所见即所得),引号、斜杠无需 “\” 转义,比如常用的目录表示,引入原始字符串后,非常方便。

格式

R"(原始字符串)";

代码

#include <iostream>
#include<string>

int main()
{
    //原始字符串字面值
    std::string redist_path1 = "C:\Program Files (x86)\Microsoft.NET\RedistList";
    std::string redist_path2 = "C:\\Program Files (x86)\\Microsoft.NET\\RedistList";
    std::string redist_path3 = R"(C:\Program Files (x86)\Microsoft.NET\RedistList)";
    std::string redist_path4 = R"(C:\\Program Files (x86)\\Microsoft.NET\\RedistList)";

    std::cout << "redist_path1: " << redist_path1 << std::endl;
    std::cout << "redist_path2: " << redist_path2 << std::endl;
    std::cout << "redist_path3: " << redist_path3 << std::endl;
    std::cout << "redist_path4: " << redist_path4 << std::endl;

    std::string fozu = R"(
                            _ooOoo_
                           o8888888o
                           88" . "88
                           (| -_- |)
                            O\ = /O
                        ____/`---'\____
                      .   ' \\| |// `.
                       / \\||| : |||// \
                     / _||||| -:- |||||- \
                       | | \\\ - /// | |
                     | \_| ''\---/'' | |
                      \ .-\__ `-` ___/-. /
                   ___`. .' /--.--\ `. . __
                ."" '< `.___\_<|>_/___.' >'"".
               | | : `- \`.;`\ _ /`;.`/ - ` : | |
                 \ \ `-. \_ __\ /__ _/ .-` / /
         ======`-.____`-.___\_____/___.-`____.-'======
                            `=---='
		)";

    std::cout << fozu << std::endl;

    return 0;
}

四、 The C++ std::string Class

1. C-style 字符串的优缺点

优点:

  • 很简单,利用了底层的基本字符类型和数组结构
  • 很轻,如果使用得当,只会占用所需的内存
  • 它们是低级别的,所以您可以很容易地将它们作为原始内存进行操作和复制
  • 如果你是一个C程序员,为什么要学习一些新东西?

缺点:

  • 需要付出难以置信的努力来模拟一流的字符串数据类型
  • 容易出现难以找到的内存错误
  • 没有利用C++的面向对象特性
  • 它们要求程序员了解其底层表示

2. 字符串比较

    //c 字符串比较
    const char* a = "hello";        //不可修改
    char b[] = "hello";             //可以修改
    //b[0] = 'a';
    //比较的是字符指针
    if (a == b)         
    {
        std::cout << "a == b" << std::endl;
    }
    //C字符串比较
    if (strcmp(a, b) == 0)
    {
        std::cout << "a == b" << std::endl;
    }
    //stl C++ 字符串
    std::string a1("hello");
    std::string b1("hello");
    //这种方法的缺点:compate 返回值是 int 不容易记忆比较结果 使用起来很麻烦
    auto    result = a1.compare(b1);
    if (result == 0)
    {
        std::cout << "a1 equal b1" << std::endl;
    }else if (result < 0)
    {
        std::cout << "a1 less b1" << std::endl;
    }else if (result > 0)
    {
        std::cout << "a1 greater b1" << std::endl;
    }
    //C++20 字符串比较
    auto result2{ a1 <=> b1 };
    if (std::is_eq(result2))
    {
        std::cout << "a1 equal b1" << std::endl;
    }
    else if (std::is_lt(result2))
    {
        std::cout << "a1 less b1" << std::endl;
    }
    else if (std::is_gt(result2))
    {
        std::cout << "a1 greater b1" << std::endl;
    }

3. 获取字符串指针

auto pChar1 = a1.c_str();
auto pChar2 = a1.data();
std::cout << pChar1 << std::endl;
std::cout << pChar2 << std::endl;

4. find substr replace starts_with ends_with 用法

//find substr replace starts_with ends_with
std::string strHello{ "Hello!!" };
std::string strWorld{ "The World..." };
auto position{ strHello.find("!!") };
if (position != std::string::npos) {
    // Found the "!!" substring, now replace it.
    strHello.replace(position, 2, strWorld.substr(3, 6));
}
std::cout << strHello << std::endl;

bool bStart = strHello.starts_with("Hel");
std::cout << bStart << std::endl;
bool bEnd = strHello.ends_with("d");
std::cout << bEnd << std::endl;

5. 数值转换

5.1. 数值转字符串

long double d { 3.14L };
string s { to_string(d) };

5.2. 字符串转数值

  • int stoi(const string& str, size_t *idx=0, int base=10);
  • long stol(const string& str, size_t *idx=0, int base=10);
  • unsigned long stoul(const string& str, size_t *idx=0, int base=10);
  • long long stoll(const string& str, size_t *idx=0, int base=10);
  • unsigned long long stoull(const string& str, size_t *idx=0, int base=10);
  • float stof(const string& str, size_t *idx=0);
  • double stod(const string& str, size_t *idx=0);
  • long double stold(const string& str, size_t *idx=0);

string :将要转换的字符串

idx:第一个不能被转换的字符指针,可以为空(忽略返回值)

base:数值进制,默认十进制

const std::string toParse{ "123USD232" };
size_t index{ 0 };
int value{ stoi(toParse, &index) };

std::cout << std::format("字符串转数值:{}", value) << std::endl;
std::cout << std::format("第一个不能转换的字符:{}", toParse[index]) << std::endl;

五、The std::string_view Class

string_view提供字符串的只读视图(没有字符串拷贝,内部只包含一个指针和长度),并支持类似于字符串的接口

注意:每当函数需要只读字符串作为其参数之一时使用std::string_view而不是const string&或const char*

//string_view 没有字符串拷贝,内部只包含一个指针和长度 效率高
string_view extractExtension(string_view filename)
{
 return filename.substr(filename.rfind('.'));
}

string filename { R"(c:\temp\my file.ext)" };
cout << format("C++ string: {}", extractExtension(filename)) << endl;
const char* cString { R"(c:\temp\my file.ext)" };
cout << format("C string: {}", extractExtension(cString)) << endl;
cout << format("Literal: {}", extractExtension(R"(c:\temp\my file.ext)")) << endl;

const char* raw{ "hfdskfd" };
size_t length{ 3 };
std::string_view stringView(raw, length);
std::cout << stringView << std::endl;

注意:不能使用string_view 直接构造 string

//handleExtension(extractExtension("my file.ext")); //error
handleExtension(extractExtension("my file.ext").data()); // data() method
handleExtension(std::string{ extractExtension("my file.ext") }); // explicit ctor
std::string str{ "Hello" };
std::string_view sv{ " world" };
//auto result{ str + sv };   //error
auto result1{ str + sv.data() };
std::string result22{ str };
result22.append(sv.data(), sv.size());

注意:不能使用string_view 作为函数返回值,有失效风险

注意:不能使用string_view存储一个临时string变量的view

string s { "Hello" };
string_view sv { s + " World!" };   //临时变量 World 在大括号之后会释放
cout << sv;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值