Tokenization of strings in C++ - c++

I am using the following code for splitting of each word into a Token per line. My problem lies here: I want a continuous update on my number of tokens in the file. The contents of the file are:
Student details:
Highlander 141A Section-A.
Single 450988012 SA
Program:
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cstring>
const int MAX_CHARS_PER_LINE = 512;
const int MAX_TOKENS_PER_LINE = 20;
const char* const DELIMITER = " ";
int main()
{
// create a file-reading object
ifstream fin;
fin.open("data.txt"); // open a file
if (!fin.good())
return 1; // exit if file not found
// read each line of the file
while (!fin.eof())
{
// read an entire line into memory
char buf[MAX_CHARS_PER_LINE];
fin.getline(buf, MAX_CHARS_PER_LINE);
// parse the line into blank-delimited tokens
int n = 0; // a for-loop index
// array to store memory addresses of the tokens in buf
const char* token[MAX_TOKENS_PER_LINE] = {}; // initialize to 0
// parse the line
token[0] = strtok(buf, DELIMITER); // first token
if (token[0]) // zero if line is blank
{
for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
{
token[n] = strtok(0, DELIMITER); // subsequent tokens
if (!token[n]) break; // no more tokens
}
}
// process (print) the tokens
for (int i = 0; i < n; i++) // n = #of tokens
cout << "Token[" << i << "] = " << token[i] << endl;
cout << endl;
}
}
Output:
Token[0] = Student
Token[1] = details:
Token[0] = Highlander
Token[1] = 141A
Token[2] = Section-A.
Token[0] = Single
Token[1] = 450988012
Token[2] = SA
Expected:
Token[0] = Student
Token[1] = details:
Token[2] = Highlander
Token[3] = 141A
Token[4] = Section-A.
Token[5] = Single
Token[6] = 450988012
Token[7] = SA
So I want it to be incremented so that I could easily identify the value by its variable name. Thanks in advance...

What's wrong with the standard, idiomatic solution:
std::string line;
while ( std::getline( fin, line ) ) {
std::istringstream parser( line );
int i = 0;
std::string token;
while ( parser >> token ) {
std::cout << "Token[" << i << "] = " << token << std::endl;
++ i;
}
}
Obviously, in real life, you'll want to do more than just
output each token, and you'll want more complicated parsing.
But anytime you're doing line oriented input, the above is the
model you should be using (probably keeping track of the line
number as well, for error messages).
It's probably worth pointing out that in this case, an even
better solution would be to use boost::split in the outer
loop, to get a vector of tokens.

I would just let iostream do the splitting
std::vector<std::string> token;
std::string s;
while (fin >> s)
token.push_back(s);
Then you can output the whole array at once with proper indexes.
for (int i = 0; i < token.size(); ++i)
cout << "Token[" << i << "] = " << token[i] << endl;
Update:
You can even omit the vector altogether and output the tokens as you read them from the input strieam
std::string s;
for (int i = 0; fin >> s; ++i)
std::cout << "Token[" << i << "] = " << token[i] << std::endl;

Related

what can I get sum that string tokens converted int in C++?

