【问题标题】:using fscanf to parse file使用 fscanf 解析文件
【发布时间】:2013-07-30 21:45:22
【问题描述】:

我正在解析一个包含这样的模式的文件

[0][姓名][描述]

我正在使用 fscanf(fp, "[%d][%s][%s]", &no, &name, &desc)

并获得这些值 no=0 和 name=NAME][DESCRIPTION] 和 desc = junk。我尝试在 [0] 和 [Name] 之间添加空格,导致 no = 0 和 name=NAME] 我在这里做错了什么?

【问题讨论】:

    标签: c++ c parsing scanf


    【解决方案1】:

    %s 都替换为%[^]\n]%s 正在使用 ],您需要将 name 限制为允许的字符。

    这里]\n不允许放入name。您可能希望 %[A-Za-z_ ]name 限制为字母、_ 和空格。


    相关改进:
    避免溢出的长度说明符。
    考虑 fgets()sscanf()fscanf() 配对。

    【讨论】:

    • 这不是 scanf 的非标准语法吗?
    • 在 cplusplus.com 和 linux.die.net 上有提到,但在维基百科 msdn 上没有。
    • 这是不寻常的,但 c11 说“如果转换说明符以 [] 或 [^] 开头,右括号字符在扫描列表中,下一个右括号字符是匹配的右括号规范;”,它编译正常并按预期工作。
    • [ 或扫描集转换是在 C89 中引入的。
    • 可能很高兴提到%[,就像%s,没有长度说明符是危险的。
    【解决方案2】:

    %s 一直读取直到找到一个空白字符,scanf 在这里无法满足您的需求。你需要别的东西。幸运的是,C++ 让这一切变得简单。

    我有这些函数,我在字符串或字符文字中使用哪个流,只需将它们放在标题中:

    #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);
    }
    

    除了标准库之外,还有这些,扫描有点奇怪,但很简单:

    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!
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多