0

So I am trying to make a program that gets an input from a text file, and has the user enter the term they want to search for. From there, the file should be printed out with 3 asterisks in front and behind all of the terms.

It works currently, but it only finds the first term in the file, I want it to find all terms. Any help?

Thanks

#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>

using namespace std;

int main(void)
{
    int a, i, z, loc;
    string inputFileName;
    string s, term;
    ifstream fileIn;
    char ch;
    cout << "Enter the name of a file of characters: ";
    cin >> inputFileName;
    fileIn.open(inputFileName.data());
    assert(fileIn.is_open() );
    i = 0;

    while (!(fileIn.eof()))
    {
        ch = fileIn.get();
        s.insert(i, 1, ch);     //insert character at position i
        i++;
    }

    cout << s;
    cout << "Enter a word/phrase you want to search for in the file you entered" << endl;
    cin >> term;
    cout << "The word/phrase " << term << " will have '***' before it and after it" << endl;
    z = (int)term.length();
    loc = s.find(term);

    s.insert(loc, 1, '*');
    s.insert(loc+1, 1, '*');
    s.insert(loc+2, 1, '*');

    s.insert(loc+3+z, 1, '*');
    s.insert(loc+4+z, 1, '*');
    s.insert(loc+5+z, 1, '*');
    cout << s;

    return 0;
}

Text output
Enter the name of a file of characters: text.txt

Repair- Determined by the difficulty of the fix, and the parts needed in order for it to work.

Enter a word/phrase you want to search for in the file you entered

the

The word/phrase by will have '***' before it and after it

Repair- Determined by the difficulty of the fix, and the parts needed in order for it to work.

greatgamer34
  • 35
  • 1
  • 7
  • 1
    `using namespace std;` is [bad](http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). – Baum mit Augen Mar 07 '15 at 18:34
  • 1
    @BaummitAugen It's a bad idea in headers which will be recombined in circumstances beyond your control, but even on the question you cite [plenty of upvotes](http://stackoverflow.com/a/1452759/211160) say it's to your discretion in private C++ implementation files. And on stackoverflow it shortens many examples. So don't bother calling people out unless it's demonstrably in a header, and even then...there are probably other things to worry about. – HostileFork says dont trust SE Mar 07 '15 at 18:40
  • 1
    The formatting is terrible. Please format your code so that others can read the code more easily. FYI, my code formatter detected you have a missing brace somewhere, so your code isn't even compilable. – PaulMcKenzie Mar 07 '15 at 18:46
  • Whoops I had an extra brace in there. Fixed. Will reformat in a moment :D – greatgamer34 Mar 07 '15 at 18:48
  • I made an edit that fixes the formatting, but I don't think it's been reviewed yet – Sam van Kampen Mar 07 '15 at 18:50
  • [`while (!f.eof())` is always wrong](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – The Paramagnetic Croissant Mar 07 '15 at 19:05

2 Answers2

1

string.find("term") gives you only the first occurrence of the term "term". If your file is not too long, one way to solve the problem is as follows.

int loc[100], i=0;
int pos = string.find("term", 0);
while(pos!=string::npos) {
   loc[i] = pos;
   pos = string.find("term", pos+1);
   i++;
} 

string.find(term, pos) allows you to search for a term in a string on or after the index "pos".

Ofcourse you can create a dynamic array for storing more than 100 locations

1

std::basic_string::find

Return value
Position of the first character of the found substring or npos if no such substring is found.

(http://en.cppreference.com/w/cpp/string/basic_string/find)

This means you can simply loop std::string::find until its return value is npos, adding the previous substring location plus the substring length as the starting position.

As you also don't want to find words that contain the substring, but merely the substring as a standalone word, I've added some checks at the start of the function. Note: using a regular expression engine may be cleaner at this point.

loc = 0;

while ((loc = s.find(term, loc)) != std::string::npos)
{
    // check for space at start of term, or check
    // for beginning of string
    if (loc != 0 && s[loc - 1] != ' ') {
        loc += z;
        continue;
    }

    // check for space at end of term, or check for end of string
    if (loc != (s.length() - z) && s[loc + z] != ' ') {
        loc += z;
        continue;
    }

    s.insert(loc, 1, '*');
    s.insert(loc+1, 1, '*');
    s.insert(loc+2, 1, '*');

    s.insert(loc+3+z, 1, '*');
    s.insert(loc+4+z, 1, '*');
    s.insert(loc+5+z, 1, '*');

    loc += z;
    loc += 6; // the amount of asterisks added
}

There are also quicker ways to find all substrings, not using the C++ standard library. This question's accepted answer contains one.

Community
  • 1
  • 1
Sam van Kampen
  • 973
  • 9
  • 17
  • I did that^ but it froze up for some reason. It wont print out the new string after I added the while loop that you suggested above. – greatgamer34 Mar 07 '15 at 19:16
  • Oh, that might be because it's finding the same string over and over again, try changing `loc + z` to `loc + z + 6` (the amount of asterisks added) - my test program merely printed the substring, so I didn't have such a problem. (I'm just guessing here, you should really use a debugger like gdb to see what's going wrong) – Sam van Kampen Mar 07 '15 at 19:20
  • Ahh, yes, that works now. But theres another issue that I found now. If you search for a term, and there is another word that has that term inside of it( "the", "e***the***rnet") Is there any way to check for the ascii space value before and after the term? – greatgamer34 Mar 07 '15 at 19:24
  • You could add some logic that checks for a space before and after the term (and add exceptions for the beginning and end of the string) - I'll edit my answer. – Sam van Kampen Mar 07 '15 at 19:26
  • Well Thank you!! I tried to upvote your post but i need 15 karma(rep)or something. :) – greatgamer34 Mar 07 '15 at 19:38
  • No problem :) While you can't upvote it, I think you *can* accept it as a correct answer (although that might be after a certain time) – Sam van Kampen Mar 07 '15 at 19:40