I need to sum 100, 200, 300 in a.txt
a.txt
2323|A|5|0|2|100
2424|B|6|1|3|200
2525|C|7|2|4|300
so I opened this file, and read line by line using getline(), and tokenized.
main.cpp
for (std::string each; std::getline(split, each, split_char); tokens.push_back(each)) {
for (int i = 0; i < tokens.size(); i++) {
std::cout << tokens[i] << std::endl;
tokens.pop_back();
}
}
As expected, that code printed singly of all things.
so I thought using token index to sum values. but my code have error.
"vector subscript out of range" or no compile.
first try
for (std::string each; std::getline(split, each, split_char); tokens.push_back(each)) {
for (int i = 0; i < tokens.size(); i++) {
std::cout << tokens[i] << std::endl;
tokens.pop_back();
std::cout << tokens[5] << std::endl;
std::cout << tokens[11] << std::endl;
std::cout << tokens[17] << std::endl;
int a = 0;
int b = 0;
int c = 0;
int sum = 0;
a = stoi(tokens[5]);
b = stoi(tokens[11]);
c = stoi(tokens[17]);
sum = (a + b + c);
std::cout << sum << std::endl;
}
}
second try
for (std::string each; std::getline(split, each, split_char); tokens.push_back(each)) {
if(tokens.size() > 4) {
for (int k = 0; k < ((tokens.size() - 5) / 6) + 1; k++) {
int sum = 0;
int change = 0;
int j = 0;
j = 6 * k + 5;
change = stoi(tokens[j]);
sum += change;
std::cout << sum << std::endl;
tokens.pop_back();
}
}
}
what should I do sum value? and I'm wondering that tokens.size()`s meaning except meaning "size" because second for statement always get an error if not exactly correcting i < tokens.size()
You are modifying the tokens vector while you are looping through it. Don't do that. You are affecting its size(), which accounts for why you are able to go out of bounds.
You say that you need to sum only the last token of each line. But that is not what your code is trying to do. There is no need for an inner for loop at all. Simply split each line into a local tokens vector and then use tokens.back() to get the last token, eg:
std::string line;
int sum = 0;
while (std::getline(inFile, line))
{
std::istringstream iss(line);
std::vector<std::string> tokens;
std::string token;
while (std::getline(iss, token, '|')) {
tokens.push_back(token);
}
// use tokens as needed...
token = tokens.back();
sum += std::stoi(token);
}
std::cout << sum << std::endl;
Live Demo
I would like to structure my code slightly differently.
Rather than try and do everything in the main function split your code up so that you read each line and validate it is correct:
#include <iostream>
#include <string>
// A structure representing the data we want to parse.
struct DataLine
{
int v1;
char c;
int v2;
int v3;
int v4;
int v5;
// An input operator that will read one line of data.
// If the data is valid will update the variable we are reading into.
friend std::istream& operator>>(std::istream& str, DataLine& data)
{
DataLine tmp;
char s[5];
std::string extra;
if ( str >> tmp.v1 >> s[0] && s[0] == '|'
&& str >> tmp.c >> s[1] && s[1] == '|'
&& str >> tmp.v2 >> s[2] && s[2] == '|'
&& str >> tmp.v3 >> s[3] && s[3] == '|'
&& str >> tmp.v4 >> s[4] && s[4] == '|'
&& str >> tmp.v5
&& std::getline(str, extra) && extra.empty())
{
// all the data was read and the line was valid.
// update the correct variable.
swap(tmp, data);
}
else {
// there was an issue.
// set the stream to bad so that reading will stop.
str.setstate(std::ios::badbit);
}
return str;
}
// Standard swap method.
friend void swap(DataLine& lhs, DataLine& rhs) noexcept
{
using std::swap;
swap(lhs.v1, rhs.v1);
swap(lhs.c , rhs.c );
swap(lhs.v2, rhs.v2);
swap(lhs.v3, rhs.v3);
swap(lhs.v4, rhs.v4);
swap(lhs.v5, rhs.v5);
}
};
Then the loop you use to read the data becomes really trivial to implement.
int main()
{
DataLine data;
int sum = 0;
// Now we can read the data in a simple loop.
while(std::cin >> data) {
sum += data.v5;
}
std::cout << "Sum: " << sum << "\n";
}

print 2nd word in a string with its size in C++

