Having trouble with spaces while reading in sentences from separate text file - c++

While reading in data from a separate text file, it doesn't keep the spaces and instead looks comes out looking like :
Todayyouareyouerthanyou,thatistruerthantrue
When it should have the spaces and say:
Today you are youer than you, that is truer than true
Here is my code that I have so far:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
std::ifstream inFile;
inFile.open("Rhymes.txt", std::ios::in);
if (inFile.is_open())
{
string word;
unsigned long wordCount = 0;
while (!inFile.eo())
{
cout << word;
inFile >> word;
if (word.length() > 0)
{
wordCount++;
}
}
cout << "The file had " << wordCount << " word(s) in it." << endl;
}
system("PAUSE");
return 0;
}
The "Rhymes.txt" has many phrases such as the one above and I'll just add 2 more so it's not a lot on here. Here they are:
Today you are You, that is truer than true. There is no one alive who is Youer than You.
The more that you read, the more things you will know. The more that you learn, the more places you'll go.
How did it get so late so soon? Its night before its afternoon.
Any help or advice would be greatly appreciated!! Also I am a beginner so if this turns out to be something really obvious, sorry!

How about inserting the spaces back to your output, so instead of this
cout << word;
You put this:
cout << word << " ";
Another option would be to read whole lines from your input file and then split them to words.

Issues that I see:
You are writing out word before the first read.
Reading the words using inFile >> word skips the white spaces. You need to add code to write the white spaces.
I am not sure what you were thinking with the following block of code. But, it is not necessary.
if (word.length() > 0)
{
wordCount++;
}
You can simplify your while loop to:
while (inFile >> word)
{
cout << word << " ";
wordCount++;
}
This will print an extra white space at the end. If that is objectionable, you can add more logic to fix that.

Let's fix the typo: inFile.eo() -> inFile.eof() and include stdlib.h for system(). Now you can put the spaces back by writing cout << word << " ";
But your program seems to be out by 1. Linux wc says 53 words but your program says 54. So I fixed your loop like this:
while (true)
{
inFile >> word;
if (inFile.eof())
break;
if (word.length() > 0)
{
wordCount++;
cout << word << " ";
}
}
Now it agrees with wc.

Related

How to print multilple words in c++

I can get the file to save right but I can't seem to get multiple words to write to .txt, like if I type "Hi purple" it just writes "Hi", here is code
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
system("color F0");
string name0;
cout << "Please enter a file name, no spaces/special characters" << endl;
cin >> name0;
name0 = name0+".txt";
system("cls");
cout << " FISHSOFT" << endl;
cout << "The best text editor in the world" << endl << endl;
string text;
cin >> text;
ofstream myfile;
myfile.open (name0.c_str() , ios::out | ios::trunc);
myfile << text;
myfile.close();
system("PAUSE");
return 0;
}
Use std::getline to read an entire line of input including spaces.
cin >> text; will read one whitespace delimited token from the input stream. One word in == one word out.
std::getline(cin, text); will read a whole line. Reading more than that is tricky, but typically a loop around multiple calls to getline.
Suggestion: Save yourself time and fire up your IDE's debugger to see what's happening in your code before posting a question. Almost always faster, and if not, you can make much better, tighter-focused questions.
std::cin is able to get several parameters at once.
That mean you may write:
std::cin >> name0 >> name1 >> name2;
// input: a1 a2 a3
// make: name0: a1, name1: a2, name3:a3
By default, the space is the separator between parameters.
To avoid this behavior, you could use getLine:
std::getline(std::cin, name0);
There are 2 ways to get the string with spaces and special character.
cin.getline(name);
gets(name);
Hope this will serve your purpose.

Why is this word sorting program only looping once?

I'm trying to create a word sorting program that will read the words in a .txt file and then write them to a new file in order from shortest words to longest words. So, for instance, if the first file contains:
elephant
dog
mouse
Once the program has executed, I want the second file (which is initially blank) to contain:
dog
mouse
elephant
Here's the code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string word;
ifstream readFrom;
ofstream writeTo;
readFrom.open("C:\\Users\\owner\\Desktop\\wordlist.txt");
writeTo.open("C:\\Users\\owner\\Desktop\\newwordlist.txt");
if (readFrom && writeTo)
{
cout << "Both files opened successfully.";
for (int lettercount = 1; lettercount < 20; lettercount++)
{
while (readFrom >> word)
{
if (word.length() == lettercount)
{
cout << "Writing " << word << " to file\n";
writeTo << word << endl;
}
}
readFrom.seekg(0, ios::beg); //resets read pos to beginning of file
}
}
else
cout << "Could not open one or both of files.";
return 0;
}
For the first iteration of the for loop, the nested while loop seems to work just fine, writing the correct values to the second file. However, something goes wrong in all the next iterations of the for loop, because no further words are written to the file. Why is that?
Thank you so much.
while (readFrom >> word)
{
}
readFrom.seekg(0, ios::beg); //resets read pos to begin
The while loop will continue until special flags are set on readFrom, namely, the EOF flag. Seeking to the beginning does not clear any flags, including EOF. Add the following line right before the seek to clear the flags and your code should work fine.
readFrom.clear();
After seek, clear the EOF flag.
readFrom.clear();

