在使用fscanf
读取字符串并将其存储到字符串变量时,fscanf
期望char*
作为格式字符串之后的参数,即,即据我所知应该是:
char str[<apppropriate length here>];
std::fscanf(filepointer,"%s\n",str);
如果我使用std::string str
而不是char str[]
,我会收到-Wformat
警告(很明显),并且程序崩溃并显示Segnetation fault
(我不知道为什么,但是,但我并不感到惊讶)。除了修复段错误之外,我还可以正确执行此操作,即不接收-Wformat
警告。
是否有一种方法可以“内联”地进行char*
到std::string
的转换,即在fscanf
的参数列表中,还是我必须创建一个临时的{{1} }变量来存储数据,然后将其转换为char*
(如here所述,我看不出将这种方法应用于我的情况的方法。)
答案 0 :(得分:0)
您可能已经在reference中读到过,它应该是:
char str[<apppropriate length here>];
fscanf(filepointer, "%s\n", str);
因为str
是一个数组。在What is array decaying?
有c_str()
和data()
,它们可以为您提供std::string
的C字符串。但是,这些函数返回一个常量指针,因此不能在fscanf()
中使用(这是一个来自C的函数,因此可以处理C字符串)。
注意:在C++17中,data()
具有一个重载,该重载返回一个非恒定指针,因此可以用于内联用法,如下所示:
std::string str(10, '\0'); // a string of size 10, null terminated
fscanf(filepointer, "%9s\n", str.data());
str.resize(strlen(str.data())); // so that 'str.size()' is correct
但是您实际上应该使用C ++流,例如std::cin
而不是C IO函数。
示例:
std::string str;
std::cin >> str;
答案 1 :(得分:0)
如果使用的是C ++,则不应使用C或C样式的函数。特别是像std::fscanf
这样的函数,它们会执行不受保护的写入。以下是在C ++中如何从文件正确读取数据到std::string
的方法:Read file line by line using ifstream in C++
答案 2 :(得分:0)
一个人可以将std::string
与std::scanf()
一起使用:
#include <cstdlib> // EXIT_FAILURE
#include <cstdio> // std::scanf()
#include <cstring> // std::strlen()
#include <string>
#include <iostream>
int main()
{
std::string foo(40, '\0'); // fill the string with 40 0s
// for pre C++11 please make it 41
int length = 0;
if (std::scanf("%39s%n", &foo[0], &length) != 1) {
std::cerr << "Input error :(\n\n";
return EXIT_FAILURE;
}
foo.resize(length); // let foo know its own length ^^
std::cout << foo.length() << " chars: " << foo << '\n';
}
答案 3 :(得分:0)
自C++17起,您可以:
std::string str(<apppropriate length here>, 0);
fscanf(filepointer, "%s\n", str.data());
str.resize(strlen(str.c_str()));
但是你不应该。
首先,它没有按照您想要的去做。如果您有"Tom Jerry\n"
,will only read "Tom"
这样的输入行,更糟糕的是,下次您从文件中读取时,它将尝试读取"Jerry"
。您应该真正使用fgets()
,std::istream::getline()
,或者最好使用std::getline(file, str)
。
第二,'\0'
或char()
是C ++字符串中的有效字符。如果您阅读"Tom\0Jerry\n"
,则代码将设法读取的实际字符串将包含"Tom\0Jerry"
,这可能是有效的结果,但是由于该{{ 1}}。您可以通过创造性地使用"Tom"
格式说明符来缓解这种情况,但是为什么首先要使您的生活复杂化?
第三,C ++字符串输入例程可以在必要时调整字符串的大小。在C函数中,您需要指定一个字符串大小限制,该限制通常是任意的。如果您对格式说明符草率(例如在示例中),这可能导致缓冲区溢出,但是如果您不能正确处理截断的输入的特殊情况,则可能导致逻辑错误。
因此,只需在C ++流输入中使用std::getline(file, str)
,就可以避免所有这些情况。