-1

i heed some help with ignore(). I have a text file with three lines of text

AMBITIONI DEDISSE SCRIPSISSE IUDICARETUR. ARAS\n
MATTIS IUDICIUM PURUS SIT AMET FERMENTUM. AONEC\n
SED ODIO OPERAE, EU VULPUTATE FELIS RHONCUS.\n

and i need to read it into string arrays in sentences like this:

AMBITIONI DEDISSE SCRIPSISSE IUDICARETUR.\n
ARAS MATTIS IUDICIUM PURUS SIT AMET FERMENTUM.\n
AONEC SED ODIO OPERAE, EU VULPUTATE FELIS RHONCUS.\n

what im getting is this:

AMBITIONI DEDISSE SCRIPSISSE IUDICARETUR\n
TIS IUDICIUM PURUS SIT AMET FERMENTUM\n
D ODIO OPERAE, EU VULPUTATE FELIS RHONCUS\n

any ideas? thanks

 void sakiniais(){
 sak=0;
  ifstream fv;
  fv.open("tekstas.txt");
  if(fv.fail()) cout<<"Nerastas failas.";
  else{
    while(getline(fv,sakiniai[sak],'.')){
        fv.ignore('\n');
        cout<<sakiniai[sak]<<endl;



       //sak++;

     }
Ted Lyngmo
  • 37,764
  • 5
  • 23
  • 50
asdas
  • 1
  • 1
  • The main problem is that you use `!eof()` as a loop condition. `eof()` will not return `true` until you've actually tried to read after end of file. Do: `while(getline(fv, sakiniai[sak], '.')) {...}` – Ted Lyngmo Apr 22 '20 at 13:00
  • [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – molbdnilo Apr 22 '20 at 13:01
  • @Ted Lyngmo well after i tried `while(getline(fv,sakiniai[sak],'.')){ fv.ignore('\n'); out< – asdas Apr 22 '20 at 13:08
  • [`ignore`](https://en.cppreference.com/w/cpp/io/basic_istream/ignore) takes the number of chars to skip as first argument. You need at least 2 (the `.` and the `\n`). Supply an example of `tekstas.txt`, the output you get and the output you want. You can create the textfile in code by using an `istringstream`. Example: https://godbolt.org/z/N2oNXf – Ted Lyngmo Apr 22 '20 at 13:13
  • So, the newlines are to be converted to spaces? – Ted Lyngmo Apr 22 '20 at 14:47

2 Answers2

0

Not so easy as initially thought.

And, there are of cause many possible solutions. I show you 3 solutions with increasing complexity, but all are using the same algorithm.

  1. We read the complete text file into a std::string
  2. We replace all newlines '\' with a space ' '
  3. We replace all dot space ". " sequences with ".\n"
  4. We split the complete text into sentences using the delimiter "."

Please note that the 3rd solution does not need any loop and is using modern C++ language elements and algorithms. But, no need to explain it here, because nobody will use it.

Please see:


#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
#include <regex>
#include <algorithm>

std::istringstream fv{ R"(AMBITIONI DEDISSE SCRIPSISSE IUDICARETUR. ARAS
MATTIS IUDICIUM PURUS SIT AMET FERMENTUM. AONEC
SED ODIO OPERAE, EU VULPUTATE FELIS RHONCUS.
)" };

// either 1 or 2 or 3
#define COMPLEXITY 1

#if COMPLEXITY == 1

void replace(std::string& text, const std::string search, const std::string& replace) {
    // Search, if the search string is in the text at all
    size_t pos = text.find(search);

    // Could we find it?
    while (pos != std::string::npos) {

        // We found it. Replace found text
        text.replace(pos, search.length(), replace);

        // Check, if there are more search strings in the text
        pos = text.find(search, pos);
    }
}
int main() {

    // Here we will store the content of the complete text file
    std::string text;
    char c;

    // Read all characters from the text file and store them in one strinf
    while (fv.get(c)) 
        text.push_back(c);

    // Replace all '\n' by space
    replace(text, "\n", " ");

    // Replace all ". " by ".\n"
    replace(text, ". ", ".\n");

    // Put in stringstream for extraction with getline
    std::istringstream iss(text);

    // Here we will store all sentences
    std::vector<std::string> sentences;

    // Read all sentences from stringstream
    std::string line;
    while(std::getline(iss,line)) 
        sentences.push_back(line);

    // Show output
    for (const std::string& s : sentences) 
        std::cout << s << "\n";

    return 0;
}

#elif COMPLEXITY == 2


std::string& replace(std::string& text, const std::string search, const std::string& replace) {
    for (size_t pos{ text.find(search) }; pos != std::string::npos; pos = text.find(search, pos)) {
        text.replace(pos, search.length(), replace);
    }
    return text;
}

int main() {

    // Here we will store the content of the complete text file
    std::string text;

    // Read all characters from the text file and store them in one string
    for (char c{}; fv.get(c); text.push_back(c)) ; // Empty loop body

    // Replace all '\n' by space and replace all ". " by ".\n"
    replace(replace(text, "\n", " "), ". ", ".\n");

    // Put in stringstream for extraction with getline
    std::istringstream iss(text);

    // Here we will store all sentences
    std::vector<std::string> sentences;

    // Read all sentences from stringstream
    for (std::string line; std::getline(iss, line); sentences.push_back(line));  // Empty body

    // Show output
    for (const std::string& s : sentences)  std::cout << s << "\n";

    return 0;
}

#elif COMPLEXITY == 3

std::regex dotSpace(R"(\. )");

int main() {

    // Read the complete text file into one string
    std::string text(std::istreambuf_iterator<char>(fv), {});

    // Replace all '\n' by space andf replace all ". " by ".\n"
    text = std::regex_replace(std::regex_replace(text, std::regex("\n"), " "), dotSpace, ".\n");

    // Get sentences
    std::vector<std::string> sentences(std::sregex_token_iterator(text.begin(), text.end(), dotSpace, -1), {});

    // Show debug output
    std::copy(sentences.begin(), sentences.end(), std::ostream_iterator<std::string>(std::cout);

    return 0;
}
#endif

Armin Montigny
  • 7,879
  • 3
  • 11
  • 29
0

Here's one way with comments in the code to explain the steps.

#include <algorithm> // replace_copy
#include <iostream>
#include <iterator>  // istreambuf_iterator, back_inserter
#include <string>
#include <vector>

#include <sstream> // istringstream for demo

std::vector<std::string> sakiniais(std::istream& fv) {
    std::vector<std::string> retval;
    std::string all;

    // copy chars from the istream "fv" into the string "all", replacing '\n' with ' '
    std::replace_copy(
        std::istreambuf_iterator<char>(fv), std::istreambuf_iterator<char>{},
        std::back_inserter(all), '\n', ' ');

    // find '.' and store substrings in the vector<string> "retval"
    for(size_t begin=0, end = all.find(".");
        end < all.size();
        begin = end, end = all.find(".", begin))
    {
        ++end; // include '.' in substring

        // store substring
        retval.emplace_back(all.substr(begin, end - begin));

        // skip space following a '.'
        if(end < all.size() && all[end] == ' ') ++end;
    }

    return retval;
}

int main () {
    std::istringstream file(
        "AMBITIONI DEDISSE SCRIPSISSE IUDICARETUR. ARAS\n"
        "MATTIS IUDICIUM PURUS SIT AMET FERMENTUM. AONEC\n"
        "SED ODIO OPERAE, EU VULPUTATE FELIS RHONCUS.\n"
    );

    auto strs = sakiniais(file);

    for(const std::string& s : strs) {
        std::cout << '>' << s << "<\n"; // show string enclosed with '>' and '<'
    }
}

Output:

>AMBITIONI DEDISSE SCRIPSISSE IUDICARETUR.<
>ARAS MATTIS IUDICIUM PURUS SIT AMET FERMENTUM.<
>AONEC SED ODIO OPERAE, EU VULPUTATE FELIS RHONCUS.<
Ted Lyngmo
  • 37,764
  • 5
  • 23
  • 50