I am trying to make a program in which a user enters a string and i will print out the second word in the string with its size.
The delimiter's are space( ), comma(,) and tab( ).
I have used a character array and fgets to read from user and a character pointer that points to the first element of the array.
source code:
#include"iostream"
#include<stdio.h>
#include<string>
using namespace std;
// extract the 2nd word from a string and print it with its size(the number of characters in 2nd word)
int main()
{
char arr[30], arr1[30];
char *str = &arr1[0];
cout<<"Enter a string: ";
fgets(str, 30, stdin);
int i = 0, j, count = 1, p = 0; // count is used to find the second word
// j points to the next index where the first delimiter is found.
// p is used to store the second word found in character array 'arr'
while(*(str+i) != '\n')
{
if(*(str+i) == ' ' || *(str+i) == ',' || *(str+i) == ' ')
{
count++;
if(count == 2)
{
// stroing 2nd word in arr character array
j = i+1;
while(*(str+j) != ' ' || *(str+j) != ',' || *(str+j) != ' ')
{
arr[p] = *(str+j);
cout<<arr[p];
p++;
i++;
j++;
}
break;
}
}
i++;
}
arr[p+1] = '\0'; // insert NULL at end
i = 0;
while(arr[i] != '\0')
{
cout<<arr[i];
i++;
}
cout<<"("<<i<<")"<<endl;
return 0;
}
Help me out with this.
To start, don't use std::cin for testing. Just set a value in your code for consistency and ease of development. Use this page for a reference.
#include <iostream>
#include <string>
int main() {
std::string str("this and_that are the tests");
auto start = str.find_first_of(" ,\n", 0);
auto end = str.find_first_of(" ,\n", start + 1);
std::cout << str.substr(start, end - start);
return 0;
}
And this is still somewhat of a hack, it just depends where you are going. For instance the Boost library is rich with extended string manipulation. If you are going to parse out more than just one word it can still be done with string manipulations, but ad-hoc parsers can get out of hand. There are other tools like Boost Spirit to keep code under control.
The delimiters used when extracting from a stream depends on the locale currently in effect. One (cumbersome) way to change the extraction behaviour is to create a new locale with a special facet in which you specify your own delimiters. In the below example the new locale is used to imbue a std::stringstream instead of std::cin directly. The facet creation part is mostly copy/paste from other answers here on SO, so you'll find plenty of other examples.
#include <iostream>
#include <locale> // std::locale, std::ctype<char>
// https://en.cppreference.com/w/cpp/locale/ctype_char
#include <sstream> // std::stringstream
#include <algorithm> // std::copy_n
#include <vector> // a container to store stuff in
// facet to create our own delimiters
class my_facet : public std::ctype<char> {
mask my_table[table_size];
public:
my_facet(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
// copy the "C" locales table to my_table
std::copy_n(classic_table(), table_size, my_table);
// and create our delimiter specification
my_table[' '] = (mask)space;
my_table['\t'] = (mask)space;
my_table[','] = (mask)space;
}
};
int main() {
std::stringstream ss;
// create a locale with our special facet
std::locale loc(std::locale(), new my_facet);
// imbue the new locale on the stringstream
ss.imbue(loc);
while(true) {
std::string line;
std::cout << "Enter sentence: ";
if(std::getline(std::cin, line)) {
ss.clear(); // clear the string stream from prior errors etc.
ss.str(line); // assign the line to the string stream
std::vector<std::string> words; // std::string container to store all words in
std::string word; // for extracting one word
while(ss>>word) { // extract one word at a time using the special facet
std::cout << " \"" << word << "\" is " << word.size() << " chars\n";
// put the word in our container
words.emplace_back(std::move(word));
}
if(words.size()>=2) {
std::cout << "The second word, \"" << words[1] << "\", is " << words[1].size() << " chars\n";
} else {
std::cout << "did not get 2 words or more...\n";
}
} else break;
}
}
#include"iostream"
#include<stdio.h>
#include<string>
#include <ctype.h>
using namespace std;
int main()
{
char c;
string str;
char emp = ' ';
cout<<"Enter a string: ";
getline (cin,str);
int j = 0, count = 1, counter = 0;
for (int i = 0; i < str.length() && count != 2; i++)
{
cout<< str[i] <<endl;
if( isspace(str[i]) || str[i] == ',' || str[i] == '\t' )
{
count++;
if(count == 2)
{
j = i+1;
while(j < str.length())
{
if (isspace(str[j]) || str[j] == ',' || str[j] == '\t')
{
break;
}
cout<<str[j];
counter++;
j++;
}
cout<<endl;
}
}
}
cout<<"size of the word: "<<counter<<endl;
return 0;
}
This is a simple answer to what you want, hope to help you.
// Paul Adrian P. Delos Santos - BS Electronics Engineering
// Exercise on Strings
#include <iostream>
#include <sstream>
using namespace std;
int main(){
// Opening Message
cout << "This program will display the second word and its length.\n\n";
// Ask for a string to the user.
string input;
cout << "Now, please enter a phrase or sentence: ";
getline(cin, input);
// Count the number of words to be used in making a string array.
int count = 0;
int i;
for (i=0; input[i] != '\0'; i++){
if (input[i] == ' ')
count++;
}
int finalCount = count + 1;
// Store each word in a string array.
string arr[finalCount];
int j = 0;
stringstream ssin(input);
while (ssin.good() && j < finalCount){
ssin >> arr[j];
j++;
}
// Display the second word and its length.
string secondWord = arr[1];
cout << "\nResult: " << arr[1] << " (" << secondWord.size() << ")";
return 0;
}

C++ insertion sort from a txt file

