Reputation: 95
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
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
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
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
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
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