I've a little problem with split of text file; in my text file there are almost 10 thousand of recipies like
-Ing_principal
ingr 1
-Ingredients
ingr 1
ingr 2
ingr 3
-Preparation
now how I can get only ingredients between 2 delimiters that are ingredients and preparation.
So I think this solution
int main() {
string s, t;
bool i = false;
ifstream ricette;
ofstream ingredienti;
ingredienti.open("ingredienti.txt");
ricette.open("ricette.txt", ios::out);
while(ricette) {
getline (ricette, s);
if (s[0] == '-' && s[1] == 'I' && s[5] != 'P') {
i = true;
getline(ricette, t);
while (i) {
if (t[0] != '-' && t[1] != 'P')
cout << t << endl;
else i = false;
}
}
}
ingredienti.close();
ingredienti.close(); }
but this return only ingr 1 in infinite loop. Anyone have good solution or suggestion?
It seems you don't read new input lines in this loop:
while (i) {
if (t[0] != '-' && t[1] != 'P')
cout << t << endl;
else i = false;
// Here you'll need to read the next line
}
This line also looks strange:
if (s[0] == '-' && s[1] == 'I' && s[5] != 'P') {
I guess it shall be a 'p' instead of 'P':
if (s[0] == '-' && s[1] == 'I' && s[5] != 'p') {
BTW - you close the same file twice:
ingredienti.close();
ingredienti.close();
However, I would use another approach to avoid two while-statements. Something like:
int main() {
string s;
bool foundInterestingSection = false;
ifstream ricette("ricette.txt");
ofstream ingredienti("ingredienti.txt");
while(getline (ricette, s))
{
if (foundInterestingSection)
{
if (s == "-Preparation")
{
// The interesting section ends now
foundInterestingSection = false;
}
else
{
cout << s << endl;
// Write to output file
ingredienti << s << endl;
}
}
else
{
if (s == "-Ingredients")
{
// The interesting section starts now
foundInterestingSection = true;
}
}
}
ingredienti.close();
ricette.close();
}
You want to access a portion that is delimited by two delimiters. Then the straightforward solution is to search for those two delimiters. You can then copy the intermediate contents for further use.
The approach I used buffers first the whole input from std::cin
, because it doesnt't support arbitrary moving around in the input. When using a file, this is most likely not necessary.
To perform searches, the best solution is std::search
from <algorithm>
, you can use it to find the first occurrence of a sequence inside of another one. In your case, this is finding "-Ingredients"
or "-Preparation"
inside of the file.
std::string const start_delimiter{"-Ingredients"};
auto start = std::search(from, to, start_delimiter.begin(), start_delimiter.end());
// start now points to '-', assuming the string was found
std::advance(start, delimiter.size());
// start now points delimiter.size() characters AFTER the '-', which
// is the character following the delimiter string
// ...
std::string const end_delimiter{"-Preparation"};
auto end = std::search(start, to, end_delimiter.begin(), end_delimiter.end());
// Your text is between [start,end)
from = end;
std::advance(from, end_delimiter.size());
You use this to find the both delimiters, then you can use the part in between the respective iterators to extract / print / work with the text you're interested in. Note that you might need to add newline characters to your delimiters as needed.
I put together a small example , though you might want to factor the reading into some function, either returning the respective text parts, or taking a functor to work on each of the text part.
Concerning your code, there are multiple issues:
ifstream ricette;
// ...
ricette.open("ricette.txt", ios::out);
// ...
getline(ricette, t);
You take an input file stream, open it for output , then read from it?
getline(ricette, t);
while (i) {
// ...
}
You only read one line of the ingredients. You need to perform reading inside of your loop, otherwise t
will never change inside of that while
loop (which is why you get an infinite loop).
ingredienti.close();
ingredienti.close();
... double close ...
Then, in general, you should directly test the input operations, ie the getline
:
std::string t; // Use better names, define variables near their use
while(getline(ricette, t)) {
if (t[0] == '-' && t[1] == 'P') {
break;
}
}
// could be eof/failure OR "-P.." found
Then, seeing your test, think of what happens when you input an empty line? Or a line with only a single character? You need to test for the size, too:
if (t.size() > 1 && t[0] == '-' && t[1] == 'P')
And finally, your code assumes different things than what you told us. (Your delimiters are "-I" followed by a "not p" test as well as "-P")
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.