Home > OS >  C how to ignore string while reading from file?
C how to ignore string while reading from file?

Time:01-26

I have a program that opens a file, reads from the file and I need to ignore the strings from the file and save only the integers into variables. So far I have tried with file.ignore(' '), but it ignores only the first line. Does anyone has an idea how I can fix this?

My code is:

ifstream file1;
int num1, num2, num3;
int intervalNumber1, intervalNumber2, intervalNumber3;
file1.open("file1.txt");
if (file1.fail()) {
    cout << "Error" << endl;
    exit(1);
} else {
    if (file1.is_open()) {
        file1 >> num1;
        file1 >> num2;
        file1 >> num3;

        file1 >> intervalNumber1;
        file1 >> intervalNumber2;
        file1 >> intervalNumber3;
    }
}

File1.txt

Number 40
Number1 34
Number2 100

Interval Number [20, 50]
Interval Number1 [60, 100]
Interval Number2 [110, 300]

CodePudding user response:

The simple approach is to read the strings the same way you read the integers. Assuming the format of the file is always the same and there is one word in the first the lines and two words in the next three lines and numbers are enclosed in [] and seperated by , you can just read the strings and the [ and ] and , in a char:

#include <sstream>
#include <utility>
#include <iostream>

int main() {
    std::stringstream ss{R"(Number 40
Number1 34
Number2 100

Interval Number [20, 50]
Interval Number1 [60, 100]
Interval Number2 [110, 300])"};

    std::string dummy_string;
    char dummy_char;
    int number0=0;
    int number1=0;
    int number2=0;
    std::pair<int,int> interval0;
    std::pair<int,int> interval1;
    std::pair<int,int> interval2;

    ss >> dummy_string >> number0;
    ss >> dummy_string >> number1;
    ss >> dummy_string >> number2;
    ss >> dummy_string >> dummy_string >> dummy_char >> interval0.first >> dummy_char >> interval0.second >> dummy_char;
    ss >> dummy_string >> dummy_string >> dummy_char >> interval1.first >> dummy_char >> interval1.second >> dummy_char;
    ss >> dummy_string >> dummy_string >> dummy_char >> interval2.first >> dummy_char >> interval2.second >> dummy_char;

    std::cout << number0 << " " << number1 << " " << number2 << "\n";
    std::cout << interval0.first << " " << interval0.second << "\n";
    std::cout << interval1.first << " " << interval1.second << "\n";
    std::cout << interval2.first << " " << interval2.second << "\n";

}

Output:

40 34 100
20 50
60 100
110 300

Reading from a file stream instead of the string stream works the same.


You should consider to use a std::vector instead of naming variables foo0,foo1, foo2 etc. Also consider to use a custom struct, for example if the numbers and the intervals belong together:

struct my_data {
    int number;
    int interval_start;
    int interval_stop;
};

For this type you can then overload the input operator <<.

CodePudding user response:

You might want to use a regular expression to solve this, if there is a known pattern.

If you just want to extract all numeric characters, using std::copy_if to another array (eg a string) would do the job.

Another direct and performant option is, to read the file content into an array, (eg std::string) and iterate over the content, checking for numbers.

std::string file_content (... load file content);
for(char& c : file_content) {
    if (isdigit(c)) {
        have_fun_with_digit(c);
    }
}

CodePudding user response:

Similar actions using regular expressions

i am using two classes std::regex and std::smatch. To read lines from a file, I use the getNewLine function, which skips empty lines

  1. std::regex ref where I apply a pattern that is suitable for both cases NUMBER and [NUMBER, NUMBER]. In all cases, the numbers are placed in separate groups. Pattern: [ \\[](\\d )[ ,]*(\\d )?

  2. std::smatch ref which contains at position 0 the entire search string and further indices contain the found groups

  3. Then using a stoi function ref to get numbers

#include <iostream>
#include <regex>
#include <fstream>

using namespace std;

bool getNewLine(ifstream& f, string& s) {
    while (true) {
        if (!getline(f, s))
            return false;

        if (!s.empty())
            break;
    }

    return true;
}

int main()
{
    const int ArrSize = 3;
    ifstream file1;
    int Numbers[ArrSize] = { 0,0,0 };
    pair<int, int> intervalNumber[ArrSize] = { {0,0},{0,0},{0,0} };
    regex re("[ \\[](\\d )[ ,]*(\\d )?");
    smatch m;

    string newLine;


    file1.open("c:\\file1.txt");

    if (file1.fail()) {
        cout << "Error" << endl;
        exit(1);
    }

    for (int i = 0; i < ArrSize; i  ) {
        if (!getNewLine(file1, newLine))
            exit(1);

        if (!regex_search(newLine, m, re))
            exit(1);

        Numbers[i]=stoi(m[1]);
    }

    for (int i = 0; i < ArrSize; i  ) {
        if (!getNewLine(file1, newLine))
            exit(1);

        if (!regex_search(newLine, m, re))
            exit(1);

        if(m.size()<3)
            exit(1);

        intervalNumber[i].first = stoi(m[1]);
        intervalNumber[i].second = stoi(m[2]);
    }

    for (int i = 0; i < ArrSize; i  )
        cout << Numbers[i] << endl;

    for (int i = 0; i < ArrSize; i  )
        cout << intervalNumber[i].first << " "  << intervalNumber[i].second << endl;
    

    file1.close();
    return 0;
}

results

40
34
100
20 50
60 100
110 300

CodePudding user response:

Here you are:

#include <fstream>
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <functional>
#include <cctype>
#include <algorithm>

int main() {
    std::ifstream is("test.txt");
    if (!is) {
        std::cout << "Unable to open file!\n";
        return 1;
    }
    std::string tmp(
        (std::istreambuf_iterator<char>(is)),
        std::istreambuf_iterator<char>());
    std::vector<int> ans;
    std::string::const_iterator it;
    int ret = 0, len = 0, off;
    auto b_negative = std::negate<int>();
    for (it = tmp.cbegin(); it != tmp.cend();   it) {
        if (std::isdigit(*it)) {
            ret = ret * 10   *it - '0';
              len;
        }
        else {
            if (len != 0) {
                ans.emplace_back(ret);
                off = len   1;
                if (std::distance(tmp.cbegin(), it) >= off && *std::prev(it, off) == '-') {
                    ans.back() = b_negative(ans.back());
                }
            }
            len = ret = 0;
        }
    }
    std::copy(ans.cbegin(), ans.cend(), std::ostream_iterator<int>(std::cout, "\n"));
    return 0;
}
  •  Tags:  
  • Related