0

I am attempting to convert text from a text document to a char array. To begin I tried to implement a dynamic array. However, for some reason when I attempt to save each char from the text into the new array it returns a bunch of equals signs. Down below is what I have:

Say for example the text said something like "Make this a char array".

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    char x;
    int y = 0;
    ifstream file;
    file.open("text.txt");
    while (file >> x)
        y++;

    char *phrase = NULL;
    phrase = new char[y];

    for (int i = 0; file >> x; i++)
    {
        phrase[i] = x;
    }
    for (int i = 0; i < y; i++)
    {
        cout << phrase[i];
    }
}

It will end up outputting: "=================="

I did research on this issue but I couldn't find anything that clears it up.

O'Neil
  • 3,638
  • 3
  • 13
  • 28
Mike
  • 51
  • 5
  • 1
    You need to go back to the beginning of the file. You can't just keep reading the file after you have read everything to the end. – Galik Jun 11 '18 at 23:07
  • 2
    It would be easier to use a `std::vector` which will automatically resize its internal array as needed. – NO_NAME Jun 11 '18 at 23:12
  • 2
    This doesn't address the question, but don't do pointless initialization followed by modifying objects. Instead of `ifstream file; file.open("text.txt");` use `ifstream file("text.txt");`. Similarly, instead of `char *phrase = NULL; phrase = new char[y];` use `char *phrase = new char[y];`. Your code block doesn't go this far, but I'll bet there's `file.close()` further down; that's not needed, either: the destructor will close the file. – Pete Becker Jun 11 '18 at 23:36
  • @einpoklum - I also helped mess it up, if that `iostream` was a cut-and-paste from mine. In mine it's a spell-check-induced error. I took the liberty of fixing that in your answer. – Pete Becker Jun 11 '18 at 23:42
  • (checking...) Oh yeah. Right. Wll, all's well that ends well. – einpoklum Jun 11 '18 at 23:43
  • I think douplicate of https://stackoverflow.com/questions/116038/what-is-the-best-way-to-read-an-entire-file-into-a-stdstring-in-c – M.M Jun 12 '18 at 00:14

3 Answers3

4

You seem to be "measuring" the length of the file by repeatedly reading individual characters from it. You don't need to do that - just determine the size before opening the file:

#include <filesystem>
#include <fstream>  

int main() {
    auto file_name { "text.txt" };
    auto size = std::filesystem::file_size(file_name);
    std::ifstream file(file_name);
    // etc. etc.

See the documentation for the file_size() function. It's in C++17; if you're using an earlier version of the language, try >experimental/filesystem> with C++14, or otherwise the boost::filesystem library with any version of C++.

... but actually, you don't need to do that at all!

You can just read the entire file using plain vanilla C++ standard library facilities:

#include <sstream>
#include <iostream>
#include <fstream>

int main() {
    std::ifstream file("text.txt");
    if (not file) { /* handle error */ }
    std::stringstream sstr;
    sstr << file.rdbuf(); // magically read all of the file!
    auto entire_file_contents = sstr.str();
    const char* arr = entire_file_contents.c_str();
    // Now do whatever you like with the char array arr
}

See also this: What is the best way to read an entire file into a std::string in C++?

By the way, it's kind of tricky to determine the size of a file given an std::ifstream without sort-of reading the whole file, see this answer.

einpoklum
  • 86,754
  • 39
  • 223
  • 453
2

Here's another approach:

#include <fstream>
#include <iterator>
#include <algorithm>

int main() {
    std::ifstream file("text.txt");
    std::vector<char> text;
    std::copy(std::istream_iterator<char>(file),
        std::istream_iterator<char>(),
        std::back_inserter(text));
    // now text holds the contents of the file
    // if you really need a char array, you can use text.data()
}

Note that the code does not test whether the file was opened successfully. I/O operations on streams are no-ops when the stream is in an error state. Yes, you can check if you prefer, but it's not strictly necessary.

Pete Becker
  • 69,019
  • 6
  • 64
  • 147
  • +1, but I suggest you include some token error handling code anyway, as otherwise you're surreptitiously legitimizing failure to check errors generally. – einpoklum Jun 11 '18 at 23:52
  • Also, how fast is this? Are you sure it doesn't end up copying one character at a time? – einpoklum Jun 12 '18 at 12:05
1

Here's one way to do it:

std::ifstream file("text.txt", std::ios::binary | std::ios::ate);
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);

std::vector<char> buffer(size);
if (file.read(buffer.data(), size))
{
    //...
}
Andreas DM
  • 9,654
  • 6
  • 31
  • 58
  • This has different behaviour to the original intent of opening the file in text mode, on some operating systems – M.M Jun 12 '18 at 00:08