How can I convert a char array to a string in C++? - c++

I have a char array called firstFileStream[50], which is being written to from an infile using fstream.
I want to convert this char array into a string called firstFileAsString. If I write string firstFileAsString = firstFileStream; it only writes the first word within the array and stops at the first space, or empty character. If I write firstFileAsString(firstFileStream) I get the same output.
How do I write the whole char array, so all words within it, to a string?
Here is the code to read in and write:
string firstInputFile = "inputText1.txt";
char firstFileStream[50];
ifstream openFileStream;
openFileStream.open(firstInputFile);
if (strlen(firstFileStream) == 0) { // If the array is empty
cout << "First File Stream: " << endl;
while (openFileStream.good()) { // While we haven't reached the end of the file
openFileStream >> firstFileStream;
}
string firstFileAsString = firstFileStream;
}

My problem, as zdan pointed out, is I was only reading the first word of the file, so instead I've used istreambuf_iterator<char> to assign the content directly to the string rather than the character array first. This can then be broken down into a character array, rather than the other way around.

openFileStream >> firstFileStream;
reads only one word from the file.
A simple example of reading the whole file (at least up to the buffering capacity) looks like this:
openFileStream.read(firstFileStream, sizeof(firstFileStream) - 1);
// sizeof(firstFileStream) - 1 so we have space for the string terminator
int bytesread;
if (openFileStream.eof()) // read whole file
{
bytesread = openFileStream.gcount(); // read whatever gcount returns
}
else if (openFileStream) // no error. stopped reading before buffer overflow or end of file
{
bytesread = sizeof(firstFileStream) - 1; //read full buffer
}
else // file read error
{
// handle file error here. Maybe gcount, maybe return.
}
firstFileStream[bytesread] = '\0'; // null terminate string

Related

Converting C function to C++ language

Since this is my first encounter with the C programming language, it's not clear to me how I'm going to convert a piece of code to C++. I know that this code can be used in C ++ but I want to work exclusively on the syntax of the C++ language.
Here is my code:
FILE *f;
char name[10],surname[10],j[10];
f=fopen("Marks.txt","r");
fscanf(f,"%d",&n);
I want to open the file using:
ifstream input;
input.open("Marks.txt");
But then I don't know what to use instead of the fscanf function because I can no longer use FILE *f;
Like this:
int main()
{
// Let the constructor handle opening the file.
std::ifstream input("Marks.txt");
int n = 0;
std::string s;
double d = 0;
// Read an int, followed by a string, followed by a double.
if (input >> n >> s >> d)
{
std::cout << "Success!\n";
}
else
{
std::cout << "Failure!\n";
}
// The destruction of 'input' will close the file.
}
Here's the C++ way to do it, though you technically can still use that C code.
#include <ifstream>
int main() {
std::string str;
int i;
double d;
char c_str[10];
std::ifstream input;
input.open("Marks.txt");
input >> str; // reads a word of text into str
input >> i; // assuming there is a valid integer after the first line, reads it into i
input >> d; // assuming there is a valid double after that, reads it into d
// reads up to 9 characters + a '\0', stopping if it reaches a period
input.get(c_str, 10-1, '.');
// etc.
}
First to do is make a std::fstream object then open the file of your choice, you can do any lines (in sequence) of the following:
// Option 1
std::fstream input; // create the object
input.open("Marks.txt", ios::in); // since this is a `std::fstream` object, you'll need to specify `ios::in` for input operations
// Option 2
std::ifstream input; // create the object, this time dedicated to input
input.open("Marks.txt"); // no need to specify `ios::in`
// Option 3
std::fstream input("Marks.txt", ios::in); // you can directly open the file using the constructor, but specify `ios::in`
// Option 4
std::ifstream input("Marks.txt"); // directly opening the file using the constructor with the object dedicated to input
Next, you'll use operator>> or std::getline() to get input from the stream
// first declare the variables
std::string str1 = ""; // use std::string in C++ instead C-style strings (char[])
int ing1 = 0;
// Option 1
input >> str1; // this parses the contents of the file into str1, until the space
/*
Suppose "Marks.txt" has this inside it:
Hello World
The first content of the file until a space is "Hello", this string parsed into str1
*/
// Option 2
ing1 = input.get() // this parses only one character then turns it into an integer (destination type) into ing1
/*
Suppose "Marks.txt" has this inside it:
1234567890
ing1 will bear the value 1.
however, like std::iostream, this does not convert the character to it's integral value (ASCII, automatically) thus when:
abcdefghij
ing1 will have the value 0, since 'a' is not an integer
*/
// Option 3
input.getline(str1, 6); // this will parse into str1 six (6) characters, including spaces (not sure with control characters)
/*
Suppose "Marks.txt" has this inside it:
StackOverflow
"StackO" will be parsed into str1
*/
Note: this operations differ when stream is opened in binary mode (ios::binary) and be careful with std::getline() this may overload the buffer (especially when specified with std::numeric_limits<std::streamsize>::max())
EDIT: IMPORTANT close the stream after using.
// some operations here
// file is no longer needed -> close it
input.close();

