变量 » 字符串 » 常见问题
忘记包含头文件
int main()
{
std::string s = "Hello";
}
可能的错误消息
- GCC
- MSVC
In function 'int main()':
error: 'string' is not a member of 'std'
2 | std::string s = "Hello";
| ^~~~~~
note: 'std::string' is defined in header '<string>'; did you forget to '#include <string>'?
+++ |+#include <string>
1 | int main() {
error C2039: 'string': is not a member of 'std'
predefined C++ types (compiler internal)(339): message : see declaration of 'std'
error C2065: 'string': undeclared identifier
解决方案
在文件顶部添加 #include <string>
。
将数字视为字符串
#include <string>
int main()
{
std::string s = 123;
}
可能的错误消息:
- GCC
- MSVC
In function 'int main()':
error: conversion from 'int' to non-scalar type 'std::string' {aka 'std::__cxx11::basic_string<char>'} requested
4 | std::string s = 123;
| ^~~
error C2440: 'initializing': cannot convert from 'int' to 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>'
note: No constructor could take the source type, or constructor overload resolution was ambiguous
解决方案
使用 std::to_string
将整数转换为字符串。有关更多信息,请参阅数字和字符串之间的转换以及数字和字符串。
将字符串视为数字
#include <string>
int main()
{
std::string s = "123";
s *= 15;
}
可能的错误消息:
- GCC
- MSVC
In function 'int main()':
error: no match for 'operator*=' (operand types are 'std::string' {aka 'std::__cxx11::basic_string<char>'} and 'int')
5 | s *= 15;
| ~~^~~~~
error C2676: binary '*=': 'std::string' does not define this operator or a conversion to a type acceptable to the predefined operator
解决方案
使用 std::stoi
或 std::stof
将字符串转换为代数数值。有关更多信息,请参阅数字和字符串之间的转换以及数字和字符串。
连接两个字符串字面量
#include <string>
int main()
{
std::string s = "Hello " + "World";
}
可能的错误消息:
- GCC
- MSVC
In function 'int main()':
error: invalid operands of types 'const char [7]' and 'const char [6]' to binary 'operator+'
5 | std::string s = "Hello " + "World";
| ~~~~~~~~ ^ ~~~~~~~
| | |
| | const char [6]
| const char [7]
error C2110: '+': cannot add two pointers
解决方案
无论何时你在 C++ 文件中看到 "TEXT"
,这都被称为一个 字符串字面量。基本上,这是一个花哨的术语,表示这是一个硬编码的文本值。然而,关键的是,字符串字面量的类型不是 std::string
。相反,它是 const char[N]
,其中 N
是文本长度 + 1。上面的 GCC 错误最好地说明了这一点。
const char[N]
称为一个 数组。我们将在后面的章节中介绍数组,但这里重要的知识是,你不能将两个数组相加,因为它们不是数字。std::string
为我们提供了通过 +
连接字符串的能力。
最简单的解决方法是直接像 "Hello World"
那样组合字符串字面量。
使用 std::getline 跳过输入
#include <string>
int main()
{
int age;
std::string full_name;
std::cout << "Enter your age: ";
std::cin >> age;
std::cout << "Enter your full name: ";
std::getline(std::cin, full_name); // This line is seemingly skipped
std::cout << "\nYour name is " << full_name << " and your age is " << age;
}
意外行为
你可能会发现,在使用 std::cin >> ...
之后使用 std::getline
时,它似乎跳过了 std::getline
。在上面的例子中,它会询问你的年龄,你会输入比如 23
,然后它会询问你的全名,但不会让你输入名字。相反,它会立即输出 你的名字是,你的年龄是 23
。
解决方案
理解为什么会这样有点棘手。需要记住的关键是,当你使用 std::cin >> ...
时,它会从 stdin 读取输入,直到它看到空白字符(空格、换行符或制表符)。当你按下键盘上的 Enter
来输入年龄时,它会将一个 换行符 \n
放入 stdin。然后 std::cin
读取你输入的数字,并在该换行符处停止,但不移除 \n
字符。
std::getline
使用这些 \n
字符的存在来确定一整行的结束位置。因此,当它尝试从 stdin (std::cin
) 读取一行直到下一个 \n
时,它会立即看到由之前的 std::cin >> age;
留下的 \n
字符。因此,它将其解释为空行,并将 full_name
设置为空字符串 ""
。
解决这个问题的方法是另一个 方法 叫做 ignore
。这个方法会告诉 std::cin
跳过上一个操作留下的剩余换行符。无论何时你计划在 std::cin >> ...
操作之后使用 std::getline
,你都应该在它们之间放置方法调用 std::cin.ignore();
,就像下面的简化示例一样
int age;
std::string full_name;
std::cin >> age;
std::cin.ignore();
std::getline(std::cin, full_name);