fpf3
fpf3

Reputation: 424

C++ Fstream Only Prints One Word

This is a very strange issue. I'm trying to print a large text file, it's a Wikipedia entry. It happens to be the page on Velocity. So, when I tell it to print the file, it prints "In", when it should print "In physics, velocity is etc, etc etc". Here's the code I'm using to print out:

#include <iostream>
#include <fstream>

using namespace std;

    int main()
        {
        ifstream wiki;
        wiki.open("./wiki/velocity.txt");
        char* wikiRead;
        wiki >> wikiRead;
        cout << wikiRead << endl;
        wiki.close();
        }

Please help.

Upvotes: 0

Views: 2924

Answers (6)

Bo Persson
Bo Persson

Reputation: 92271

The operator>> is designed to only read one word at a time. If you want to read lines, use getline.

#include <iostream>
#include <fstream>
#include<string>

using namespace std;

int main()
{
    ifstream wiki;
    wiki.open("./wiki/velocity.txt");

    string   wikiRead;

    while (getline(wiki, wikiRead))
    {
        cout << wikiRead << endl;
    }

    wiki.close();
}

Upvotes: 0

Ragesh Chakkadath
Ragesh Chakkadath

Reputation: 1531

Since you want to read a large file, reading it block by block is a better way.

ifstream wiki;
wiki.open("./wiki/velocity.txt");
const int buf_size = 1024;
char* wikiRead = 0;
int cnt = 1;
do
{
   wikiRead = realloc( wikiRead, bufsize*cnt );
   wiki.Read( wikiRead + (bufSize*(cnt-1)), buf_size ); //appends to reallocated memory
   cnt++;
}while( !wiki.eof())
wikiRead[(bufSize*(cnt-2)) + wiki.gcount() + 1] = '\0'; // null termination.
wiki.Close();
cout << wikiRead;
delete[] wikiRead;

Upvotes: 0

Potatoswatter
Potatoswatter

Reputation: 137810

The >> operator applied to a char * reads only one word. Moreover, you're reading into an uninitialized pointer, which is not valid. Usually std::string, not char *, is used for string processing in C++.

If you only want to print the file's contents, you can hook the file's buffer directly to std::cout:

int main() {
    std::ifstream wiki("./wiki/velocity.txt");
    std::cout << wiki.rdbuf() << '\n';
}

If you want to put the contents into an automatically-allocated string, use std::getline with the delimiter disabled.

int main() {
    std::ifstream wiki("./wiki/velocity.txt");
    std::string wiki_contents;
    getline( wiki, wiki_contents, '\0' /* do not stop at newline */ );

    std::cout << wiki_contents << '\n'; // do something with the string
}

Upvotes: 0

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361472

wiki >> wikiRead;

The default delimiter for stream is space, so when the stream encounters a space, it simply stops reading, that is why it reads only one word.

If you want the stream to read all words, the you've to use a loop as:

char* wikiRead = new char[1024]; //must allocate some memory!
while(wiki >> wikiRead)
{
   cout << wikiRead << endl;
}
wiki.close();
delete []wikiRead; //must deallocate the memory

This will print all the words in the file, each on a new line. Note if any of the word in the file is more than 1024 character long, then this program would invoke undefined behavior, and the program might crash. In that case, you've to allocate a bigger chunk of memory.

But why use char* in the first place? In C++, you've better choice: Use std::string.

#include<string>

std::string word;
while(wiki >> word)
{
   cout << word << endl;
}
wiki.close();

Its better now.

If you want to read line-by-line, instead of word-by-word, then use std::getline as:

std::string line;
while(std::getline(wiki, line))
{
   cout << line << endl;
}
wiki.close();

This will read a complete line, even if the line contains spaces between the words, and will print each line a newline.

Upvotes: 2

sarat
sarat

Reputation: 11130

I wonder why you ignored the compiler warning (most of the modern compiler warns you about using uninitialized variables). How about this?

    ifstream wiki;
    wiki.open("./wiki/velocity.txt");
    char wikiRead[255];
    wiki >> wikiRead;
    cout << wikiRead << endl;
    wiki.close();

Alternatively I'd suggest you to use string object with getline to get a single line of text.

string str;
getline(wiki, str);

Upvotes: 0

Nikki Locke
Nikki Locke

Reputation: 2941

You ask the stream to read the (binary) value of a pointer (probably 4 bytes, depending on your machine architecture), then you ask it to print the text pointed to by those 4 bytes!

Upvotes: 0

Related Questions