std::字符串 有一些缺点,最常见的情况之一是常量字符串。下面的程序演示了使用 std:: 字符串处理常量字符串时出现的问题:
方案一:
C++
// C++ program to demonstrate the
// problem occurred in string
#include
#include
using namespace std;
// Driver Code
int main()
{
char str_1[]{ "Hello !!, GeeksforGeeks" };
string str_2{ str_1 };
string str_3{ str_2 };
// Print the string
cout << str_1 << '\n'
<< str_2 << '\n'
<< str_3 << '\n';
return 0;
}
C++
// C++ program to implement
// the above approach
#include
using namespace std;
#include
// Driver code
int main()
{
// View the text "hello", which is
// stored in the binary
string_view str_1{ "Hello !!, GeeksforGeeks" };
// View of the same "hello"
string_view str_2{ str_1 };
// View of the same "hello"
string_view str_3{ str_2 };
std::cout << str_1 << '\n ' << str_1 << '\n ' << str_3 << '\n';
return 0;
}
C++
// C++ program for the above approach
#include
#include
#include
using namespace std;
string_view sur_name(wstring_view x)
{
return x.substr(6);
}
// Driver Code
int main()
{
// Basic_string_view wstr
// (L"Madhav_Mohan"); both are equivalent
const wchar_t* str1{ L"Madhav_Mohan" };
cout << your_name(str1);
return 0;
}
C++
// C++ program to implement
// the above approach
#include
#include
using namespace std;
string to_alpha(int r)
{
if (r < 0)
return " less than ";
else if (r == 0)
return " equal to ";
else
return " greater than ";
}
// Driver code
int main()
{
char str{ "Muddy" };
char str_1{ "Maddy" };
string_view str_2{ str_1 };
// This line prints Maddy
cout << str_2 << '\n';
// Change 'M' to 'D' in arr
str_1[0] = 'D';
// This line prints Daddy
cout << str_2 << '\n';
cout << str_2.at(2);
cout << str_2.back();
cout << " is last char of str_2 is y " << (str_2.back() == 's');
cout << " is last char of str_2 is y " << boolalpha << (str_2.back() == 's');
// In above statement boolalpha is
// used to give the boolean result
// in True or False
int cmp{ str_1.compare(str_2) };
cout << to_alpha(cmp
};
int cmp_1 = str.compare(1, 4, str_2);
cout << "last three characters of str are" << to_alpha(cmp_1) << "str_2.\n";
return 0;
}
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
// Driver code
int main()
{
string_view str_1{ "Maddy" };
cout << str_1 << '\n';
string_view str_2{ "Daddy" };
cout << str_2 << '\n';
string_view var{ "Hello !!, GeeksforGeeks" };
cout << var << '\n';
cout << var.starts_with("Hi !!") << '\n';
cout << var.ends_with("GeeksforGeeks !!") << '\n';
// Remove the first characters.
str_1.remove_prefix(1);
cout << str_1 << '\n';
// Remove the last 2 characters.
str_1.remove_suffix(2);
std::cout << str_1 << '\n';
return 0;
}
C++
// C++ program to implement the
// above approach
#include
#include
#include
#include
#include
#include
using namespace std;
// Driver code
int main()
{
constexpr string_view str{ "Daddy" };
constexpr string_view str1{ "Maddy" };
string str2{};
// Copy data of str1 into str2
str1.copy(str2.data(), 4);
// This line prints Madddy
cout << str2.data() << '\n';
if ((str.compare(str2)) != 0)
cout << str << " "
<< "doesn't = to"
<< " " << str1 << '\n';
cout << str1.starts_with("Mad");
cout << '\n'
<< str.starts_with("Pad") << '\n';
cout << str1.ends_with("ddt");
cout << '\n'
<< str.ends_with("ddy") << '\n';
// Checks whether the given string contains
// the given substring or character
constexpr string_view s1{ "Hello! Madhav" };
// Position of the first character that
// match first
constexpr string_view str3{ "Hi! Maddy" };
size_t found = str3.find(str1);
cout << found << '\n';
// Find the last occurrence of a substring
cout << '\n'
<< str3.rfind('d');
// Gives the first time occured char's position
cout << '\n'
<< str3.find_first_of("d");
// Gives the last time occured char's position
cout << '\n'
<< str3.find_last_of("d");
// Finds the first char that's not equal to
// any of the char(s) in the given string
cout << '\n'
<< str3.find_last_not_of(str, 6);
// It givesIndex of first unmatched character
// when successful or string::npos if no such
// character found. It searches for the first
// char that doesn't match any of the char(s)
// that has given in the arguement
cout << '\n'
<< str3.find_last_not_of(str, 4);
return 0;
}
C++
// C++ program to implement
// the above approach
#include
// For std::size
#include
#include
using namespace std;
// Driver code
int main()
{
// No null-terminator.
char name[]{ 'M', 'a', 'd',
'h', 'a', 'v' };
// Here name isn't null-terminated.
// We need to pass the length manually.
// Because name is an array, we can
// use std::size to get its length.
string_view str_1{ \name, size(name) };
// This is safe and cout knows how to
// print std::string_views.
cout << str_1 << '\n';
return 0;
}
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
void print(string s)
{
cout << s << '\n';
}
// Driver code
int main()
{
string_view str_1{ "Madhav" };
str_1.remove_suffix(3);
// compile error: won't implicitly
// convert
// print(str_1);
// explicit conversion
string str_2{ str_1 };
print(str_2);
// It'll work
print(static_cast(str_1));
return 0;
}
C++
// C++ program to implement
// the above approach
#include
#include
#include
#include
// Driver code
int main()
{
string_view str_1{ "Madhav" };
str_1.remove_suffix(3);
// Create a std::string from
// the std::string_view
string str_2{ str_1 };
// A Null_terminated C-style string.
auto Null_Terminated{ str_2.c_str() };
// Pass the null-terminated string
// to the function that we want to use.
cout << str_2 << " has " << strlen(Null_Terminated) << " letter's\n";
return 0;
}
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
string_view ask_name()
{
cout << "Write your surname?\n";
// A std::string is needed, because
// std::cin needs to modify it.
string str_1{};
cin >> str_1;
// Pass str_1 to std::string_view
string_view str_2{ str_1 };
cout << str_2 << '\n';
// str_1 dies, and so does the
// string that str created.
return str_2;
}
// Driver code
int main()
{
std::string_view str_2{ ask_name() };
// str_2 is observing a string that
// already died.
// Undefined behavior you'll observe
cout << your surname is << str_2 << '\n';
return 0;
}
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
#include
// Driver code
int main()
{
string str{ "Madhav_Mohan" };
string_view str1{ str.data() };
cout << str1 << endl;
string_view str2{ str1.substr(6) };
string_view str3{ str2 };
cout << str3;
return 0;
}
输出:
说明:输出与预期相同。但是,为了两次查看“Hello !!, GeeksforGeeks” , std::字符串在内存上执行了两次开销。但这里的任务是读取字符串(“Hello !!, GeeksforGeeks”) ,不需要对其进行写操作。所以只是为了显示一个字符串为什么要多次分配内存。为了更有效地处理字符串,C++17 提出了std::string_view() ,它提供了预定义 char str[] 的视图,而无需向内存创建新对象。
std:: 字符串 的缺点:在上面的例子中,相同的字符串str_1通过分配两个不同的字符串变量被打印两次。因此,对于变量str_2和str_3 ,内存是使用静态内存分配分配的,这会导致我们的内存开销两次。
std::string_view 的好处:
- 轻便且便宜: std::string_view非常轻便、便宜,主要用于提供字符串的视图。每当创建string_view 时,都不需要以上述示例中的方式复制字符串,这种方式效率低下并导致内存开销。它使字符串的复制过程非常有效,并且当在查看的字符串中进行修改时,永远不会创建字符串的任何副本,所做的更改已出现在std::string_view 中。
- 更好的性能: std::string_view比 const std::string&更好,因为它消除了在字符串开头有std:: 字符串对象的约束,因为std::string_view由两个元素组成,第一个是const char*指向数组的起始位置,第二个是size 。
- 支持必不可少的函数:标准:: string_view支持大部分是被施加在STD所有关键函数::字符串如SUBSTR,比较,发现,重载运算符(如==,<,> =!)。因此,在大多数情况下,当我们的首选项为只读时,它消除了具有 std:: 字符串对象声明的约束。
std::string_view : C++17 库提出了一种标准类型的字符串( std::string_view ),它不同于通常的 std:: 字符串。
- 在std :: string_view提供了一种轻量级对象,提供只读字符串或字符串的一部分的访问使用类似于标准:: _串的接口的接口,并且仅仅是指连续的炭序列。与 std:: 字符串保留自己的字符串副本不同,它还提供了在源代码中其他地方定义的字符串的视图。
- 它由两个成员组成:指向 char 数组开头的const char*和 _size。它是对字符串本身的非拥有引用。
- 在header(#include
)中定义,std::string_view类模板如下:
template
The class template string_view explains about an object that can refer to a constant contiguous sequence of char’s or array of char’s -like objects with the first element of the sequence at position zero.
以下是使用std::string_view的上述源代码的确切版本:
方案二:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
#include
// Driver code
int main()
{
// View the text "hello", which is
// stored in the binary
string_view str_1{ "Hello !!, GeeksforGeeks" };
// View of the same "hello"
string_view str_2{ str_1 };
// View of the same "hello"
string_view str_3{ str_2 };
std::cout << str_1 << '\n ' << str_1 << '\n ' << str_3 << '\n';
return 0;
}
输出-
说明:输出将与上面相同,但不会在内存中创建字符串“Hello !!, GeeksforGeeks”的更多副本。
std::string_view 中的参数:
字符类型:
char类型定义了存储在string_view字符的类型。 C++ 标准库为上述模板的特化提供了以下类型定义。
- string_view用于char类型的元素
- wstring_view ,用于wchar_t
- u16string_view用于char16_t
- u32string_view用于char32_t
下面是说明 Char 类型的 C++ 程序:
方案三:
C++
// C++ program for the above approach
#include
#include
#include
using namespace std;
string_view sur_name(wstring_view x)
{
return x.substr(6);
}
// Driver Code
int main()
{
// Basic_string_view wstr
// (L"Madhav_Mohan"); both are equivalent
const wchar_t* str1{ L"Madhav_Mohan" };
cout << your_name(str1);
return 0;
}
输出-
std::string_view示例:下面的示例表明,大多数基于字符串的函数都可以与 std::string_view 一起使用,如str.compare() 、 str.back() 、 str.cend()和str 。 at()函数。
程序4:
C++
// C++ program to implement
// the above approach
#include
#include
using namespace std;
string to_alpha(int r)
{
if (r < 0)
return " less than ";
else if (r == 0)
return " equal to ";
else
return " greater than ";
}
// Driver code
int main()
{
char str{ "Muddy" };
char str_1{ "Maddy" };
string_view str_2{ str_1 };
// This line prints Maddy
cout << str_2 << '\n';
// Change 'M' to 'D' in arr
str_1[0] = 'D';
// This line prints Daddy
cout << str_2 << '\n';
cout << str_2.at(2);
cout << str_2.back();
cout << " is last char of str_2 is y " << (str_2.back() == 's');
cout << " is last char of str_2 is y " << boolalpha << (str_2.back() == 's');
// In above statement boolalpha is
// used to give the boolean result
// in True or False
int cmp{ str_1.compare(str_2) };
cout << to_alpha(cmp
};
int cmp_1 = str.compare(1, 4, str_2);
cout << "last three characters of str are" << to_alpha(cmp_1) << "str_2.\n";
return 0;
}
输出:
std::string_view 的修改:在 C++20 中添加了一些新函数,如 str.remove_suffix(),使用这些函数的 str.remove_suffix() 可以修改 std::string_view。 Like 可以删除给定字符串的选择性后缀或前缀。
计划5:
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
// Driver code
int main()
{
string_view str_1{ "Maddy" };
cout << str_1 << '\n';
string_view str_2{ "Daddy" };
cout << str_2 << '\n';
string_view var{ "Hello !!, GeeksforGeeks" };
cout << var << '\n';
cout << var.starts_with("Hi !!") << '\n';
cout << var.ends_with("GeeksforGeeks !!") << '\n';
// Remove the first characters.
str_1.remove_prefix(1);
cout << str_1 << '\n';
// Remove the last 2 characters.
str_1.remove_suffix(2);
std::cout << str_1 << '\n';
return 0;
}
输出:
下面是一些可以用 std::string_view 执行的其他操作的例子:
计划6:
C++
// C++ program to implement the
// above approach
#include
#include
#include
#include
#include
#include
using namespace std;
// Driver code
int main()
{
constexpr string_view str{ "Daddy" };
constexpr string_view str1{ "Maddy" };
string str2{};
// Copy data of str1 into str2
str1.copy(str2.data(), 4);
// This line prints Madddy
cout << str2.data() << '\n';
if ((str.compare(str2)) != 0)
cout << str << " "
<< "doesn't = to"
<< " " << str1 << '\n';
cout << str1.starts_with("Mad");
cout << '\n'
<< str.starts_with("Pad") << '\n';
cout << str1.ends_with("ddt");
cout << '\n'
<< str.ends_with("ddy") << '\n';
// Checks whether the given string contains
// the given substring or character
constexpr string_view s1{ "Hello! Madhav" };
// Position of the first character that
// match first
constexpr string_view str3{ "Hi! Maddy" };
size_t found = str3.find(str1);
cout << found << '\n';
// Find the last occurrence of a substring
cout << '\n'
<< str3.rfind('d');
// Gives the first time occured char's position
cout << '\n'
<< str3.find_first_of("d");
// Gives the last time occured char's position
cout << '\n'
<< str3.find_last_of("d");
// Finds the first char that's not equal to
// any of the char(s) in the given string
cout << '\n'
<< str3.find_last_not_of(str, 6);
// It givesIndex of first unmatched character
// when successful or string::npos if no such
// character found. It searches for the first
// char that doesn't match any of the char(s)
// that has given in the arguement
cout << '\n'
<< str3.find_last_not_of(str, 4);
return 0;
}
输出:
非空终止字符串:与 C 字符串和 std::字符串 需要一个字符串终止符 (‘\0’) 在字符串的末尾, std::string_view 不需要空终止符来标记字符串。因为它会跟踪字符串长度。
下面是实现上述方法的 C++ 程序:
程序 7:
C++
// C++ program to implement
// the above approach
#include
// For std::size
#include
#include
using namespace std;
// Driver code
int main()
{
// No null-terminator.
char name[]{ 'M', 'a', 'd',
'h', 'a', 'v' };
// Here name isn't null-terminated.
// We need to pass the length manually.
// Because name is an array, we can
// use std::size to get its length.
string_view str_1{ \name, size(name) };
// This is safe and cout knows how to
// print std::string_views.
cout << str_1 << '\n';
return 0;
}
输出:
将 std::string_view 转换为 std:: 字符串 :需要使用显式转换方法,因为隐式转换在这里无济于事。
下面是实现 std::string_view 到 std:: 字符串转换的 C++ 程序:
程序8:
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
void print(string s)
{
cout << s << '\n';
}
// Driver code
int main()
{
string_view str_1{ "Madhav" };
str_1.remove_suffix(3);
// compile error: won't implicitly
// convert
// print(str_1);
// explicit conversion
string str_2{ str_1 };
print(str_2);
// It'll work
print(static_cast(str_1));
return 0;
}
输出:
将 std::string_view 转换为 C 风格的字符串: strlen() 等函数,这些函数需要一个 C 风格的字符串才能使用。因此,每当需要将 std::string_view 转换为 C 风格的字符串,都可以通过首先转换为 std:: 字符串来完成。
下面是实现上述方法的 C++ 程序:
程序 9:
C++
// C++ program to implement
// the above approach
#include
#include
#include
#include
// Driver code
int main()
{
string_view str_1{ "Madhav" };
str_1.remove_suffix(3);
// Create a std::string from
// the std::string_view
string str_2{ str_1 };
// A Null_terminated C-style string.
auto Null_Terminated{ str_2.c_str() };
// Pass the null-terminated string
// to the function that we want to use.
cout << str_2 << " has " << strlen(Null_Terminated) << " letter's\n";
return 0;
}
输出:
范围的问题性病:: string_view:在std :: string_view提供的视图,因此它保持独立,其中它提供了一个视图的字符串的,并且除非观看字符串是在范围,而是在情况下,如果它伸出的字符串的视图查看的字符串范围消失,然后 std::string_view 没有任何可投影的内容,因此它显示未定义的行为。 std::string_view 总是需要一个或已经由STD创建一个字符串,字符串:: 在范围内以投影字符串的视图,但是一旦范围终止 std::string_view 就无法自行创建任何字符串,因为它只是一个视图。
下面是实现上述方法的示例:
计划10:
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
string_view ask_name()
{
cout << "Write your surname?\n";
// A std::string is needed, because
// std::cin needs to modify it.
string str_1{};
cin >> str_1;
// Pass str_1 to std::string_view
string_view str_2{ str_1 };
cout << str_2 << '\n';
// str_1 dies, and so does the
// string that str created.
return str_2;
}
// Driver code
int main()
{
std::string_view str_2{ ask_name() };
// str_2 is observing a string that
// already died.
// Undefined behavior you'll observe
cout << your surname is << str_2 << '\n';
return 0;
}
输出:
使用 data() 执行 std::string_view函数: data()函数将字符串的字符写入数组。它返回一个指向数组的指针,该指针是从字符串到数组的转换中获得的。它的返回类型不是有效的 C 字符串,因为在数组末尾没有附加 ‘\0’字符。
下面是实现上述方法的 C++ 程序:
计划 11:
C++
// C++ program to implement
// the above approach
#include
#include
#include
using namespace std;
#include
// Driver code
int main()
{
string str{ "Madhav_Mohan" };
string_view str1{ str.data() };
cout << str1 << endl;
string_view str2{ str1.substr(6) };
string_view str3{ str2 };
cout << str3;
return 0;
}
输出:
非成员函数:
operator==
operator!= (has been removed in C++20)
operator< (has been removed in C++20)
operator> (has been removed in C++20)
operator<= (has been removed in C++20)
operator>= (has been removed in C++20)
operator<=> (has newly been included C++20)
注意: Std::string_view 仅在 C++17 或以上版本中运行。有许多与 std::string_view 合并的函数,其中一些是新的(C++20),一些是旧的。在下面,我引用了 web_address,您可以在其中深入了解它们。