c++ string

 

string是C++风格的字符串,本质上是一个类,它的内部封装了char *,是一个char *型的容器

使用string需要包含<string>头文件

string的内部封装了很多方法,本文将重点介绍string的一些常用方法,这些方法足以应对日常的刷题和比赛

 

C++ string 类详解:

字符串是存储在内存的连续字节中的一系列字符。C++ 处理字符串的方式有两种,一种来自 C 语言,常被称为 C-风格字符串,另一种是基于 string 类库的字符串处理方式。C 风格字符串的处理可以参考 https://www.cnblogs.com/tongye/p/10688941.html ,本文着重介绍 string 类库的使用。

一、string 类简介

  C++ 中提供了专门的头文件 string(注意不是 string.h,这个是 C 风格字符串相关函数的头文件),来支持 string 类型。string 类定义隐藏了字符串的数组性质,让我们可以像处理普通变量那样处理字符串。string 对象和字符数组之间的主要区别是:可以将 string 对象声明为简单变量,而不是数组

1.1 string 类几种常见的构造函数:

1)string(const char *s) :将 string 对象初始化为 s 指向的字符串

string str("Hello!");

2)string(size_type n,char c) :创建一个包含 n 个元素的 string 对象,其中每个元素都被初始化为字符 c

string str(10,'a');

3)string(const string &str) :将一个 string 对象初始化为 string 对象 str(复制构造函数)

string str1("hello!");
string str2(str1);

4)string() :创建一个默认的 string 对象,长度为 0(默认构造函数)

string str;     // 创建一个空的 string 对象

  string 类的设计允许程序自动处理 string 的大小,因此,上述代码创建了一个长度为 0 的string 对象,但是向 str 中写入数据时,程序会自动调整 str 的长度。因此,与使用数组相比,使用 string 对象更方便,也更安全。

 

1.2 用 C 语言风格初始化 string 对象:

  C++ 允许使用 C 语言风格来初始化 string 对象:

string str = "hello!";

 

二、获取 string 对象的长度

  在 C 语言中,使用 strlen 函数获取字符串的长度。在 C++ 中,可以使用 string.size() 函数或 string.length() 函数来获得 string 对象的长度。在 C++ 标准库中,两者的源代码如下:

复制代码
  size_type   __CLR_OR_THIS_CALL   length()   const   
  { //   return   length   of   sequence   
  return   (_Mysize);   
  }   
    
  size_type   __CLR_OR_THIS_CALL   size()   const   
  { //   return   length   of   sequence   
  return   (_Mysize);   
  }
复制代码

   可见,这两个方法是完全一样的,并没有区别。length() 方法是 C 语言习惯保留的,size() 方法则是为了兼容 STL 容器而引入的。

string str("Hello,World!");
int strLen1 = str.length();
int strLen2 = str.size();

 

三、复制 string 对象

  在 C 语言中,使用 strcpy、strncpy 函数来实现字符串的复制。在 C++ 中则方便很多,可以直接将一个 string 对象赋值给另一个 string 对象,即:

string str1("Hello,World!");
string str2;
str2 = str1;

  由于 string 类会自动调整对象的大小,因此不需要担心目标数组不够大的问题。

 

四、string 对象的拼接和附加

  在 C 语言中,使用 strcat、strncat 函数来进行字符串拼接操作。在 C++ 中也有多种方法来实现字符串拼接和附加操作:

4.1 使用 + 操作符拼接两个字符串

string str1("hello ");
string str2("world!");
string str3 = str1 + str2;

4.1 使用 += 操作符在字符串后面附加内容

  可以使用 += 来在一个 string 对象后面附加一个 string 对象、字符以及 C 风格的字符串:

复制代码
string str1("hello ");
string str2("world!\n");
str1 += str2; str1 += "nice job\n"; str1 += 'a';
复制代码

4.2 使用 string.append() 函数

  可以使用 string.append() 函数来在一个 string 对象后面附加一个 string 对象或 C 风格的字符串:

string str1 = "hello,world!";
string str2 = "HELLO,WORLD!";
    
str1.append(str2);
str1.append("C string");

 

4.3 使用 string.push_back() 函数

  可以使用 string.push_back() 函数来在一个 string 对象后面附加一个字符:

string str("Hello");
str.push_back('a');

 

五、string 对象的比较

  在 C 语言中,使用 strcmp、strncmp 函数来进行字符串的比较。在 C++ 中,由于将 string 对象声明为了简单变量,故而对字符串的比较操作十分简单了,直接使用关系运算符(==、!=、<、<=、>、>=)即可:

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str1("hello");
    string str2("hello");

    if (str1 == str2)
        cout << "str1 = str2" << endl;
    else if (str1 < str2)
        cout << "str1 < str2" << endl;
    else
        cout << "str1 > str2" << endl;

    return 0;
}
复制代码

  当然,也可以使用类似 strcmp 的函数来进行 string 对象的比较,string 类提供的是 string.compare() 方法,函数原型如下:

复制代码
int compare(const string&str) const;

int compare(size_t pos,size_t len,const string&str)const;    // 参数 pos 为比较字符串中第一个字符的位置,len 为比较字符串的长度

int compare(size_t pos,size_t len,const string&str, size_t subpos,size_t sublen)const;

int compare(const char * s)const;

int compare(size_t pos,size_t len,const char * s)const;

int compare(size_t pos,size_t len,const char * s,size_t n)const;
复制代码

   compare 方法的返回值如下:

1)返回 0,表示相等;

2)返回结果小于 0,表示比较字符串中第一个不匹配的字符比源字符串小,或者所有字符都匹配但是比较字符串比源字符串短;

3)返回结果大于 0,表示比较字符串中第一个不匹配的字符比源字符串大,或者所有字符都匹配但是比较字符串比源字符串长。

 

六、使用 string.substr() 函数来获取子串

  可以使用 string.substr() 函数来获取子串,string.substr() 函数的定义如下:

string substr(size_t pos = 0,size_t len = npos)const;

  其中,pos 是子字符串的起始位置(索引,第一个字符的索引为 0),len 是子串的长度。这个函数的功能是:复制一个 string 对象中从 pos 处开始的 len 个字符到 string 对象 substr 中去,并返回 substr。

string str("Hello,World!");
string subStr = str.substr(3,5);
cout << subStr << endl;

  这段代码的输出结果为:"lo,Wo"。

 

七、访问 string 字符串的元素 

  可以像 C 语言中一样,将 string 对象当做一个数组,然后使用数组下标的方式来访问字符串中的元素;也可以使用 string.at(index) 的方式来访问元素(索引号从 0 开始):

string str("Hello,World!");
cout << str[1] << endl;      // 使用数组下标的方式访问 string 字符串的元素
cout << str.at(1) << endl;     // 使用 at 索引访问 string 字符串的元素

 

八、string 对象的查找操作

8.1 使用 string.find() 方法查找字符

  find 方法的函数原型如下:

1)从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:

size_type find (const string& str, size_type pos = 0) const;

2)从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 s。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:  

size_type find (const char *s, size_type pos = 0) const;

 3)从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找 s 的前 n 个字符组成的子字符串。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:

size_type find (const char *s, size_type pos, size_type n);

 4)从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找字符 ch 。如果找到,则返回该字符首次出现的位置;否则,返回 string::npos:

size_type find (char ch, size_type pos = 0) const;

   举个查找子字符串的例子(查找字符的代码与这一样,只需要将 find 函数的参数换成字符即可):

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str("cat,dog,cat,pig,little cat,hotdog,little pig,angry dog");
    size_t catPos = str.find("cat",0);

    if (catPos == string::npos) {
        printf("没有找到字符串\n");
        return 0;
    }

    while (catPos != string::npos) {
        cout << "在索引 " << catPos << " 处找到字符串" << endl;
        catPos = str.find("cat", catPos + 1);
    }
    return 0;
}
复制代码

  程序输出结果如下:

  

8.2 string.rfind()

  string.rfind() 与 string.find() 方法类似,只是查找顺序不一样, string.rfind() 是从指定位置 pos (默认为字符串末尾)开始向前查找,直到字符串的首部,并返回第一次查找到匹配项时匹配项首字符的索引。换句话说,就是查找子字符串或字符最后一次出现的位置。还是以上面的程序为例,稍作修改:

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str("cat,dog,cat,pig,little cat,hotdog,little pig,angry dog");
    size_t catPos = str.rfind("cat",str.length()-1);

    if (catPos == string::npos) {
        printf("没有找到字符串\n");
        return 0;
    }

    while (catPos != string::npos) {
        cout << "在索引 " << catPos << " 处找到字符串" << endl;
        catPos = str.rfind("cat", catPos - 1);
        if (catPos == 0) {
            cout << "在索引 " << catPos << " 处找到字符串" << endl;
            break;
        }
    }
    return 0;
}
复制代码

  程序输出结果如下:

  可以看到,rfind 方法是从字符串末开始查找的。

 

8.3 string.find_first_of()

   string.find_first_of() 方法在字符串中从指定位置开始向后(默认为索引 0 处)查找参数中任何一个字符首次出现的位置。举个例子说明:

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str("cat,dog,cat,pig,little cat,hotdog,little pig,angry dog");
    size_t pos = str.find_first_of("zywfgat");

    if (pos == string::npos) {
        printf("没有匹配到\n");
        return 0;
    }
    else
        cout << "在索引 " << pos << " 处匹配到" << endl;

    return 0;
}
复制代码

   程序输出结果是:在索引 1 处匹配到。所查找的字符串 zywfgat 中,第一次出现在字符串 str 中的字符是 'a',该字符在 str 中的索引是 1.