How to read just before EOF from a file and put it into a string? [duplicate]

This question already has answers here:
How do I read an entire file into a std::string in C++?
(23 answers)
Closed 3 years ago.
My function reads a file and puts it into a string in order for me to process it. I need to read just before EOF, obviously. The problem is that the EOF character is also put inside the string and I can't find a way to bypass it, since it leds other parts of the program to fail. I link the function below.
string name_to_open, ret = string();
ifstream in;
getline(cin, name_to_open);
in.open(name_to_open.c_str());
if (!in.is_open()) {
cout << "Error." << endl;
return string();
}
else {
ret += in.get();
while (in.good()) {
ret += in.get();
};
};
in.close();
return ret;
The function reads fine until the end of the file, then appends EOF and \0. How can I solve the problem? Does the EOF character work fine in controls? I also tried to put a line ret[ret.size() - 1] = '\0'; at the end of the cycle, but this doesn't seem to work either.
ret += in.get(); appends the character read from the tile to the string whether the value read was good or not. You need to 1) read, 2) test that the read is valid and the value read is safe to use, 3) use the value read. Currently your code reads, uses, and then tests whether or not the value read was safe to use.
Possible solution:
int temp;
while ((temp = in.get()) != EOF) // read and test. Enter if not EOF
{
ret += static_cast<char>(temp); // add the character
};
Note: get returns an int, not a char. This is to be able to insert out-of-band codes such as EOF without colliding with an existing valid character. Immediately treating the return value as a char could result in bugs because a special code may be mishandled.
Note: there are many better ways to read an entire file into a string: How do I read an entire file into a std::string in C++?

Unable to parse final word in text file using peek()

I'm attempting to write a lexer and parser but I'm having trouble getting the final variable in a text file due to in_file.tellg() equaling -1. My program only works if I add a space character after the variable, otherwise I get a compiler error. I want to mention that I'm able to get every other variable in the text file but the last one. I believe the cause of the problem is in_file.peek()!=EOF setting in_file.tellg() to -1.
My program is something like this:
ifstream in(file_name);
char c;
in >> noskipws;
while(in >> c ){
if(is_letter_part_of_variable(c)) {
int start_pos = in.tellg(),
end_pos,
length;
while(is_letter_part_of_variable(c) && in.peek()!=EOF ) {
in>>c;
}
end_pos = in.tellg(); // This becomes -1 for some reason
length = end_pos - start_pos; // Should be 7
// Reset file pointer to original position to chomp word.
in.clear();
in.seekg(start_pos-1, in.beg);
// The word 'message' should go in here.
char *identifier = new char[length];
in.read(identifier, length);
identifier[length] = '\0';
}
}
example.text
message = "Hello, World"
print message
I tried removing peek()!= EOF which gives me an eternal loop. I tried !in_file.eof() and that also makes tellg() equal to -1. What can I do to fix/enhance this code?
I believe the cause of the problem is in_file.peek()!=EOF setting in_file.tellg() to -1.
Close. peek attempts to read a character and returns EOF if it reads past the end of the stream. Reading past the end of a stream sets the stream's fail bit. tellg returns -1 if the fail bit is set.
Simple Solution
clear the fail bit before calling tellg.
Better solution
Use std::string.
std::string identifier;
while(in>>c && is_letter_part_of_variable(c)) {
identifier += c;
}
All of the messing around with peek, seekg, tellg and the dreaded new vanish.

How to signal EOF on a file the program opens

