st3fan0
st3fan0

Reputation: 1

fscanf doesn't work correctly with string

I have a simple problem with my application. fscanf collects an entire word, but the size (length) is equal to the default size of currentName. If the currentName's default length value is lower then the length of a word, the word is cut.

For example:

if currentName="123" then fscanf will return "Art" instead of "Arthur".

or

if currentName="123456789" then fscanf will return "Arthur 89" instead of "Arthur".

File "list.txt" contains rows:

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

What should I change to solve this issue? I have to use fscanf instead of 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");
}

Upvotes: 0

Views: 626

Answers (2)

Baum mit Augen
Baum mit Augen

Reputation: 50043

You cannot modify the internal buffer of an std::string directly as you try to do here. To read a string, use a stream:

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

If you really need to use fscanf, use a big enough std::vector<char> instead and use it like a C-style string.

Upvotes: 1

Emily
Emily

Reputation: 541

scanf scans %s into a char array, not a std::string.

std::string is implemented with something like struct { size_t length; char* buffer; }, so writing into buffer will actually change the string. However, since it tracks its length explicitly, the '\0' at the end of the string won't be considered a terminator like it would in a character-array string.

You could just scan into a char array, but the C++ish way to do this would be to use std::ifstream.

Upvotes: 1

Related Questions