I am trying to create a parser class that will parse a file based on " " and place the words into a linked list.
class FileReader
{
public:
FileReader(char* file)
{
ifstream fout (file, ifstream::in);
string hold;
while (fout.good())
{
getline (fout, hold, " ");
cout << hold;
}
fout.close();
}
};
The function getline(fout, hold, " ") is not recognizing " " as the delimiter.
I have not coded the linked list part as of yet so this is just the parsing part of the program.
Also would there be a better way to create a parser?
It should just work like this:
#include <fstream>
#include <iterator>
#include <list>
#include <string>
std::ifstream infile(file);
std::list<std::string> words(std::istream_iterator<std::string>(infile),
std::istream_iterator<std::string>());
Now words is your linked list of whitespace-separated tokens.
Lesson: The best kind of code is the one you don't have to write.
The last parameter in getline is a char not a string. Looking at your current code, you want getline(fout,hold,' ') or just getline(fout,hold) -- *if you want the whole line.
*: edit
Related
Using C++ on Linux I am parsing(for words based on multiply delimiters) a big input that is provided via the stdin(no other way).
I read the stdinput using std::getline and then parse the line using the following pseudo code.
for (std::string single_line; std::getline(std::cin, single_line);)
{
std::string single_word;
for (auto single_charecter : single_line)
{
//do parsing based on a delimiter and
// create a word
}
}
My question is regarding the efficiency of me using std::getline and then parsing the line one char at a time.
Cant this be improved using other function calls or maybe some approach that includes the use of threads?
From what I understand, you are trying to parse a text input and trying to create words based on delimiters. If this is the case, you don't need to parse one line at a time. You can directly use stringstream Class and getline Method to Parse String Using a Delimiter Try this -
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using std::cout; using std::cin;
using std::endl; using std::string;
using std::vector; using std::stringstream;
int main(){
string text = "He said. The challenge Hector heard with joy, "
"Then with his spear restrain'd the youth of Troy ";
char del = ' ';
vector<string> words{};
stringstream sstream(text);
string word;
while (std::getline(sstream, word, del))
words.push_back(word);
for (const auto &str : words) {
cout << str << endl;
}
return EXIT_SUCCESS;
}
OUTPUT -
He
said.
The
...
Troy
In this method, we are putting text string variable into a stringstream to operate on it with the getline method. getline extracts characters until the given char is found and stores the token in the string variable. Notice that this method can only be applied when a single character delimiter is needed.
My program is largely incomplete, but I assumed that using toupper to modify the strings following their input from the textfile would work to change all the characters of said string to uppercase. I read that works with type int, or what I assume is Ascii in this case. But I'm not really sure where to go from here. What is the most efficient means of converting and checking strings from a textfile as far as beginner C++ goes?
I've googled this issue and found a wide variety of ways, such as using std::transform, but I feel like my instructor would only want us using methods taught from our book 'Starting out with C++' by Tony Gaddis. Unfortunately I'm not finding any reference in my book where toupper is being used on textfile input, only on char values. For education's sake I'm hoping you have an idea of what I should be using here and why. I welcome recommended reading.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string text;
ifstream textFile;
int ch;
textFile.open("letter_count.txt", ios::in);
toupper(textFile.get());
isalpha(textFile.get());
if (textFile)
{
// Read an item from the file.
getline(textFile, text);
// While the last read operation
// was successful, continue.
while (textFile)
{
if (textFile)
// Display the last item read.
cout << text << endl;
// Read the next item.
getline(textFile, text);
}
// Close the file.
textFile.close();
}
else
{
cout << "ERROR: Cannot open file. \n";
}
cout << "The most common letter is " " with " " occurances. \n";
cout << "The least common letter is " " with " " occurances. \n";
system("pause");
}
I'm getting no results from using toupper.
That is because toupper takes only one int value. Notice here:
http://www.cplusplus.com/reference/cctype/toupper/?kw=toupper
You have to loop over every char in your string in order to convert it.
My code is intended to tell the user whether the string entered is a keyword in c++.
I am reading the keywords from a file into a set and then checking if the user supplied string is in it.
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <fstream>
using namespace std;
int main()
{
set<string> key;
fstream fs;
string b;
fs.open("keywords.txt",fstream::in);
while(getline(fs,b))
key.insert(b);
b.clear();
for(auto x:key)
cout << x << endl;
cout << "Enter String user\nPress exit to terminate\n";
while(getline(cin,b))
{
if(b == "exit")
break;
if(key.find(b) != key.end())
cout << "This is a keyword\n";
else
cout << "This is a not a keyword\n";
b.clear();
}
fs.close();
}
The keywords.txt file is just a list of keywords and can be obtained from here
The problem is that my program reads all keywords correctly but for some of them such as false,public it cannot find them in the set.
i.e. when I enter false as user input
it says, "This is not a keyword."
Considering your input file, I think you have some keyword names with trailing spaces.
"catch "
"false "
You can trim the strings before inserting in the set to remove spaces, using boost::trim or your own trim (see this question for instance.)
(If you want some advice as for your code:
You can use std::ifstream like this for input file streams:
std::ifstream file( "keywords.txt" );
You do not need to call .close() at then of the scope, it will be done automatically thanks to RAII.
You should not reuse the same std::string objects for every purpose, you can declare new string objects close to their use. You should give them better names like "line" instead of "b". Doing this, you don't need to call ".clear()" for your strings.
Every line has just one word, you could use while(fs>>b) the >> will ignore the spaces (from moldbinlo & wangxf comments)
)
Here is what I got so far:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int characterList = 0;
char* dynamo = new char[1000];
char* buffer = dynamo;
ifstream input("wordlist.txt");
if (input.is_open())
{
input >> dynamo[characterList];
while (input.eof())
{
characterList++;
input >> dynamo[characterList];
cout << dynamo[characterList];
}
}
else
{
cout << "File not opened" << endl;
}
return;
}
I'm a beginner so I do apologize if this looks like terrible coding practice. I created a text file with a quote from Bill Cosby that I'm trying to read one word at a time. The quote is "I don't know the key to success, but the key to failure is trying to please everybody." I'm trying to read one word at a time from a text document ignoring punctuation. I know there are a lot of questions similar to this, but they are using code that I have not learned so I'm sorry for having a repeating question. I have not learned getline (I used cin.getline) and #include <string>.
Edit: I forgot to mention, so I'm sorry for not doing so earlier, but I'm studying dynamic memory allocation which is why I'm using the new char[1000].
I'd suggest you to use std::string instead of manually allocating buffers on the heap with new[] and trying to read text manually from the file into those buffers (and don't forget to free the buffer with proper delete[] calls!).
C++ input stream classes like std::ifstream can simply read text into std::string instances thanks to a proper overload of operator<<.
The syntax is as simple as:
string word;
while (inFile >> word)
{
cout << word << endl;
}
Here's a complete compilable sample code for you to experiment and learn:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
ifstream inFile("test.txt");
if (inFile.is_open())
{
string word;
while (inFile >> word)
{
cout << word << endl;
}
}
else
{
cout << "Can't open file." << endl;
}
}
This is the output I got on a test text file having the content specified in your question:
I
don't
know
the
key
to
success,
but
the
key
to
failure
is
trying
to
please
everybody.
NOTE
Of course, once you have your words read into a std::string instance, you can store them in a container like std::vector<std::string>, using its push_back() method.
I would do something like this:
#include <iostream>
#include <string>
#include <fstream>
int main() {
std::string array[6];
std::ifstream infile("Team.txt");
std::string line;
int i = 0;
while (std::getline(infile, line)) {
array[i++] = line;
}
return 0;
}
based on this answer.
Here, we assume we have to read 6 lines from the file "Team.txt". We use std:::getline() and we put inside a while so that we read all the file.
At every iteration, line holds the current line of the file read. Inside the body we store it in array[i].
i have a little problem on writing the string into a file,
How can i write the string into the file and able to view it as ascii text?
because i am able to do that when i set the default value for str but not when i enter a str data
Thanks.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
fstream out("G://Test.txt");
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
char str[200];
cout << "Enter Customers data seperate by tab\n";
cin >> str;
cin.ignore();
out.write(str, strlen(str));
out.seekp(0 ,ios::end);
out.close();
return 0;
}
Please use std::string:
#include <string>
std::string str;
std::getline(cin, str);
cout << str;
I'm not sure what the exact problem in your case was, but >> only reads up to the first separator (which is whitespace); getline will read the entire line.
Just note that >> operator will read 1 word.
std::string word;
std::cin >> word; // reads one space seporated word.
// Ignores any initial space. Then read
// into 'word' all character upto (but not including)
// the first space character (the space is gone.
// Note. Space => White Space (' ', '\t', '\v' etc...)
You're working at the wrong level of abstraction. Also, there is no need to seekp to the end of the file before closing the file.
You want to read a string and write a string. As Pavel Minaev has said, this is directly supported via std::string and std::fstream:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ofstream out("G:\\Test.txt");
if(!out) {
std::cout << "Cannot open output file.\n";
return 1;
}
std::cout << "Enter Customer's data seperated by tab\n";
std::string buffer;
std::getline(std::cin, buffer);
out << buffer;
return 0;
}
If you want to write C, use C. Otherwise, take advantage of the language you're using.
I can't believe no one found the problem. The problem was that you were using strlen on a string that wasn't terminated with a null character. strlen will keep iterating until it finds a zero-byte, and an incorrect string length might be returned (or the program might crash - it's Undefined Behavior, who knows?).
The answer is to zero-initialize your string:
char str[200] = {0};
Supplying your own string as the value of str works because those in-memory strings are null-terminated.