Reading integers from a text file with words

后端 未结 6 2015
南笙
南笙 2020-12-12 01:48

I\'m trying to read just the integers from a text file structured like this....

ALS 46000
BZK 39850
CAR 38000
//....

using ifstream.

<
相关标签:
6条回答
  • 2020-12-12 02:17

    You can call ignore to have in skip over a specified number of characters.

    istr.ignore(4);
    

    You can also tell it to stop at a delimiter. You would still need to know the maximum number of characters the leading string could be, but this would also work for shorter leading strings:

    istr.ignore(10, ' ');
    

    You could also write a loop that just reads characters until you see the first digit character:

    char c;
    while (istr.getchar(c) && !isdigit(c))
    {
        // do nothing
    }
    if (istr && isdigit(c))
        istr.putback(c);
    
    0 讨论(0)
  • 2020-12-12 02:28

    Edit: it's in fact possible to work on streams directly with spirit than I suggested previously, with a parser:

    +(omit[+(alpha|blank)] >> int_)
    

    and one line of code(except for variable definitions):

    void extract_file()
    {
        std::ifstream f("E:/dd/dd.trunk/sandbox/text.txt");    
        boost::spirit::istream_iterator it_begin(f), it_end;
    
        // extract all numbers into a vector
        std::vector<int> vi;
        parse(it_begin, it_end, +(omit[+(alpha|blank)] >> int_), vi);
    
        // print them to verify
        std::copy(vi.begin(), vi.end(), 
            std::ostream_iterator<int>(std::cout, ", " ));
    
    }
    

    you get all numbers into a vector at once with one line, couldn't be simpler.


    if you do not mind using boost.spirit2. the parser to get numbers from a line only is

    omit[+(alpha|blank)] >> int_
    

    to extract everything is

    +(alpha|blank) >> int_
    

    See the whole program below(Test with VC10 Beta 2):

    #include <boost/spirit/include/qi.hpp>  
    #include <iostream>  
    #include <string>  
    #include <cstring> 
    #include <vector>  
    
    #include <fstream>
    #include <algorithm>
    #include <iterator>
    
    using std::cout; 
    
    using namespace boost::spirit;  
    using namespace boost::spirit::qi;    
    
    void extract_everything(std::string& line) 
    {
        std::string::iterator it_begin = line.begin();
        std::string::iterator it_end   = line.end();    
    
        std::string s;
        int i;
    
        parse(it_begin, it_end, +(alpha|blank)>>int_, s, i);
    
        cout << "string " << s  
             << "followed by nubmer " << i 
             << std::endl;
    
    }
    
    void extract_number(std::string& line) 
    {
        std::string::iterator it_begin = line.begin();
        std::string::iterator it_end   = line.end();    
    
        int i;
    
        parse(it_begin, it_end, omit[+(alpha|blank)] >> int_, i);
    
        cout << "number only: " << i << std::endl;
    
    } 
    
    void extract_line()
    {
        std::ifstream f("E:/dd/dd.trunk/sandbox/text.txt");
        std::string s;
        int i; 
    
        // iterated file line by line
        while(getline(f, s))
        {
            cout << "parsing " << s << " yields:\n";
            extract_number(s);  // 
            extract_everything(s);
        }
    
    }
    
    void extract_file()
    {
        std::ifstream f("E:/dd/dd.trunk/sandbox/text.txt");    
        boost::spirit::istream_iterator it_begin(f), it_end;
    
        // extract all numbers into a vector
        std::vector<int> vi;
        parse(it_begin, it_end, +(omit[+(alpha|blank)] >> int_), vi);
    
        // print them to verify
        std::copy(vi.begin(), vi.end(), 
            std::ostream_iterator<int>(std::cout, ", " ));
    
    }
    
    int main(int argc, char * argv[])  
    {    
        extract_line();
        extract_file();
    
        return 0;  
    }
    

    outputs:

    parsing ALS 46000 yields:
    number only: 46000
    string ALS followed by nubmer 46000
    parsing BZK 39850 yields:
    number only: 39850
    string BZK followed by nubmer 39850
    parsing CAR 38000 yields:
    number only: 38000
    string CAR followed by nubmer 38000
    46000, 39850, 38000,
    
    0 讨论(0)
  • 2020-12-12 02:31

    here goes :P

    private static void readFile(String fileName) {
    
            try {
                HashMap<String, Integer> map = new HashMap<String, Integer>();
                File file = new File(fileName);
    
                Scanner scanner = new Scanner(file).useDelimiter(";");
                while (scanner.hasNext()) {
                    String token = scanner.next();
                    String[] split = token.split(":");
                    if (split.length == 2) {
                        Integer count = map.get(split[0]);
                        map.put(split[0], count == null ? 1 : count + 1);
                        System.out.println(split[0] + ":" + split[1]);
                    } else {
                        split = token.split("=");
                        if (split.length == 2) {
                            Integer count = map.get(split[0]);
                            map.put(split[0], count == null ? 1 : count + 1);
                            System.out.println(split[0] + ":" + split[1]);
                        }
                    }
                }
                scanner.close();
                System.out.println("Counts:" + map);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            readFile("test.txt");
        }
    }
    
    0 讨论(0)
  • 2020-12-12 02:32
    fscanf(file, "%*s %d", &num);
    

    or %05d if you have leading zeros and fixed width of 5....

    sometimes the fastest way to do things in C++ is to use C. :)

    0 讨论(0)
  • 2020-12-12 02:34

    why to make simple things complicated?

    whats wrong in this :

    ifstream ss("C:\\test.txt");
    
    int score;
    string name;
    while( ss >> name >> score )
    {
        // do something with score
    }
    
    0 讨论(0)
  • 2020-12-12 02:34

    You can create a ctype facet that classifies letters as white space. Create a locale that uses this facet, then imbue the stream with that locale. Having that, you can extract numbers from the stream, but all letters will be treated as white space (i.e. when you extract numbers, the letters will be ignored just like a space or a tab would be):

    Such a locale can look like this:

    #include <iostream>
    #include <locale>
    #include <vector>
    #include <algorithm>
    
    struct digits_only: std::ctype<char> 
    {
        digits_only(): std::ctype<char>(get_table()) {}
    
        static std::ctype_base::mask const* get_table()
        {
            static std::vector<std::ctype_base::mask> 
                rc(std::ctype<char>::table_size,std::ctype_base::space);
    
            if (rc['0'] == std::ctype_base::space)
                std::fill_n(&rc['0'], 9, std::ctype_base::mask());
            return &rc[0];
        }
    };
    

    Sample code to use it could look like this:

    int main() {
        std::cin.imbue(std::locale(std::locale(), new digits_only()));
    
        std::copy(std::istream_iterator<int>(std::cin), 
            std::istream_iterator<int>(),
            std::ostream_iterator<int>(std::cout, "\n"));
    }
    

    Using your sample data, the output I get from this looks like this:

    46000
    39850
    38000
    

    Note that as it stands, I've written this to accept only digits. If (for example) you were reading floating point numbers, you'd also want to retain '.' (or the locale-specific equivalent) as the decimal point. One way to handle things is to start with a copy of the normal ctype table, and then just set the things you want to ignore as space.

    0 讨论(0)
提交回复
热议问题