Reputation: 83
I'm a beginner to C++ and I'm having trouble reading blocks of data from an input file and displaying that data properly in an output file. The text inside the input file I need to use looks like this:
& Warehouse ÿÿÿÿ X¦a¤ Ãq¹B
The output should look something like this:
Id: (some integer)
Department: Warehouse
Hours: (some float)
Heres what I have so far:
#include<iostream>
#<include<fstream>
#include<string>
using namespace std;
struct employee {
int id;
char department[25];
float hours;
};
int main()
{
ifstream inputFile;
ofstream outputFile;
string inFilename, outFileName;
cout << "Please give me two file names" << endl;
getline(cin, inFileName);
getline(cin, outFileName);
inputFile.open(inFileName);
outputFile.open(outFileName);
if (inputFile.eof())
{
inputFile.close();
outputFile.close();
}
string buffer;
employee emp;
inputFile.read(reinterpret_cast<char*>(&emp), sizeof(emp));
while (!inputFile.eof())
{
outputFile << "Id:\t" << emp.id << endl;
outputFile << "Department:\t" << emp.department << endl;
outputFile << "Hours:\t" << emp.hours << endl;
inputFile.read(reinterpret_cast<char*>(&emp), sizeof(emp));
}
inputFile.close();
outputFile.close();
return 0;
}
My output looks like this:
Id: 538968358
Department: Warehouse ÿÿÿÿ X¦a¤ Ãq¹BÌÌÌÌÌÌÌÌ î
Hours: 92.7222
Why is it still outputting these strange characters on the department line? Im having a hard time understanding what exactly the read function is doing when I call it and I think this might be whats causing the issue. I've looked into what the read function does but I couldn't find anything that could explain what was happening in this context specifically with the reinterpret cast. I know it takes two parameters, the first one being "char*" but in this case we are using the reinterpret cast to take the characters and turn them into type employee defined by the structure. The second parameter is sizeof and thats supposed to indicate how many characters its reading from the file I think? If I knew exactly how the read() function was working in this context I could probably figure out why its outputting the strange characters.
Upvotes: 0
Views: 1410
Reputation: 84531
You are actually fairly close. Your primary stumbling block comes from failing to open inputFile
in binary mode (e.g. specifying mode
as ios::binary
). Your secondary issues have to do with validation. All input must be validated (especially user input). All file openings must be validated (and you should validate a close after a write. by checking if failbit
indicates a stream error following close. note this is only necessary after a write)
Putting those pieces together (and leaving the check of failbit
after close of outputFile
to you), it looks like you intended something similar to the following:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
struct employee {
int id;
char department[25];
float hours;
};
int main()
{
ifstream inputFile;
ofstream outputFile;
string inFilename, outFilename, buffer;
struct employee emp;
cout << "Please give me two file names" << endl;
/* validate all input succeeds */
if (!getline (cin, inFilename)) {
cerr << "error: invalid input for input file.\n";
return 1;
}
if (!getline (cin, outFilename)) {
cerr << "error: invalid input for output file.\n";
return 1;
}
/* open file in binary mode 'ios::binary' */
inputFile.open (inFilename, ios::binary);
/* valdiate all files open for reading/writing */
if (!inputFile.is_open()) {
perror (("error opening: " + inFilename).c_str());
return 1;
}
outputFile.open (outFilename);
if (!outputFile.is_open()) {
perror (("error opening: " + outFilename).c_str());
return 1;
}
/* while each read succeeds, write to output file */
while (inputFile.read (reinterpret_cast<char*>(&emp), sizeof(emp)))
{
outputFile << "Id:\t" << emp.id << endl;
outputFile << "Department:\t" << emp.department << endl;
outputFile << "Hours:\t" << emp.hours << endl;
}
inputFile.close(); /* close files */
outputFile.close();
return 0;
}
Example output data1.info
$ ./bin/read_binary_info
Please give me two file names
dat/data1.info
dat/data1.txt
$ cat dat/data1.txt
Id: 579
Department: Warehouse
Hours: 95.9083
Id: 23
Department: Admin
Hours: 33.7954
Id: 901
Department: Operations
Hours: 99.5081
Id: 193
Department: Admin
Hours: 2.15763
...
Id: 707
Department: Maintenance
Hours: 63.801
Id: 110
Department: Sales
Hours: 1.22974
Example outoput data3.info
$ ./bin/read_binary_info
Please give me two file names
dat/data3.info
dat/data3.txt
$ cat dat/data3.txt
Id: 294
Department: Warehouse
Hours: 92.7222
Look things over and let me know if you have further questions.
Upvotes: 1
Reputation: 776
In c++ the char[] must include a \0 charater for indicate the end of the text. otherwise unspected resuts because qye data of the array is not initialized to any values and contains arbitrary characters. When you try to output the char[25] departament, if after 'warehouse' dont have a \0 char then output all 25 chars.
Upvotes: 0