简体   繁体   中英

using fscanf to parse file

I am parsing a file which contains pattern like this

[0][NAME][DESCRIPTION]

I am using fscanf(fp, "[%d][%s][%s]", &no, &name, &desc)

and getting these values no=0 and name=NAME][DESCRIPTION] and desc = junk. I tried adding space between the [0] and [Name] which results into no = 0 and name=NAME] what I am doing wrong here?

Replace both %s with %[^]\\n] . The %s is consuming the ] and you need to limit the name to allowable characters.

Here ] and \\n are not allowed to be put in name . You may want %[A-Za-z_ ] to limit name to letters, _ and space.


Related improvements:
A length specifier to avoid overruns.
Consider fgets() paired with sscanf() vs fscanf() .

%s reads until it finds a whitespace character, scanf is not going to meet your needs here. You need something else. Luckily, C++ makes this easy.

I have these functions I use which stream in string or character literals, just stick them in a header:

#include <iostream>
#include <string>
#include <array>
#include <cstring>

template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e(&sliteral)[N]) {
        std::array<e, N-1> buffer; //get buffer
        in >> buffer[0]; //skips whitespace
        if (N>2)
                in.read(&buffer[1], N-2); //read the rest
        if (strncmp(&buffer[0], sliteral, N-1)) //if it failed
                in.setstate(std::ios::failbit); //set the state
        return in;
}
template<class e, class t>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e& cliteral) {
        e buffer;  //get buffer
        in >> buffer; //read data
        if (buffer != cliteral) //if it failed
                in.setstate(std::ios::failbit); //set the state
        return in;
}
//redirect mutable char arrays to their normal function
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, e(&carray)[N]) {
        return std::operator>>(in, carray);
}

With these in addition to the standard library, scanning is a little wierd, but simple:

int id;
std::string name;
std::string description;

std::cin >> "[" >> id >> "][";
std::getline(std::cin, name, ']'); //read until ]
std::cin >> "][";
std::getline(std::cin, description, ']');  //read until ]
std::cin >> "]";

if (std::cin) {
    //success!  All data was properly read in!
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM