views:

248

answers:

2

I have a text file named num.txt who's only contents is the line 123. Then I have the following:

void alt_reader(ifstream &file, char* line){
    file.read(line, 3);
    cout << "First Time: " << line << endl;
}

int main() {
    ifstream inFile;
    int num;
    inFile.open("num.txt");
    alt_reader(inFile, (char*)&num);
    cout << "Second Time: " << num << endl;
}

The output is:

First Time: 123
Second Time: 3355185

Can you help me figure out how to get an fstream that is read in a function still assign the variable in main? I'm doing this because alt_reader really has a lot more to it, but this is the part I'm stuck on. Thanks a lot for the help.

UPDATE: Using Bill Oneal's comments, I've written

void alt_reader(ifstream &file, stringstream &str, int n){
    char buffer[n+1];
    file.read(buffer, n);
    buffer[n] = 0;
    str << buffer;
    cout << "First Time: " << buffer << endl; //First Time: 123
}

int main() {
    ifstream inFile;
    stringstream strm;
    int num;
    inFile.open("num.txt");
    alt_reader(inFile, strm, 3);
    cout << "Second Time: " << num << endl; //Second Time: 123
}

Thanks. Any critiques with what's there now?

+2  A: 

The first time you printed the variable, you printed it as a char *, printing treating the file as a text file (And you're lucky you didn't crash). The second time you printed it, you reinterpreted it as an int, making the representation completely different.

Whenever you cast pointers from one type to another type you are usually invoking undefined behavior. Since char has no standard relation to int, you have it here.

EDIT: To answer your comment question:

#include <sstream>

void foo(std::stream &str) {
 str << "42\n";
};

int main() {
 int aNumber;
 std::stringstream aStringStream;
 foo(aStringStream); //Pass our stream to the funciton. It contains
    //"42\n" when the funciton returns.
 aStringStream >> aNumber; //aNumber == 42
 aNumber += 10; //aNumber == 52;
 std::cout << aNumber; //Print "52"
}
Billy ONeal
Thanks. Any advice on passing an fstream and getting the read value out of the function (without a return statement?)?
vgm64
@vgm64: Sure. See edit.
Billy ONeal
@Bill ONeal: I just added an attempt to expand my code with your technique. It works. What do you think of it?
vgm64
Well -- you can do it that way, but in general it's better to return type safe data. I'm assuming you have a really good reason for having the function write to the string directly here. Oh .. this is a buffer overrun: `char buffer[n]; buffer[n] = 0;`. The maximum index of an array with length n is n-1.Also: I'm surprised that even compiles because array declarations need to be constant.
Billy ONeal
@Bill ONeal: Thanks, fixed the index. I've never quite figured out when array declarations need to be constant. Ever since I moved to C++ it's been like they all use some form of malloc to do the declaration and they don't need to be constant. But I'm terrible at C++!
vgm64
@Bill ONeal: To clarify the need for this, I'm reading a binary file that is something like: `int header_length; infile.read( (char*) if(byteswap_bool) EndianByteSwap(header_length);` and I'm just trying to condense the read and if calls into something cleaner.
vgm64
@vgm64: Sounds like a case for the Abstract Factory pattern, where the factory is initialized at start after an endian detection. Then you don't have constant checking for endianness all the time -- you can use the most obvious operations for each individual action and get the behavior you want.
Billy ONeal
@Bill ONeal: Something like that would be ideal, but I'm afraid it goes a bit over my head as far as how to implement "initializing the factory" after endian detection. Could you link something instructional so as to allow me to learn more without bothering you further? =)
vgm64
@vgm64: http://en.wikipedia.org/wiki/Abstract_factory_pattern
Billy ONeal
+2  A: 

You have at least two problems here.

In main():

  1. You should be passing a string buffer into alt_reader, instead you're passing an int.
  2. You seem to want to read the string '123' but want an int to have the value 123.

You could do:

void alt_reader(ifstream &file, char* line){
    file.read(line, 3);
    line[3]=0;
    cout << "First Time: " << line << endl;
}

int main() {
    ifstream inFile;
    inFile.open("num.txt");

    char buffer[128];
    alt_reader(inFile, buffer);

    int num=atoi(buffer);
    cout << "Second Time: " << num << endl;

    return 0;
}

Note that I've added line[3]=0; to alt_reader and atoi does the conversion from string (a scii) to int.

quamrana
@quamrana: That would work perfectly for the situation I described, but the number I'll be reading isn't necessarily an int, and the string stream below will happily go into an int or double. Even so, thanks a lot.
vgm64