【问题标题】:fscanf doesn't work correctly with stringfscanf 不能与字符串一起正常工作
【发布时间】:2015-05-04 16:20:02
【问题描述】:

我的应用程序有一个简单的问题。 fscanf 收集整个单词,但大小(长度)等于currentName 的默认大小。如果currentName 的默认长度值小于一个词的长度,则该词被剪切。

例如:

如果currentName="123" 然后 fscanf 将返回“Art”而不是“Arthur”。

如果currentName="123456789" 那么fscanf 将返回“Arthur 89”而不是“Arthur”。

文件“list.txt”包含行:

Arthur 30 1550
Ben 32 2100
Charlie 25 1850
Danny 46 2400
Edward 35 2750

我应该改变什么来解决这个问题?我必须使用 fscanf 而不是 fstream。

#include <iostream>
#include <stdio.h>
#include <string>
#include <stdlib.h>
using namespace std;
class Worker
{
private:
    string name;
    int age;
    double salary;
public:
    Worker()
    :name(""),age(99),salary(0)
    {}
    Worker(string name, int age, double salary)
        :name(name),age(age),salary(salary)
    {}
    void showVaulues()
    {
        cout<<endl;
        cout<<"Name:\t"<<name<<endl;
        cout<<"Age:\t"<<age<<endl;
        cout<<"Salary:\t"<<salary<<endl;
    }
};
int main()
{
    FILE *myfile=NULL;
    string currentName="123456789";
    int currentAge=0;
    double currentSalary=999999;
    Worker *ptr=NULL;
    myfile=fopen("list.txt","r");
    while (feof(myfile) == 0)
    {
        fscanf(myfile,"%s %d %lf\n",&currentName[0],&currentAge,&currentSalary);
        ptr=new Worker(currentName,currentAge,currentSalary);
        ptr->showVaulues();
    }
    system("pause");
}

【问题讨论】:

  • 为什么标记为C,明明是C++
  • fscanf(myfile,"%s %d %lf\n",&amp;currentName, ...); 你用的是什么编译器?如果它是 C++11 之前的任何内容,那么像这样填充 std::string 是未定义的行为。而且我什至不确定它是否适用于 C++ 11。
  • @PaulMcKenzie 等等,这在 C++11 中是合法的吗?
  • 请在C++中使用&lt;cstdio&gt;&lt;cstdlib&gt;
  • @st3fan0 C 标签没有保证的原因是你给fscanf 提供了一个std::string。一旦你这样做了,那么它就是一个纯粹的 C++ 问题,因为 C 中没有 std::string 这样的东西。此外,对于下面给出的答案,该代码将不适用于 Visual Studio 2012。行为未定义,简单明了。仅仅因为它看起来有效并不意味着它实际上有效。

标签: c++ string scanf


【解决方案1】:

scanf%s 扫描到char 数组中,而不是std::string

std::string 是用类似struct { size_t length; char* buffer; } 的东西实现的,所以写入buffer 实际上会改变字符串。但是,由于它显式跟踪其长度,因此字符串末尾的 '\0' 不会像在字符数组字符串中那样被视为终止符。

您可以只扫描到 char 数组,但 C++ 的方法是使用 std::ifstream

【讨论】:

    【解决方案2】:

    您无法像在此处尝试那样直接修改std::string 的内部缓冲区。要读取string,请使用流:

    std::ifstream in ("list.txt");
    int >> currentname >> currentAge >> currentSalary;
    

    如果您确实需要使用fscanf,请改用足够大的std::vector&lt;char&gt;,并像使用C 风格的字符串一样使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 2018-11-10
      • 2014-07-01
      相关资源
      最近更新 更多