How would I signal an EOF when reading in a file in C++? I'm writing a direct coded scanner, as a part of a compiler design, that reads in a file and splits it up into tokens for a language.
I am to read in the whole program, strip out the comments, and compress the whitespace. Then put the resulting program char by char into a buffer with max size of 1024 chars. So when we empty we will refill the buffer or what not.
To open the file I have this written:
// Open source file.
source_file.open (filename);
if (source_file.fail()) {
// Failed to open source file.
cerr << "Can't open source file " << *filename << endl;
buffer_fatal_error();
To fill the buffer, I am wanting to use a while loop and iterate like
int i = 0;
// Iterate through the whole file
while(source_file.at(i) != EOF)
{
// If not a tab or newline add to buffer
if (source_file.at(i) != "\n" || source_file.at(i) != "\t")
{
bufferList.add(source_file.at(i));
}
i++;
}
Would there be a way to signal EOF like that for the file that I am opening?
This is more or less a general outline for what to do. I will need to figure out how to refill the buffer once I am empty or to use dual buffering. I also need to figure out how to strip out a comment which would begin with #. For instance # This is a comment. My scanner would see # and remove everything after that until it gets the the next newline char.
Try this:
char c;
std::vector<char> buffer(1024);
while (source_file.get(c))
{
if ((c != '\n') || (c != '\t'))
{
buffer.push_back(c);
}
}
The standard method for reading data is to test for the result of the read operation in a while loop.
For block reading, you could do something like this:
char buffer[1024];
while (source_file.read(buffer, sizeof(buffer))
{
// Process the buffer here
}
You should also use std::istream::gcount() to get the number of characters read from the file, as it could be less than the buffer size.

getline seems to not working correctly

Please tell me what am I doing wrong here. What I want to do is this:
1.Having txt file with four numbers and each of this numbers has 15 digits:
std::ifstream file("numbers.txt",std::ios::binary);
I'm trying to read those numbers into my array:
char num[4][15];
And what I'm thinking I'm doing is: for as long as you don't reach end of files write every line (max 15 chars, ending at '\n') into num[lines]. But this somewhat doesn't work. Firstly it reads correctly only first number, rest is just "" (empty string) and secondly file.eof() doesn't seems to work correctly either. In txt file which I'm presenting below this code I reached lines equal 156. What's going on?
for (unsigned lines = 0; !file.eof(); ++lines)
{
file.getline(num[lines],15,'\n');
}
So the whole "routine" looks like this:
int main()
{
std::ifstream file("numbers.txt",std::ios::binary);
char numbers[4][15];
for (unsigned lines = 0; !file.eof(); ++lines)
{
file.getline(numbers[lines],15,'\n');// sizeof(numbers[0])
}
}
This is contents of my txt file:
111111111111111
222222222222222
333333333333333
444444444444444
P.S.
I'm using VS2010 sp1
Do not use the eof() function! The canonical way to read lines is:
while( getline( cin, line ) ) {
// do something with line
}
file.getline() extracts 14 characters, filling in num[0][0] .. num[0][13]. Then it stores a '\0' in num[0][14] and sets the failbit on file because that's what it does when the buffer is full but terminating character not reached.
Further attempts to call file.getline() do nothing because failbit is set.
Tests for !file.eof() return true because the eofbit is not set.
Edit: to give a working example, best is to use strings, of course, but to fill in your char array, you could do this:
#include <iostream>
#include <fstream>
int main()
{
std::ifstream file("numbers.txt"); // not binary!
char numbers[4][16]={}; // 16 to fit 15 chars and the '\0'
for (unsigned lines = 0;
lines < 4 && file.getline(numbers[lines], 16);
++lines)
{
std::cout << "numbers[" << lines << "] = " << numbers[lines] << '\n';
}
}
tested on Visual Studio 2010 SP1
According to ifstream doc, reading stops either after n-1 characters are read or delim sign is found : first read would take then only 14 bytes.
It reads bytes : '1' (the character) is 0x41 : your buffer would be filled with 0x41 instead of 1 as you seem to expect, last character will be 0 (end of c-string)
Side note, your code doesn't check that lines doesn't go beyond your array.
Using getline supposes you're expecting text and you open the file in binary mode : seems wrong to me.
It looks like the '\n' in the end of the first like is not being considered, and remaining in the buffer. So in the next getline() it gets read.
Try adding a file.get() after each getline().
If one file.get() does not work, try two, because under the Windows default file encoding the line ends with '\n\r\' (or '\r\n', I never know :)
Change it to the following:
#include <cstring>
int main()
{
//no need to use std::ios_base::binary since it's ASCII data
std::ifstream file("numbers.txt");
//allocate one more position in array for the NULL terminator
char numbers[4][16];
//you only have 4 lines, so don't use EOF since that will cause an extra read
//which will then cause and extra loop, causing undefined behavior
for (unsigned lines = 0; lines < 4; ++lines)
{
//copy into your buffer that also includes space for a terminating null
//placing in if-statement checks for the failbit of ifstream
if (!file.getline(numbers[lines], 16,'\n'))
{
//make sure to place a terminating NULL in empty string
//since the read failed
numbers[lines][0] = '\0';
}
}
}