HW Help: get char instead of get line C++

I wrote the code below that successfully gets a random line from a file; however, I need to be able to modify one of the lines, so I need to be able to get the line character by character.
How can I change my code to do this?
Use std::istream::get instead of std::getline. Just read your string character by character until you reach \n, EOF or other errors. I also recommend you read the full std::istream reference.
Good luck with your homework!
UPDATE:
OK, I don't think an example will hurt. Here is how I'd do it if I were you:
#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
static std::string
answer (const string & question)
{
std::string answer;
const string filename = "answerfile.txt";
ifstream file (filename.c_str ());
if (!file)
{
cerr << "Can't open '" << filename << "' file.\n";
exit (1);
}
for (int i = 0, r = rand () % 5; i <= r; ++i)
{
answer.clear ();
char c;
while (file.get (c).good () && c != '\n')
{
if (c == 'i') c = 'I'; // Replace character? :)
answer.append (1, c);
}
}
return answer;
}
int
main ()
{
srand (time (NULL));
string question;
cout << "Please enter a question: " << flush;
cin >> question;
cout << answer (question) << endl;
}
... the only thing is that I have no idea why do you need to read string char by char in order to modify it. You can modify std::string object, which is even easier. Let's say you want to replace "I think" with "what if"? You might be better off reading more about
std::string and using find, erase, replace etc.
UPDATE 2:
What happens with your latest code is simply this - you open a file, then you get its content character by character until you reach newline (\n). So in either case you will end up reading the first line and then your do-while loop will terminate. If you look into my example, I did while loop that reads line until \n inside a for loop. So that is basically what you should do - repeat your do-while loop for as many times as many lines you want/can get from that file. For example, something like this will read you two lines:
for (int i = 1; i <= 2; ++i)
{
do
{
answerfile.get (answer);
cout << answer << " (from line " << i << ")\n";
}
while (answer != '\n');
}

Why istream::getline() returns so many times (with nothing)

I am trying to read a poorly formatted text file, and maybe I'm going about this the wrong way, but based on the getline documentation it sounded like it would pull values until the values weren't a delimiter value (' ', in my case):
"If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it. If you
don't want this character to be extracted, you can use member get
instead."
But for some reason it returns nothing many times. See lines 604-607, all those commas in my output are returns of getline. Could someone tell me why it is returning blanks 6 times before it comes to the value? The text file only contains one space before the value. Thanks in advance. :)
Relevant screenshot: http://j.drhu.me/2011-09-07_1317.png
#include <iostream>
#include <fstream>
#include <string>
void CMuscleModel::LoadOpParams()
{
int i, j;
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss, isn;
string line, word;
i=0; j=0;
while (getline(param,line))
{
isn.clear();
isn << line;
if(i>27){
while (getline(isn,word,' ')) {
//LGma[i][j]=atof(word.c_str());
if(word == "SM"){
getline(param,line);
cout << line << endl << endl;
isn.clear(); isn << line;
getline(isn,word,' ');
int junk=0;
while (atof(word.c_str())==0){
junk++;
getline(isn,word,' ');
}
cout << atof(word.c_str()) << ", " << junk << endl;
}
if(word == "ST"){
cout << word << endl;
}
if(word == "BFL"){
cout << word << endl;
}
if(word == "BFS"){
cout << word << endl;
}
if(word == "MG"){
cout << word << endl;
}
if(word == "LG"){
cout << word << endl;
}
if(word == "RF"){
cout << word << endl;
}
if(word == "VM"){
cout << word << endl;
}
if(word == "VL"){
cout << word << endl;
}
if(word == "VI"){
cout << word << endl;
}
j++;
}
}
j=0; i++;
isn.clear();
}
}
param.close();
}
Ah, sorry for not including code.
If you're using space as a delimiter anytime it's encountered getline will return with whatever there was upto the delimiter. If the file had 5 spaces in a row before any other characters for example you'd now have to call getline 6 times.
Perhaps use the default newline character instead '\n'?
Edit: Didn't see code before. Perhaps restructure your code to read lines and then use find in conjunction with substr on each line to search for your keywords? Would be simpler code and less looping. There is no reason to read from the file only to output to a stringstream which you then read from.
Bi-directional I/O with std::stringstream is really ambiguous. I recommand that you use it a little differently.
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss;
string line, word;
i=0; j=0;
while (getline(param,line))
{
istringstream isn(line);
// ...
}
}
This creates a fresh string stream with clean state and contains the contents of the line read from the file each time. If you really want to re-use the instance for reading tokens on multiple lines, I recommand you use the .str(line) syntax rather than .clear() and operator<<.
If you want to clear the whitespace at the beginning of each line, you can use the std::ws manipulator:
istringstream isn(line);
isn >> ws;
// ...
I think the output text file I was reading from had trailing spaces and they were just being put into the stream so I was really confused about what was going on. I simply used .str("") at the end of each line to reset my current stream and things worked out marvelously. Thanks for all the help guys.