I have to read from a .txt file and out it with a different .txt file. I have to use insertion sort in order to sort them based on two numbers. I could only get this far, I don't know how to do insertion sort in this program where I have two numbers to sort to.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(void)
{
int serialno[100], suratno[100], ayatno[100];
string order;
string str;
char ch;
int i = 0;
int j, temp;
ifstream fin;
fin.open("text.txt");
if(!fin)
{
cout << "Cannot open file \'text.txt\'! Quitting.\n";
exit(0);
}
while(fin)
{
fin.get(ch); //gets .
getline(fin, order, '('); //allegedly it removes the delimiter char from stream too
fin >> suratno;
fin.get(ch); //gets :
fin >> ayatno;
fin.get(ch); //gets )
fin.get(ch); //gets \n
cout << serialno << "." << order << "("<<suratno<<":<<ayatno<<")\n";
}
fin.close();
//sort algorithm
for (int i = 0; i < length; i++){
j = i;
while (j > 0 && suratno [j] < suratno [j-1]){
temp = suratno [j];
suratno [j] = suratno [j-1];
suratno [j-1] = temp;
j--;
cout << serialno << endl;
}
}
}
ofstream fout;
fout.open("newtext.txt");
if(!fout)
{
cout << "Cannot open output file\'orderedquranorders.txt\'!Quitting.\n";
exit(0);
}
i = 0;
//write sorted list to output file
fout.close();
cout << i << " orders successfully sorted and written.\n";
}
this is the text file (numbers in bracket should be used, firstly with number before colon, and secondly with number after colon):
1. Do not be rude in speech (3:159)
2. Restrain Anger (3:134)
3. Be good to others (4:36)
4. Do not be arrogant (7:13)
5. Forgive others for their mistakes (7:199)
6. Speak to people mildly (20:44)
7. Lower your voice (31:19)
8. Do not ridicule others (49:11)
9. Be dutiful to parents(17:23)
current output:
Do not be rude in speech (3:159)
Restrain Anger (3:134)
Be good to others (4:36)
Be dutiful to parents(17:23)
expected output:
Restrain Anger (3:134)
Do not be rude in speech (3:159)
Be good to others (4:36)
Be dutiful to parents(17:23)
sorted in terms of both the numbers and the serial no stays the same
In order to compare two pair of numbers, you can make comparisons like:
if(suratno[i] < suratno[i-1] || (suratno[i] == suratno[i-1] && ayatno[i] < ayatno[i-1])){
/* swap */
}
Or you can use one expression: expr = suratno * 10000 + ayatno. And make just one comparison:
if(expr[i] < expr[i-1]){
/* swap */
}
Also, I have a few observations about your algorithm/code:
Don't use using namespace std. Specially in big programs, because it can cause obscure bugs (see an example here). Instead use using std::<name> when you want to avoid std::. Ex. using std::string. In general, avoid using namespace xxxx.
I see you did parse the input lines manually, I prefer to use regular expressions, that are much more versatile and powerful, but requires a little learning.
When it's necessary to write an error message, always write to stderr stream cerr in C++.
In the sort algorithm, it's better start in 1 than 0, because the first item doesn't have a previous item to compare with.
Finally the swap can be done with an existent C++ function.
Here is your code reorganized and using regular expressions that I tried to explain as much as possible:
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <vector>
#include <algorithm>
using std::string;
struct Line {
int expr; // Expression used to compare
string text; // Original line without initial number
};
int main() {
std::regex linePattern(
"\\d+" // 1 or more digits
"\\. " // '. ' (dot followed by 1 space)
"(" // begin char group #1
".*" // zero or more chars
"\\(" // '(' (left parenthesis)
"(\\d+)" // char group #2 (suratno: 1+ digits)
":" // ':' (colon)
"(\\d+)" // char group #3 (ayatno: 1+ digits)
"\\)" // ')' (right parenthesis)
")" // end char group #1
);
std::smatch groups; // Regular expression found char groups
std::vector<Line> lines; // Vector to store the readed lines
// Read lines parsing content
std::ifstream fin("text.txt");
if(!fin){
std::cerr << "Cannot open file 'text.txt'! Quitting.\n";
return 1;
}
string line;
while (std::getline(fin, line))
if (std::regex_search(line, groups, linePattern) && groups.size() > 0) {
int suratno = std::stoi(groups[2]);
int ayatno = std::stoi(groups[3]);
int compExpr = suratno * 10000 + ayatno; // assumes ayatno < 10,000
lines.push_back({ compExpr, groups[1] });
}
fin.close();
// sort algorithm (better start in 1)
for (size_t i = 1; i < lines.size(); i++)
for (size_t j = i; j > 0 && lines[j].expr < lines[j - 1].expr; j--)
std::swap(lines[j], lines[j - 1]);
std::ofstream fout("newtext.txt");
if(!fout){
std::cerr << "Cannot open output file 'orderedquranorders.txt'! Quitting.\n";
return 1;
}
for (size_t i = 0; i < lines.size(); i++)
fout << i + 1 << ". " << lines[i].text << std::endl;
fout.close();
std::cout << lines.size() << " orders successfully sorted and written.\n";
return 0;
}
Note: The regular expression is really one string "\\d+\\. (.*\\((\\d+):(\\d+)\\))", I used a C/C++ feature that concatenates strings separated by spaces before compilation, so the compiler sees only one string.
Don't forget to compile with -std=c++11 option.
using namespace std; is considered bad practice and can be dangerous sometimes. Check this
Here is your solution:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
int suratno[100], ayatno[100];
std::string order[100];
char ch;
int count = 0;
int tempInt;
std::string tempStr;
std::ifstream fin;
fin.open("text.txt");
if (!fin)
{
std::cout << "Cannot open file \'text.txt\'! Quitting.\n";
exit(0);
}
else
{
while (fin)
{
fin.get(ch); //gets the numbers
fin.get(ch); //gets .
getline(fin, order[count], '('); //allegedly it removes the delimiter char from stream too
fin >> suratno[count];
fin.get(ch); //gets :
fin >> ayatno[count];
fin.get(ch); //gets )
fin.get(ch); //gets \n
std::cout << count + 1 << "." << order[count] << "(" << suratno[count] << ":" << ayatno[count] << ")\n";
count++;
}
}
fin.close();
std::cout << std::endl;
// sort algorithm (we must sort two times)
for (int i = 0; i < count; i++)
{
for (int j = i; j > 0 && suratno[j] < suratno[j - 1]; j--)
{
tempInt = suratno[j];
suratno[j] = suratno[j - 1];
suratno[j - 1] = tempInt;
tempInt = ayatno[j];
ayatno[j] = ayatno[j - 1];
ayatno[j - 1] = tempInt;
tempStr = order[j];
order[j] = order[j - 1];
order[j - 1] = tempStr;
}
}
for (int i = 0; i < count; i++)
{
for (int j = i; j > 0 && suratno[j] == suratno[j - 1] && ayatno[j] < ayatno[j - 1]; j--)
{
tempInt = ayatno[j];
ayatno[j] = ayatno[j - 1];
ayatno[j - 1] = tempInt;
tempInt = suratno[j];
suratno[j] = suratno[j - 1];
suratno[j - 1] = tempInt;
tempStr = order[j];
order[j] = order[j - 1];
order[j - 1] = tempStr;
}
}
// print the sorted list just to check
for (int i = 0; i < count; i++)
{
std::cout << i + 1 << "." << order[i] << "(" << suratno[i] << ":" << ayatno[i] << ")\n";
}
// write sorted list to output file
std::ofstream fout;
fout.open("newtext.txt");
if (!fout)
{
std::cout << "Cannot open output file\'orderedquranorders.txt\'!Quitting.\n";
exit(0);
}
else
{
for (int i = 0; i < count; i++)
{
fout << i + 1 << "." << order[i] << "(" << suratno[i] << ":" << ayatno[i] << ")\n";
}
}
fout.close();
std::cout << std::endl;
std::cout << count << " orders successfully sorted and written.\n";
return 0;
}

