正如标题所说,我很好奇是否有办法用scanf读取C++字符串.
我知道我可以读取每个char并将其插入到deserved字符串中,但我想要的是:
string a;
scanf("%SOMETHING", &a);
Run Code Online (Sandbox Code Playgroud)
gets()
也行不通.
提前致谢!
Pat*_*ato 28
这可以工作
char tmp[101];
scanf("%100s", tmp);
string a= tmp;
Run Code Online (Sandbox Code Playgroud)
Die*_*ühl 17
没有任何情况gets()
可以使用!使用它总是错误的gets()
,它从C11中删除并从C++ 14中删除.
scanf()
不支持任何C++类.但是,您可以将结果存储scanf()
到std::string
:
std::string str(100, ' ');
if (1 == scanf("%*s", &str[0], str.size())) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
我不能完全肯定,指定在缓冲区lenght的方式scanf()
及顺序的参数去(有机会的参数&str[0]
和str.size()
需要予以转回,我可能会丢失一个.
格式字符串).请注意,结果std::string
将包含终止空字符,并且不会更改其大小.
当然,我会使用,if (std::cin >> str) { ... }
但这是一个不同的问题.
std::string
您可以填充using的底层缓冲区scanf
,但是(!)托管std::string
对象不会意识到更改。
const char *line="Daniel 1337"; // The line we're gonna parse
std::string token;
token.reserve(64); // You should always make sure the buffer is big enough
sscanf(line, "%s %*u", token.data());
std::cout << "Managed string: '" << token
<< " (size = " << token.size() << ")" << std::endl;
std::cout << "Underlying buffer: " << token.data()
<< " (size = " << strlen(token.data()) << ")" << std::endl;
Run Code Online (Sandbox Code Playgroud)
输出:
Managed string: (size = 0)
Underlying buffer: Daniel (size = 6)
Run Code Online (Sandbox Code Playgroud)
那么,这里发生了什么?
该对象std::string
不知道未通过导出的官方 API 执行的更改。
当我们通过底层缓冲区写入对象时,数据发生变化,但字符串对象不知道这一点。
如果我们将原始调用: 替换token.reseve(64)
为token.resize(64)
更改托管字符串大小的调用,结果将会有所不同:
const char *line="Daniel 1337"; // The line we're gonna parse
std::string token;
token.resize(64); // You should always make sure the buffer is big enough
sscanf(line, "%s %*u", token.data());
std::cout << "Managed string: " << token
<< " (size = " << token.size() << ")" << std::endl;
std::cout << "Underlying buffer: " << token.data()
<< " (size = " << strlen(token.data()) << ")" << std::endl;
Run Code Online (Sandbox Code Playgroud)
输出:
Managed string: Daniel (size = 64)
Underlying buffer: Daniel (size = 6)
Run Code Online (Sandbox Code Playgroud)
结果再次不是最优的。输出是正确的,但大小不正确。
如果您确实想这样做,请按照下列步骤操作:
resize
以确保您的缓冲区足够大。使用 a#define
作为最大长度(请参阅步骤 2 以了解原因):std::string buffer;
buffer.resize(MAX_TOKEN_LENGTH);
Run Code Online (Sandbox Code Playgroud)
scanf
while 使用“宽度修饰符”限制扫描字符串的大小并检查返回值(返回值是扫描的标记数量):#define XSTR(__x) STR(__x)
#define STR(__x) #x
...
int rv = scanf("%" XSTR(MAX_TOKEN_LENGTH) "s", &buffer[0]);
Run Code Online (Sandbox Code Playgroud)
buffer.resize(strnlen(buffer.data(), MAX_TOKEN_LENGTH));
Run Code Online (Sandbox Code Playgroud)