Reading file input as opcode in C++

I am working on a project for a class at school. It is a simple implementation of stacks and queues. However as part of the project we are require to read opcode in from a file. The opcode is formated as follows:
append 10
serve
append 20
append 30
serve
push 10
push 50
push 20
push 20
pop
My problem is when I read in the file through a standard fstream it seems to pick up some kind of weird formatting or something, and won't match comparison checks.
I am wonder what I am doing wrong, how to fix it, and if there is a better way to manipulate opcode going forward. As it is, the if-else statement always goes to if. Kind of desperately need to get this working.
#include "StackAndQueue.h"
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main(){
Stack leStack;
Queue leQueue;
//Read in the datafile.
cout << "Reading default file: p2datafile.txt";
fstream data("p2datafile.txt");
while (data.fail()){
cout << " failed." << endl;
data.close();
cout << "Please enter path to datafile: ";
string filename;
cin >> filename;
data.open(filename.c_str());
}
cout << endl << "Sucess!" << endl;
//Loop through all the commands in the file
while(!data.eof()){
// Determine what kind of command is running
// and if parsing will be needed.
string opcode;
getline(data,opcode,' ');
if (opcode == "pop"){
cout << "popping!" << endl;
leStack.pop();
}
else if (opcode == "serve"){
cout << "serving" << endl;
leQueue.serve();
}
else if (opcode == "push"){
cout << "pushing";
}
else{
cout << "else!" << endl;
}
}
data.close();
system("pause");
return 0;
}
I apologize if the code is difficult to read, and the general half-finished nature of it. I am still pretty new to this.
getline used in that way considers just ' ' as a delimiter, so it won't stop at newlines; moreover, you're not extracting the argument (when the opcodes has any), so it will get read as an opcode (sticked in front of the real opcode) at the next iteration.
In my opinion, you could simply get away with using just the normal operator>>. It stops correctly at any whitespace (which is what you want to do) and supports the C++ strings correctly. The important thing is to remember to extract also the argument when needed (again, with operator>>), watching for istream::fail() errors in case of bad number formatting. You may even want to have the stream rise exceptions in case of these errors (so they don't go unnoticed).
try
{
string opcode;
data.exceptions(ios::failbit);
//Loop through all the commands in the file
while(data>>opcode){
// Determine what kind of command is running
// and if parsing will be needed.
int argument;
if (opcode == "pop"){
cout << "popping!" << endl;
leStack.pop();
}
else if (opcode == "serve"){
cout << "serving" << endl;
leQueue.serve();
}
else if (opcode == "push"){
cout << "pushing";
data >> argument;
}
else if (opcode == "append"){
cout << "appending";
data >> argument;
}
else{
cout << "else!" << endl;
}
}
data.close();
}
catch(const ios::failure & ex)
{
if(!data.eof())
cout<<"IO error"<<endl;
}
the problem you are most likely having stems from the way you are reading input. std::getline(..., ' ') extracts a string that ends with a space. With the given input, the first string gotten will be append, but the second will be
10
serve
append
because there are no spaces.
How about this, instead of trying to read in an opcode exactly, read a line, and see if you can figure out if it begins with an opcode.
Rather than reading the file a word a a time, read the entire line (using std::getline) then use a std::stringstream to process the line, something like this:
std::string line;
while(std::getline(file,line))
{
std::stringstream linestream(std::stringstream::in|std::stringstream::out);
linestream << line;
std::string command;
if(std::getline(linestream,command,' '))
{
//process line - chain 'if(std::getline(linestream,command,' '))' to advance the token steam
}
else
//error blank line
}