8.4 string.find_last_of()

   string.find_last_of() 方法在字符串中查找参数中任何一个字符最后一次出现的位置(也就是从指定位置开始往前查找,第一个出现的位置)。

8.5 string.find_first_not_of()

  string.find_first_not_of() 方法在字符串中查找第一个不包含在参数中的字符。

8.6 string.find_last_not_of()

  string.find_last_not_of() 方法在字符串中查找最后一个不包含在参数中的字符(从指定位置开始往前查找,第一个不包含在参数中的字符)。

 

九、string 对象的插入和删除操作

9.1 使用 string.insert() 进行插入操作

   函数原型如下:

复制代码
string&insert(size_t pos,const string&str);   // 在位置 pos 处插入字符串 str

string&insert(size_t pos,const string&str,size_t subpos,size_t sublen); // 在位置 pos 处插入字符串 str 的从位置 subpos 处开始的 sublen 个字符

string&insert(size_t pos,const char * s);    // 在位置 pos 处插入字符串 s

string&insert(size_t pos,const char * s,size_t n); // 在位置 pos 处插入字符串 s 的前 n 个字符

string&insert(size_t pos,size_t n,char c);      // 在位置 pos 处插入 n 个字符 c

iterator insert (const_iterator p, size_t n, char c); // 在 p 处插入 n 个字符 c,并返回插入后迭代器的位置

iterator insert (const_iterator p, char c);       // 在 p 处插入字符 c,并返回插入后迭代器的位置
复制代码

   举个例子:

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str("abcdefgh");
    str.insert(1,"INSERT");        // 在位置 1 处插入字符串 "INSERT"
    cout << str << endl;

    str.insert(10, 5, 'A');        // 在位置 10 处插入 5 个字符 'A'
    cout << str << endl;
    return 0;
}
复制代码

  输出结果如下:

 

9.2 使用 string.erase() 进行元素删除操作

  函数原型如下:

string& erase (size_t pos = 0, size_t len = npos);   // 删除从 pos 处开始的 n 个字符

iterator erase (const_iterator p);            // 删除 p 处的一个字符,并返回删除后迭代器的位置

iterator erase (const_iterator first, const_iterator last); // 删除从 first 到 last 之间的字符,并返回删除后迭代器的位置

   举个例子:

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str("Hello,World!");
    str.erase(5,6);                    // 删除从索引位置 5 开始的 6 个字符
    cout << "str 为:" << str << endl;

    return 0;
}
复制代码

   关于 erase() 函数的用法可以参考 https://www.cnblogs.com/liyazhou/archive/2010/02/07/1665421.html

 

十、string 对象的一些其他操作

10.1 使用 getline() 函数来获取 string 输入

string str;

getline(cin,str);    // 从输入流中读取一行数据到 str

 

10.2 使用 empty() 函数判断字符串是否为空

string str;

if(str.empty()){
    cout << "字符串为空" << endl;  
}

  string.empty() 函数,若字符串为空,则返回真,否则返回假。

 

10.3 使用 swap 函数交换两个字符串

复制代码
#include <string>
#include <iostream>

using namespace std;

int main() 
{
    string str1 = "hello,world!";
    string str2 = "HELLO,WORLD!";

    str1.swap(str2);

    cout << str1 << endl;
    cout << str2 << endl;

    return 0;
}
复制代码

 

 

 

参考资料:

C++ Primer Plus(第六版)

来自:https://www.cnblogs.com/tongye/p/10760154.html

 ===============================================================

std::basic_string

 
 
 
std::basic_string
 
Defined in header <string>
   
template<

    class CharT,
    class Traits std::char_traits<CharT>,
    class Allocator std::allocator<CharT>

class basic_string;
(1)  
namespace pmr {

template<
    class CharT,
    class Traits std::char_traits<CharT>
using basic_string =
    std::basic_string<CharT, Traits, std::pmr::polymorphic_allocator<CharT>>;

}
(2) (since C++17)
     

The class template basic_string stores and manipulates sequences of character-like objects, which are non-array objects of TrivialType and StandardLayoutType. The class is dependent neither on the character type nor on the nature of operations on that type. The definitions of the operations are supplied via the Traits template parameter - a specialization of std::char_traits or a compatible traits class.