Text parsing a log file effectively in c++

I want to build a log browser. For which I need to code effectively. Given is a simple code for parsing.
Please let me know if this code is okay or any improvements to be given.
Also strtok(o,delim) function in the below given program is not clear. So please explain me about its functionality.
// parsing ex.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cstring>
const int MAX_CHARS_PER_LINE = 512;
const int MAX_TOKENS_PER_LINE = 20;
const char* const DELIMITER = " ";
int main()
{
// create a file-reading object
ifstream fin;
fin.open("C:\\Personal\\data.txt"); // open a file
if (!fin.good())
return 1; // exit if file not found
// read each line of the file
while (!fin.eof())
{
// read an entire line into memory
char buf[MAX_CHARS_PER_LINE];
fin.getline(buf, MAX_CHARS_PER_LINE);
// parse the line into blank-delimited tokens
int n = 0; // a for-loop index
// array to store memory addresses of the tokens in buf
const char* token[MAX_TOKENS_PER_LINE] = {}; // initialize to 0
// parse the line
token[0] = strtok(buf, DELIMITER); // first token
if (token[0]) // zero if line is blank
{
for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
{
token[n] = strtok(0, DELIMITER); // subsequent tokens
if (!token[n]) break; // no more tokens
}
}
// process (print) the tokens
for (int i = 0; i < n; i++) // n = #of tokens
cout << "Token[" << i << "] = " << token[i] << endl;
cout << endl;
}
}
Your code works, except there are no boundary checks. It will fail if a line in the file is longer than MAX_CHARS_PER_LINE. while (!fin.eof()){...} is prone to other errors as well.
You can easily solve this problem with std::string
The code also fails if a line contains more than MAX_TOKENS_PER_LINE tokens. You can solve this by using std::vector
For improvements, use std::string instead of character arrays.
Use std::vector instead of C-style arrays.
Use std::stringstream instead of strtok
The advantage is that you don't have to worry about maximum line length, or maximum number of tokens per line.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
const char CDELIMITER = ' ';
int main()
{
...
std::string buf;
//read the file line by line
while (std::getline(fin, buf))
{
//convert the line in to stream:
std::istringstream ss(buf);
//declare vector of string (instead of fixed array)
std::vector<std::string> vec;
//read the line, word by word
while (std::getline(ss, buf, CDELIMITER))
vec.push_back(buf);
for (size_t i = 0; i < vec.size(); i++)
std::cout << "Token[" << i << "] = " << vec[i] << "\n";
std::cout << "\n";
}
return 0;
}

