将char *直接转换为fscanf中的std :: string

时间:2018-11-27 12:18:12

标签: c++ string io scanf

在使用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所述,我看不出将这种方法应用于我的情况的方法。)

4 个答案:

答案 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

Live Demo

但是您实际上应该使用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::stringstd::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),就可以避免所有这些情况。