The elements of a basic_string are stored contiguously, that is, for a basic_string s, &*(s.begin(+ n== &*s.begin(+ n for any n in [0​s.size()), and *(s.begin(+ s.size()) has value CharT() (a null terminator)(since C++11); or, equivalently, a pointer to s[0] can be passed to functions that expect a pointer to the first element of an array(until C++11)a null-terminated array(since C++11) of CharT.

std::basic_string satisfies the requirements of AllocatorAwareContainer (except that customized construct/destroy are not used for construction/destruction of elements), SequenceContainer and ContiguousContainer(since C++17).

If any of Traits::char_type and Allocator::char_type is different from CharT, the program is ill-formed.

Member functions of std::basic_string are constexpr: it is possible to create and use std::string objects in the evaluation of a constant expression.

However, std::string objects generally cannot be constexpr, because any dynamically allocated storage must be released in the same evaluation of constant expression.

(since C++20)

Several typedefs for common character types are provided:

Defined in header <string>
Type Definition
std::string std::basic_string<char>
std::wstring std::basic_string<wchar_t>
std::u8string (C++20) std::basic_string<char8_t>
std::u16string (C++11) std::basic_string<char16_t>
std::u32string (C++11) std::basic_string<char32_t>
std::pmr::string (C++17) std::pmr::basic_string<char>
std::pmr::wstring (C++17) std::pmr::basic_string<wchar_t>
std::pmr::u8string (C++20) std::pmr::basic_string<char8_t>
std::pmr::u16string (C++17) std::pmr::basic_string<char16_t>
std::pmr::u32string (C++17) std::pmr::basic_string<char32_t>

Template parameters

CharT - character type
Traits - traits class specifying the operations on the character type
Allocator - Allocator type used to allocate internal storage

Member types

Member type Definition
traits_type Traits
value_type CharT
allocator_type Allocator
size_type
Allocator::size_type (until C++11)
std::allocator_traits<Allocator>::size_type (since C++11)
difference_type
Allocator::difference_type (until C++11)
std::allocator_traits<Allocator>::difference_type (since C++11)
reference value_type&
const_reference const value_type&
pointer
Allocator::pointer (until C++11)
std::allocator_traits<Allocator>::pointer (since C++11)
const_pointer
Allocator::const_pointer (until C++11)
std::allocator_traits<Allocator>::const_pointer (since C++11)
iterator

LegacyRandomAccessIterator and LegacyContiguousIterator to value_type

(until C++20)

LegacyRandomAccessIteratorcontiguous_iterator, and ConstexprIterator to value_type

(since C++20)
const_iterator

LegacyRandomAccessIterator and LegacyContiguousIterator to const value_type

(until C++20)

LegacyRandomAccessIteratorcontiguous_iterator, and ConstexprIterator to const value_type

(since C++20)
reverse_iterator std::reverse_iterator<iterator>
const_reverse_iterator std::reverse_iterator<const_iterator>

Member functions

constructs a basic_string
(public member function)
destroys the string, deallocating internal storage if used
(public member function)
assigns values to the string
(public member function)
assign characters to a string
(public member function)
(C++23)
assign a range of characters to a string
(public member function)
returns the associated allocator
(public member function)
Element access
accesses the specified character with bounds checking
(public member function)
accesses the specified character
(public member function)
(DR*)
accesses the first character
(public member function)
(DR*)
accesses the last character
(public member function)
returns a pointer to the first character of a string
(public member function)
returns a non-modifiable standard C character array version of the string
(public member function)
returns a non-modifiable string_view into the entire string
(public member function)
Iterators
(C++11)
returns an iterator to the beginning
(public member function)
(C++11)
returns an iterator to the end
(public member function)
(C++11)
returns a reverse iterator to the beginning
(public member function)
(C++11)
returns a reverse iterator to the end
(public member function)
Capacity
checks whether the string is empty
(public member function)
returns the number of characters
(public member function)
returns the maximum number of characters
(public member function)
reserves storage
(public member function)
returns the number of characters that can be held in currently allocated storage
(public member function)
reduces memory usage by freeing unused memory
(public member function)
Modifiers
clears the contents
(public member function)
inserts characters
(public member function)
(C++23)
inserts a range of characters
(public member function)
removes characters
(public member function)
appends a character to the end
(public member function)
(DR*)
removes the last character
(public member function)
appends characters to the end
(public member function)
(C++23)
appends a range of characters to the end
(public member function)
appends characters to the end
(public member function)
replaces specified portion of a string
(public member function)
replaces specified portion of a string with a range of characters
(public member function)
copies characters
(public member function)
changes the number of characters stored
(public member function)
changes the number of characters stored and possibly overwrites indeterminate contents via user-provided operation
(public member function)
swaps the contents
(public member function)
Search
finds the first occurrence of the given substring
(public member function)
find the last occurrence of a substring
(public member function)
find first occurrence of characters
(public member function)
find first absence of characters
(public member function)
find last occurrence of characters
(public member function)
find last absence of characters
(public member function)
Operations
compares two strings
(public member function)
(C++20)
checks if the string starts with the given prefix
(public member function)
(C++20)
checks if the string ends with the given suffix
(public member function)
(C++23)
checks if the string contains the given substring or character
(public member function)
returns a substring
(public member function)

Constants

[static]
special value. The exact meaning depends on the context
(public static member constant)

Non-member functions

concatenates two strings or a string and a char
(function template)
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)
lexicographically compares two strings
(function template)
specializes the std::swap algorithm
(function template)
erases all elements satisfying specific criteria
(function template)
Input/output
performs stream input and output on strings
(function template)
read data from an I/O stream into a string
(function template)
Numeric conversions
(C++11)(C++11)(C++11)
converts a string to a signed integer
(function)
(C++11)(C++11)
converts a string to an unsigned integer
(function)
(C++11)(C++11)(C++11)
converts a string to a floating point value
(function)
(C++11)
converts an integral or floating-point value to string
(function)
(C++11)
converts an integral or floating-point value to wstring
(function)

Literals

Defined in inline namespace std::literals::string_literals
(C++14)
converts a character array literal to basic_string
(function)

Helper classes

hash support for strings
(class template specialization)

Deduction guides (since C++17)

Notes

Although it is required that customized construct or destroy is used when constructing or destroying elements of std::basic_string until C++23, all implementations only used the default mechanism. The requirement is corrected by P1072R10 to match existing practice.

Feature-test macroValueStdFeature
__cpp_lib_string_udls 201304L (C++14) User-defined literals for string types
__cpp_lib_starts_ends_with 201711L (C++20) starts_withends_with
__cpp_lib_constexpr_string 201907L (C++20) Constexpr for std::basic_string
__cpp_lib_char8_t 201907L (C++20) std::u8string
__cpp_lib_erase_if 202002L (C++20) eraseerase_if
__cpp_lib_string_contains 202011L (C++23) contains
__cpp_lib_string_resize_and_overwrite 202110L (C++23) resize_and_overwrite
__cpp_lib_containers_ranges 202202L (C++23) Member functions for construction, insertion, and replacement that accept container compatible range

Example

#include <iostream>
#include <string>
 
int main()
{
    using namespace std::literals;
 
    // Creating a string from const char*
    std::string str1 = "hello";
 
    // Creating a string using string literal
    auto str2 = "world"s;
 
    // Concatenating strings
    std::string str3 = str1 + " " + str2;
 
    // Print out the result
    std::cout << str3 << '\n';
 
    std::string::size_type pos = str3.find(" ");
    str1 = str3.substr(pos + 1); // the part after the space
    str2 = str3.substr(0, pos);  // the part till the space
 
    std::cout << str1 << ' ' << str2 << '\n';
 
    // Accessing an element using subscript operator[]
    std::cout << str1[0] << '\n';
    str1[0] = 'W';
    std::cout << str1 << '\n';
}

Output:

hello world
world hello
w
World

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DRApplied toBehavior as publishedCorrect behavior
LWG 530 C++98 contiguity of the storage for elements of basic_string
was accidently made not required by LWG259
required again
LWG 2994
(P1148R0)
C++98 the behavior is undefined if any of Traits::char_type[1]
and Allocator::char_type is different from CharT
the program is
ill-formed in this case
  1.  The Traits::char_type case is fixed in P1148R0.

See also

read-only string view
(class template)

https://en.cppreference.com/w/cpp/string/basic_string

===================

文章目录
前言
1. string的构造方法
1.1 无参构造
1.2 字符数组构造
2. string的赋值
2.1 数据源为字符数组
2.2 数据源为string
2.3 构造方法和赋值中的细节
3. string的存取
4. string的拼接
5. string的查找
5.1 find方法
5.2 string::npos
5.2 find方法的底层
6. string的替换
7. string的比较
8. string的长度
9. string的插入
10. string的删除
11. string的子串获取
12. string与基本数据类型之间的转换
12.1 基本数据类型转string
12.2 string转基本数据类型
12.3 知识点补充——浮点数的格式化输出
12.3.1 C++风格
12.3.2 C风格
13. string转C风格的字符串
前言
string是C++风格的字符串,本质上是一个类,它的内部封装了char *,是一个char *型的容器

使用string需要包含<string>头文件

string的内部封装了很多方法,本文将重点介绍string的一些常用方法,这些方法足以应对日常的刷题和比赛

1. string的构造方法
1.1 无参构造
#include <iostream>
#include <string>

using namespace std;

int main() {
string str;
cout << "str = " << str << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
1.2 字符数组构造
#include <iostream>
#include <string>

using namespace std;

int main() {
char words[15] = {"Hello World"};
string str(words);
cout << "str = " << str << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
2. string的赋值
string类重载了赋值符号

string的赋值本质上是将数据源的内容拷贝一份放到string里,修改string的值并不会影响数据源

2.1 数据源为字符数组
#include <iostream>
#include <string>

using namespace std;

int main() {
string str;
char words[15] = {"Hello"};
str = words;
cout << "str = " << str << endl;

str[0] = 'h';
cout << "str = " << str << endl;
cout << "words = " << words << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
输出结果为

str = Hello
str = hello
words = Hello
1
2
3
2.2 数据源为string
#include <iostream>
#include <string>

using namespace std;

int main() {
string src = "Hello World";
string destination;
destination = src;
cout << "destination = " << destination << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
2.3 构造方法和赋值中的细节
先看以下代码

#include <iostream>
#include <string>

using namespace std;

int main() {
string src = "Hello World";
string destination = src;
cout << "destination = " << destination << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
虽然代码string destination = src;看起来是src为destination赋值,但是经过编译器优化后,该句代码等价于string destination(src);,也就是说,该句代码本质上是调用了string类的构造方法,而不是赋值操作

我们可以使用自定义的类来验证

#include <iostream>

using namespace std;

class Student {
public:
int age;
double height;

public:
Student() {
this->age = 0;
this->height = 0.0;
}

Student(const Student &anotherStudent) {
cout << "拷贝构造函数" << endl;
this->age = anotherStudent.age;
this->height = anotherStudent.height;
}

Student &operator=(const Student &anotherStudent) {
cout << "重载赋值符号" << endl;
this->age = anotherStudent.age;
this->height = anotherStudent.height;
return *this;
}
};

int main() {
Student tom;
tom.age = 18;
tom.height = 180;

Student jerry = tom;
cout << "jerry.age = " << jerry.age << endl;
cout << "jerry.height = " << jerry.height << endl;

Student amy;
amy = tom;
cout << "amy.age = " << amy.age << endl;
cout << "amy.height = " << amy.height << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
输出结果为

拷贝构造函数
jerry.age = 18
jerry.height = 180
重载赋值符号
amy.age = 18
amy.height = 180
1
2
3
4
5
6
3. string的存取
string类重载了[]符号

#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello,World";
cout << "str[0] = " << str[0] << endl;
str[0] = 'h';
cout << "str[0] = " << str[0] << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
4. string的拼接
string类重载了+和+=符号,可以接收字符数组、字符、string、字符串等类型的变量

#include <iostream>
#include <string>

using namespace std;

int main() {
string str01;
char words[15] = {"Hello"};
str01 += words;
cout << "str01 = " << str01 << endl;

char ch = ',';
str01 += ch;
cout << "str01 = " << str01 << endl;

string temp = "World";
str01 += temp;
cout << "str01 = " << str01 << endl;

str01 += "!";
cout << "str01 = " << str01 << endl;

string str02;
str02 = str02 + words + ch + temp + "!";
cout << "str02 = " << str02 << endl;

return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
输出结果为

str01 = Hello
str01 = Hello,
str01 = Hello,World
str01 = Hello,World!
str02 = Hello,World!
1
2
3
4
5
5. string的查找
5.1 find方法
string类的find方法有多个重载版本,我们只学习它的基本用法

find方法可以接收string、字符、字符数组三种类型的参数

#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello,World Hello,World! Hello,World!";

string temp = "Hello";
char ch = ',';
char words[15] = "World";

int index = str.find(temp);
cout << "index = " << index << endl;

index = str.find(ch);
cout << "index = " << index << endl;

index = str.find(words);
cout << "index = " << index << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
输出结果为

index = 0
index = 5
index = 6
1
2
3
上述的find方法只接收一个参数,默认是从下标0开始寻找子串

如果我们想从特定的位置开始寻找子串,我们可以填入开始寻找的下标作为find方法的第二个参数

配合循环,我们就可以在母串中找到所有子串的开始位置

#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello,World Hello,World! Hello,World!";
int start = 0;

while (true) {
int index = str.find("Hello", start);
if (index == -1) {
break;
}
cout << "index = " << index << endl;
start = index + 5;
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
输出结果为

index = 0
index = 12
index = 25
1
2
3
5.2 string::npos
当使用string类的find方法查找不到子串时,find方法将会返回string::npos

string::npos的类型本质上是unsigned long long,而且string::nops的数位(二进制)都是1,也就是说string::npos的值为264-1,即18,446,744,073,709,551,615

当我们用int、long、long long等有符号整形变量去接收string::npos时,该有符号整形变量的数位(二进制)将全变成1,而-1的补码也全部为1,所以该有符号整形变量的值也就变成了-1

因此我们可以根据find方法是否返回-1或string::npos来判断是否寻找到子串

#include <iostream>
#include <string>

using namespace std;

int main() {
cout << "string::npos = " << string::npos << endl;

string str = "Hello,World";
if (-1 == str.find("Tom")) {
cout << "Can not find subStr Tom" << endl;
}

if (string::npos == str.find("Jerry")) {
cout << "Can not find subStr Jerry" << endl;
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
输出结果为

string::npos = 18446744073709551615
Can not find subStr Tom
Can not find subStr Jerry
1
2
3
5.2 find方法的底层
find方法的底层并没有采用KMP算法等更高效的字符串匹配算法

find方法使用的是朴素的线性搜索算法,也就是逐个字符比对,时间复杂度大约为 O(n*m) ,其中 n 为母串长度,m 为子串长度。

6. string的替换
string的替换主要是使用replace方法,replace方法也有很多个重载版本,我们只学习它的基本用法

常规的replace方法接收三个参数

第一个参数为替换的起始下标
第二个参数为替换的长度
第三个参数为新的字符串,该字符串可以是string类,也可以是字符数组
#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello,World";
string str01 = "hello";
char str02[15] = "world";

str.replace(0, str01.length(), str01);
cout << "str = " << str << endl;

str.replace(6, 5, str02);
cout << "str = " << str << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
输出结果

str = hello,World
str = hello,world
1
2
7. string的比较
string类重载了>=、<=、>、<、!=、==符号,使得string类在进行字符串比较时可以接收char数组类型或string类型的参数

string类的比较是将两个字符串的字符从左到右逐个比较(比较的依据是字符的ASCII码值),直到两个字符串出现不同的字符或者两个字符串中的每个字符都比较完之后返回

string类在进行字符串的比较时会返回三个值

-1,第一个字符串小于第二个字符串
0,第一个字符串等于第二个字符串
1,第一个字符串大于第二个字符串
#include <iostream>
#include <string>

using namespace std;

int main() {
string str01 = "Hello,World";
string str02 = "hello,World";
char str03[20] = "Hello,world";

cout << (str01 == str02) << endl;
cout << (str01 > str03) << endl;
cout << (str02 > str03) << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
输出结果

0
0
1
1
2
3
8. string的长度
使用string类的length方法或size方法可以得到string的长度

#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello,World";
cout << "str.length() = " << str.length() << endl;
cout << "str.size() = " << str.size() << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
输出结果

str.length() = 11
str.size() = 11
1
2
9. string的插入
string的插入使用的是insert方法,insert方法也有很多个重载版本,我们只学习它的基本用法

常规的insert方法接收两个参数

第一个参数为插入的起始位置
第二个参数为要插入的字符串,类型可以是char数组或string
#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello";
str.insert(5, "World");
cout << str << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
输出结果为

HelloWorld
1
10. string的删除
string的插入使用的是erase方法,该方法主要有两个版本

第一个版本接收两个参数

第一个参数为起始坐标
第二个参数为要删除的长度
第二个版本只接收一个参数,该参数为起始坐标,使用该版本将会清空起始位置及之后的所有字符

#include <iostream>
#include <string>

using namespace std;

int main() {
string str01 = "HelloWorld!";
str01.erase(5, 5);
cout << str01 << endl;

string str02 = "HelloWorld!";
str02.erase(5);
cout << str02 << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
输出结果为

Hello!
Hello
1
2
11. string的子串获取
string的子串获取主要使用substr方法,该方法接收两个参数

第一个参数为起始的位置
第二个参数为截取的长度
如果省略第二个参数,将会截取从起始位置开始到字符串结尾的整个子串

#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "HelloWorld!";
cout << "str.substr(5, 5) = " << str.substr(5, 5) << endl;
cout << "str.substr(5) = " << str.substr(5) << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
输出结果为

str.substr(5, 5) = World
str.substr(5) = World!
1
2
12. string与基本数据类型之间的转换
注意:以下介绍的string与基本数据类型之间相互转换的方法是在C++11之后才出现的,在C++11之前的版本中使用以下方法程序将会报错

12.1 基本数据类型转string
基本数据类型转string使用的是to_string方法

#include <iostream>
#include <string>

using namespace std;

int main() {
int number = 8848;
long long date = 20202020;
double pi = 3.1415926;

string NUMBER = to_string(number);
string DATE = to_string(date);
string PI = to_string(pi);

cout << "NUMBER = " << NUMBER << endl;
cout << "DATE = " << DATE << endl;
cout << "PI = " << PI << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
输出结果为

NUMBER = 8848
DATE = 20202020
PI = 3.141593
1
2
3
12.2 string转基本数据类型
这里主要介绍string转换成int、long long、double,string,转成其它基本数据类型的方法可以类比

stoi方法(string to int),将string转为int
stoll方法(string to long long),将string转为long long
stod方法(string to double),将string转为double
#include <iostream>
#include <string>

using namespace std;

int main() {
string intStr = "8848";
string timeStr = "202002202020";
string piStr = "3.1415926";

cout << "stoi(intStr) = " << stoi(intStr) << endl;
cout << "stoll(timeStr) = " << stoll(timeStr) << endl;
cout << "stod(piStr) = " << stod(piStr) << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
输出结果为

stoi(intStr) = 8848
stoll(timeStr) = 202002202020
stod(piStr) = 3.14159
1
2
3
12.3 知识点补充——浮点数的格式化输出
当浮点数的总长度大于等于7(包括小数点)时,C/C++程序输出浮点数的格式会千奇百怪,下面介绍两种格式化输出浮点数的方法

12.3.1 C++风格
我们可以借助<iomanip>头文件来控制浮点数的输出格式

setw:总长度
setfill:浮点数的位数不够时自动填充的字符
setprecision:保留的精度
fixed:修饰符,配合setprecision使用,表示以固定小数位输出,如果不加这个修饰符,浮点数可能会以科学计数法的形式输出
setiosflags:设置对齐方向,默认为右对齐
#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

int main() {
string piStr = "3.1415926";

double pi = stod(piStr);
cout << "************" << endl; // 12个*
cout << setw(12) << setfill('\0') << setprecision(8) << fixed << setiosflags(ios::left) << pi << endl;
cout << setw(12) << setfill('\0') << setprecision(8) << fixed << setiosflags(ios::right) << pi << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
输出结果为

************
3.14159260
3.14159260
1
2
3
12.3.2 C风格
可以使用C语言的printf来控制浮点数的输出格式

格式为%width.precisionlf
width为输出的浮点数的总宽度,包括小数点,当浮点数的宽度小于width时,会自动填充'\0'字符(width参数可以省略)
precision为保留的小数位数
浮点数的小数位数小于precision时会自动在浮点数后面补0
如果width小于等于precision,width参数将不起作用
#include <cstdio>

using namespace std;

int main() {
double pi = 3.1415926;

printf("************\n");
printf("%12.8lf\n", pi); // 默认是右对齐
printf("%-12.8lf\n", pi); // 左对齐
printf("%.8lf\n", pi); // 省略width
printf("%6.8lf\n", pi); // precision >= width

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
输出结果为

************
3.14159260
3.14159260
3.14159260
3.14159260
1
2
3
4
5
13. string转C风格的字符串
string类的c_str()方法返回一个指向以'\0'结尾的字符数组的指针,该字符数组包含了与string对象相同的字符序列。

#include <iostream>
#include <string>

using namespace std;

int main() {
string str = "Hello, World!";

const char *cstr = str.c_str();
cout << cstr << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
注意,c_str()方法返回的C风格字符串指针指向的内存是由string对象管理的,因此在string对象的生命周期内,该C风格字符串是有效的。
如果string对象被销毁或修改,那么之前返回的C风格字符串指针将不再有效。

先看以下代码

#include <iostream>
#include <string>

using namespace std;

const char *cstr;

void function() {
string str = "Hello,World!";
cstr = str.c_str();
}

int main() {
function();

cout << cstr << endl;
cout << cstr << endl;
cout << cstr << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
以上代码在function()函数中创建了一个局部的string对象str,并将c_str()方法返回的指针赋值给全局变量cstr。

然而,当function()函数结束时,局部变量str将被销毁,这意味着cstr现在指向的内存区域已经不再有效。

因此,当在main()函数中试图通过cout输出cstr时,程序正在访问已经被释放的内存,这是未定义的行为,可能会导致程序崩溃或输出不可预测的结果。

当然,如果你拷贝上述代码到自己电脑上运行,大概率是没有问题的。

以下是GPT4.0给出的分析和改进后的代码

虽然你的代码在运行时没有报错,但这并不意味着代码是正确的。

你的代码中存在未定义行为,这意味着程序可能会以任何方式运行,包括看似“正常”运行。

在你的例子中,尽管str已经被销毁,但其内存可能尚未被操作系统回收或重新分配给其他对象,因此你可能仍然能够看到原来的内容。

然而,这是非常不安全的,因为你无法预测何时这块内存会被重新分配。

因此,你应该避免这种未定义行为,确保你的代码总是安全、可预测的。

#include <iostream>
#include <string>

using namespace std;

string function() {
string str = "Hello, World!";
return str;
}

int main() {
string str = function();

const char *cstr = str.c_str();

std::cout << cstr << std::endl;
std::cout << cstr << std::endl;
std::cout << cstr << std::endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
文章知识点与官方知识档案匹配,可进一步学习相关知识
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_62128476/article/details/133753296

===============

来自:

https://www.cnblogs.com/tongye/p/10760154.html

https://en.cppreference.com/w/cpp/string/basic_string

https://en.cppreference.com/w/cpp/string/basic_string/stol

 

posted @ 2024-03-29 10:00  redrobot  阅读(8)  评论(0编辑  收藏  举报