parsing a text file with first line all 1's and second line all 2's

i have created a program which will take a file read a text file line-by-line, and separate out the individual words in each line (as separated by blanks).
now i want to be able to edit the code so that all the tokens for the first line will be all 1's and all the tokens for the second line will be 2's
if any one could help me with this please
down below is my code:
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cmath>
#include <string>
const int MAX_CHARS_PER_LINE = 512;
const int MAX_TOKENS_PER_LINE = 20;
const char* const DELIMITER = " ";
using namespace std;
int main()
{
string filename;
// create a file-reading object
/*std::ifstream file1("file1.txt", ios_base::app);
std::ifstream file2("file2.txt");
std::ofstream combinedfile("combinedfile.txt");
combinedfile << file1.rdbuf() << file2.rdbuf();*/
ifstream fin;
//enter in file name combinedfile.txt
cout <<"please enter file name (including .txt)";
cin >> filename ;
fin.open(filename); // open a file
if (!fin.good())
return 1; // exit if file not found
// read each line of the file
while (!fin.eof())
{
// read an entire line into memory
char buf[MAX_CHARS_PER_LINE];
fin.getline(buf, MAX_CHARS_PER_LINE);
// parse the line into blank-delimited tokens
int n = 0; // a for-loop index
// array to store memory addresses of the tokens in buf
const char* token[MAX_TOKENS_PER_LINE] = {}; // initialize to 0
// parse the line
token[0] = strtok(buf, DELIMITER); // first token
if (token[0]) // zero if line is blank
{
for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
{
token[n] = strtok(0, DELIMITER); // subsequent tokens
if (!token[n]) break; // no more tokens
}
}
// process (print) the tokens
for (int i = 0; i < n; i++) // n = #of tokens
cout << "Token[" << i << "] = " << token[i] << endl;
cout << endl;
}
system("pause");
return 0;
}
so the output should be like this:
Token[1] = This
Token[1] = course
Token[1] = provides
Token[1] = detailed
Token[1] = coverage
Token[1] = of
Token[1] = the
Token[1] = concepts
Token[1] = and
Token[1] = syntax
Token[2] = Coverage
Token[2] = includes
Token[2] = inheritance,
Token[2] = overloaded
Token[2] = operators,
Token[2] = overloaded
Token[2]= default
Token[2] = operators,
If you just want to separate words into two containers such that the first contains words from the first line, and the second contains words from the second line, you can use vectors to store them and string streams to extract words from a line of text:
#include <sstream>
#include <string>
#include<vector>
#include<fstream>
using namespace std;
int main()
{
ifstream infile("test.txt");
string line;
string word;
vector< vector<string> > tokens(2);
for (int ix = 0; ix < 2; ++ix)
{
getline(infile, line);
istringstream iss(line);
while(iss >> word)
tokens[ix].push_back(word);
}
}
Here, tokens[0] is a vector containing words from the first line, and tokens[1] contains words from the second line.
You can create a vector of vectors as
vector<vector<string>> VEC;
And keep on adding words to VEC[0] for the first line and then increment the counter as you encounter a newline character to point to VEC[1] and so on.