How to read integers elegantly using C++ stream?

后端 未结 6 1281
醉话见心
醉话见心 2021-01-02 08:52

I have a file full of lines in this format:

1 - 2: 3

I want to only load numbers using C++ streams. Whats the most elegant way to do it? I

相关标签:
6条回答
  • 2021-01-02 09:15

    You can use a locale to change what things are read from the file as it is being read. That is, you will filter out all non-numeric values:

    struct numeric_only: std::ctype<char> 
    {
        numeric_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);
    
            std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
            return &rc[0];
        }
    };
    
    std::fstream myFile("foo.txt");
    myfile.imbue(std::locale(std::locale(), new numeric_only()));
    

    Then when you read your file, it'll convert all non digits to spaces while leaving you only the numbers. After that, you can simply use your normal conversions to transform what is being read into ints.

    std::vector<int> intFromFile;
    std::istream_iterator<int> myFileIter(myFile);
    std::istream_iterator<int> eos;
    std::copy(myFileIter, eos, std::back_inserter(intFromFile));
    

    Response to the comments below:

    Here is what I did to get it to work

    int main(int args, char** argv){
        std::fstream blah;
        blah.open("foo.txt", std::fstream::in);
        if(!blah.is_open()){
            std::cout << "no file";
            return 0;
        }
        blah.imbue(std::locale(std::locale(), new numeric_only()));
    
        std::vector<int> intFromFile;
        std::istream_iterator<int> myFileIter(blah);
        std::istream_iterator<int> eos;
        std::copy(myFileIter, eos, std::back_inserter(intFromFile));
    
       return 0;
    }
    

    And this put only the ints into the vector, nothing more, nothing less. The reason it wasn't working before was two fold:

    1. I was filling up to '9' but not '9' itself. I've changed the fill to ':'
    2. Numbers larger than what an int can hold are a problem. I'd suggest using longs.
    0 讨论(0)
  • 2021-01-02 09:15

    Simply,

    ifstream file("file.txt");
    int n1, n2, n3;
    char tmp;
    while (file.good()) {
      file >> n1 >> tmp >> n2 >> tmp >> n3;
    }
    
    0 讨论(0)
  • 2021-01-02 09:16

    Sorry Konrad, but I recommend: never on pain of death, never never never (is that clear enough? :-) read formatted data from a file. Just don't.

    There is only one correct way to do input of formatted data: read chunks of characters (typically lines but you can also read fixed length blocks).

    Then parse the input text. You're not going to do a cursory check, you going to use a parser that guarantees to catch any formatting error, and report that error in a comprehensible way, take appropriate action (termination, skip the line and continue, whatever).

    Separate input (the I/O operation) from parsing.

    This advice from decades of experience as a commerical programmer: reading formatted input is for micky mouse proof-of-principal programs. Even if you have exclusive control of the creation of the file, always parse and check and report errors: after all, stuff changes, it may work today but not tomorrow.

    I've been writing C++ for decades and I've never read an integer.

    0 讨论(0)
  • 2021-01-02 09:21

    I think this one would be the fastest -yet elegant- way:

    int a, b, c;
    scanf("%d-%d:%d", &a, &b, &c);
    
    0 讨论(0)
  • 2021-01-02 09:23

    I would recommend doing at least cursory sanity checks when reading this:

    int a, b, c;
    char dash, colon;
    
    if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':')
        Failure. Do something.
    
    0 讨论(0)
  • 2021-01-02 09:24
        int a,b,c;
    
        cin >> a;
        cin.ignore(100,'-');
        cin >> b;
        cin.ignore(100,':');
        cin >> c;
    
        cout << "a = "<< a <<endl;
        cout << "b = "<< b <<endl;
        cout << "c = "<< c <<endl;
    

    Input:

    1 - 2: 3

    Output:

    a = 1
    b = 2
    c = 3

    See yourself here : http://www.ideone.com/DT9KJ

    Note: this can handle extra spaces also. So you can read even this:

     1     -        2      :      3

    Similar topic:

    Using ifstream as fscanf

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