Nick
Nick

Reputation: 95

C++ How do we find each line of a word from a text file?

I am reading a text file word for word and I am trying to find the number of the line the word is in. For example if I had the following:

Dog Cat
Car 
Truck

Dog is found on line one, Cat is found on line one, Car line two, and Truck line 3.

I have the following code:

int main(){
string word;
ifstream inFile;
Node* rootPtr = NULL; // Pointer to the root node

inFile.open("example.txt");
if (!inFile)
    cout << "Unable to open text file";

while (inFile >> word) {
    if (word == "#")
        break;

    /* THIS DOES NOT WORK! Most likely because my text file doesn't contain /n but this is the
    kind of logic I am looking for
    else if (word == "/n"){
        counter++;
        cout << counter;
    }
    */

    else{
    rootPtr = Insert(rootPtr,word.substr(0,10));
    }
}
inOrderPrint(rootPtr);
inFile.close();
}

You can ignore anything to do with the pointers. That is for some other stuff. I have tried figuring out how to check for the end of the line and creating a counter that will increment every time then end of a line is found but I was unsuccessful.

Thanks for your help!

Upvotes: 0

Views: 2686

Answers (5)

Nick
Nick

Reputation: 95

I found a nice way to go about doing this. All I had to do is add the following:

    char c;
    while (inFile >> word) {
        c = inFile.get();
        else if (c=='\n'){
            rootPtr = Insert(rootPtr,word.substr(0,10));
            counter++;
        }
    }

Thanks for all of your suggestions!

Upvotes: 0

Mohan
Mohan

Reputation: 1955

You can use the getline function

string line;
int lineNum = 0; // Or 1 
while(getline(infile, line))
{
    i++;
}

And you can use the stringstream if you want to split the line by word.

#include <sstream>
// Your code
 while(getline(infile, line))
{
    stringstream ssLine(line);
    string substr;
    while(ssLine)
    {
         ssLine >> substr;
         // substr will now hold each word (words should be separated by spaces)
    }
    i++;
}

Or better, I have my version of split and you are welcome to use that

/**
 * Equivalent to java's string.split() function.
 * 
 * @param toPopulate The return value of this function.
 * @param s          The string we want to split.
 * @param delim      The delim which we want to split. This will not be included in
 *                   the splitted string. User should pass only one character to this
 *                   string.
 */
void split(vector<string> &toPopulate, string s, string delim)
{
// Will hold the start of the substring (after the delim). Initially the 
// substring will start at 0.
int substrStart = 0;
while (substrStart < s.length())
{
    // Will hold the position of the delim.
    int curFoundPos = s.find(delim, substrStart);
    // Holds the current substring.
    string oneOfSplittedStr;

    // The delim not found. So, take the substring from previous delim to end.
    if (curFoundPos == -1)
    {
        oneOfSplittedStr = 
            s.substr(substrStart, s.length() - substrStart);
        // To break off the loop. If not for this stmt, we will go into infinite loop.
        substrStart = s.length();
    }
    else
    {
        oneOfSplittedStr = 
            s.substr(substrStart, curFoundPos - substrStart);
        // our next substring will start one greater than the current found position.
        substrStart = curFoundPos + 1;
    }
    // Empty - Nah
    if (!oneOfSplittedStr.empty() && oneOfSplittedStr.compare("") != 0)
        toPopulate.push_back(oneOfSplittedStr);
}

}

And you can always use boost's split

Upvotes: 1

Thomas Matthews
Thomas Matthews

Reputation: 57698

There is an issue with your requirements: What if the word exists on multiple lines?

For the simple case, I recommend keeping a line counter and using std::map<string, unsigned int>, where string is your word and unsigned int is the line number it first occurs on.

To handle all line numbers that a word occurs on, you may want to use std::map<string, std::vector<unsigned int> >, where the std::vector contains all the line number that the word occurs on.

Example:

typedef std::map<std::string, unsigned int> Word_Ref_Container;
Word_Ref_Container word_line_reference;
//...
std::string text_line;
unsigned int line_number = 1;
while (getline(input_file, text_line)
{
  std::istringstream text_stream(text_line);
  std::string  word;
  while (text_stream >> word)
  {
     if (word_line_reference.find(word) != word_line_reference.end())
     {
        word_line_reference[word] = line_number;
     }
  }
  ++line_number;
}

Upvotes: 0

Joshua
Joshua

Reputation: 328

You could try a few things. A map would work:

#include <map>
map <int,string> words;

And then while adding words:

int wordNum = 0;
while (inFile >> word) {
    if (word == "#")
        break;
    else{
        words[wordNum] = word;
    }

And recall your words like this:

int x = 0;
while ( x < map.size() ) {
    cout << words[x] << " ";
    x++;
}

Another option is to store your words into a struct containing two strings, or any two corresponding data types (one for your word, one for the #):

struct words_struct{
    string words;
    string wordNum;
} store ;  // single instance

And store the words like this:

int x=0;
while (inFile >> word) {
    if (word == "#")
        break;
    else{
        store->words.append(word);
        store->wordNum.append(x);
        x++;
    }

The above code needs some fixin' (no space between words, int->string, etc) but the gist is correct. Hope this helps! Best of luck!

Upvotes: 0

Ferenc Deak
Ferenc Deak

Reputation: 35408

You always can use carefully getline (http://www.cplusplus.com/reference/string/string/getline/) and count the lines by yourself. Of course, split the read string into words from the line: Split a string in C++?

Upvotes: 0

Related Questions