Thread: files/arrays

  1. #1
    Registered User
    Join Date
    Nov 2001
    Posts
    255

    files/arrays

    ok im doing this for school and he says i need to read a file with an array and load that numbers of the file using a function so this is what i have so far:

    it seems to bomb at the thought of istream being placed in a function and passed through??? but as far as i know variable types can always be passed through at least thats my understanding. i dont see why it would be bombing on it it also doesnt seem to like if i put file_data[99] when i call it in main with the print_array function so i just leave it blank. why does it do that? doesnt make sense to me anyway.

    Code:
    #include "stdafx.h"
    #include <fstream>
    #include <string>
    
    #using <mscorlib.dll>
    
    using namespace std;
    using namespace System;
    
    
    
    int load_array(ifstream in);
    void print_array(int file_data[99],int count);
    
    int main()
    {
    	int count = 0;
    	int file_data[99];
    	ifstream in;
    	in.open("prog1.dat");
    
    	while(!in.eof())
    	{
    		file_data[count] = load_array(in); //THE LINE IT ERRORS ON
    		count++;
    		
    	}
    	in.close();
    	print_array(file_data,count);
    
      
    	return 0;
    }
    
    
    int load_array(ifstream in)
    {
    	int dummy;
    	in >> dummy;
    	return dummy;
    }
    
    void print_array(int file_data[99],int count)
    {
    	for(int i = 0;i <= count;i++)
    		cout << file_data[i];
    }
    c:\skool\Program 1\Program 1\Program 1.cpp(27): error C2664: 'load_array' : cannot convert parameter 1 from 'std::ifstream' to 'std::ifstream'


    oh and yea some of those headers are C++.net headers i know but im using that compiler and since hes running it im not making portable code just using the .net framework version. though in this class he said if you know standard C++ because we used to teach that and some students still know it if you know it you can use it and i much rather use that over C++.net anyday or year. plus hes using standard C++ file handling anyway cause .net sucks with it lol and yea it doesnt seem to like me to remove those headers.
    hooch

  2. #2
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    file streams must be passed by reference -- never by value. So change the prototype and function like this
    Code:
    int load_array(ifstream& in);
    why is load_array() a fiunction anyway? All it is doing is reading one int from the file. you can do that more efficiently inline
    Code:
    in >> file_data[count];
    Last edited by Ancient Dragon; 09-18-2005 at 05:07 PM.

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    simple because the teacher wants a function and he gives the grade so good enough for me but yes i know lol

    and why do ifstreams have to referenced? why cant they just pass normally??? any reason for such madness? i dont really understand references that well anyway but still the whole idea that it should be able to pass normally would make more sense too me?

    oh and why does the output unless i change that for to i < count-1 display excess 0's at the bottom??? it displays 2 extra 0's?
    hooch

  4. #4
    CS Author and Instructor
    Join Date
    Sep 2002
    Posts
    511
    You pass file parameters to functions by reference.

    let's see from one of my C++ reference books:

    "The internal state of file stream objects change with most every operation. They should be always passed to functions by reference to ensure internal consistency."

    This is just by general convention- there really is nothing to say you can't pass files by value.

    Typically you should follow conventions.

    JC.
    Mr. C: Author and Instructor

  5. #5
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    well it was erroring so that usually means syntax not convention so thats why i asked although it works just seems kind of strange but eh whatever lol

    but why did those 0's appear at the bottom logic error i presume? if so i dont understand the random guessing that put in there lol?
    hooch

  6. #6
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    since you have to have a function, then you might want to change it to do what the function name implies -- load the entire array at one time. To do that, just add parameters to pass the array and number of array elements
    Code:
    int load_array(ifstream& in, int array[], int arraysize)
    {
        int i = 0;
       while( !in.eof() && i < arraysize)
           in >> array[i++];
       return i;
    }
    
    int main()
    {
    	int count = 0;
    	int file_data[99];
    	ifstream in("prog1.dat");
    	count = load_array(in, file_data, 99);
    	in.close();
    	print_array(file_data,count);
    
    
    	return 0;
    }
    Last edited by Ancient Dragon; 09-18-2005 at 08:36 PM.

  7. #7
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    oh so you can do that thats what i originally wanted to do but didnt think it would work

    i didnt think you could read the array in a function and have it still get read since seems like one time i tried that and it errored on me oh well either that i mthinking of basic or something im not sure lol

    but thanks
    hooch

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> This is just by general convention- there really is nothing to say you can't pass files by value.

    You cannot pass file streams by value. The copy constructor and copy assignment operator are disabled so that there will be a compiler error if you do. The reason is that when you pass by value a copy of the object is made, meaning there will be two separate file stream instances referencing the same file. This doesn't usually make sense. Passing by reference allows only one stream instance to access the file, while multiple references use that stream.

    In addition, class variables are usually passed by reference to avoid sometimes expensive and unnecessary copies. So for non-built-in types you generally want to pass by const reference instead of by value anyway. In this case it cannot be const because the filestream changs, but the copy is still avoided.

    BTW, Ancient Dragon's example might add an extra entry into the error. You shouldn't use eof() to control the loop. Using while (i < arraysize && in >> array[i++]); might be better.

  9. #9
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    Quote Originally Posted by Daved
    BTW, Ancient Dragon's example might add an extra entry into the error. You shouldn't use eof() to control the loop. Using while (i < arraysize && in >> array[i++]); might be better.

    but doesn't in >> array[i++] return a reference to iostream in instead of the number of bytes read? At least that is the way I understood it, but could be wrong.

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Ancient Dragon
    but doesn't in >> array[i++] return a reference to iostream in instead of the number of bytes read? At least that is the way I understood it, but could be wrong.
    http://parashift.com/c++-faq-lite/in....html#faq-15.4
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    hmm thats a useful looking site ill save that thanks

    and whats bad about eof() anyway cause thats what teacher was teaching and it seems to work ok at least that hasnt given me trouble.

    and that ifstream references having to be used to pass in actually makes sense dont want two copies of something going into a file since thats what i gather would happen?
    hooch

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    eof() itself isn't bad, and on second look at that code it might be ok because it won't save any value if the read fails.

    Often, users will have code like this:
    Code:
    while (!fin.eof())
    {
        fin >> value; // Read in value
        some_func(value); // Use value
    }
    This is bad because if there is any whitespace after the last value (most input files have a newline at the end), then eof() will still return false after the last value is read in. The operator>> will be called again and will fail because there is no more data (except some whitespace that is skipped). Unfortunately the return value of operator>> is ignored in that code, and so the value is used even though it wasn't set. Usually that means that whatever was in there from the last time will be used again, so often the last piece of data is duplicated.

    Your teacher has either fallen into this common trap, or purposefully dances around it to avoid the errors that can be easily be made. The FAQ linked by Dave_Sinkula shows the better way (using the return value to identify success or failure, including an eof condition).

  13. #13
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    oh well hes probably doing it that way cause this is only a second semester class and a logic class at that so hes probably just still trying to get our heads thinking in the right direction and coming from someone who has had the misery/joy of self teaching having to think out logic in big dosses is painful so probably just trying to keep it simple at first.

    hes bald so i doubt hes fallen into traps lol


    so basically eof can be bad because if something has whitespace it takes that as eof when its not really the eof? so just mannually put a file >> file[i++] and see if it returns anything anything at all that way catching the whole line? which if so then how does it know when to read another input line?

    cause eof reads another line at a space so when would while(file >> data[i++]) know when to read another line of input??? i read that link but didnt completely get though sorta kinda? eof causes a of by 1 error cause of that input space thing but didnt quite catch onto how the cin way knows a new line of input?
    hooch

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I will use the more common example first, since your example is different than usual in that it only reads in the value and doesn't use it in any other way. Start with this:
    Code:
    while (!fin.eof())
    {
        fin >> value; // Read in value
        some_func(value); // Use value
    }
    Assume an input file looking like this (with <newline> representing a newline in the file):
    Code:
    1<newline>
    2<newline>
    3<newline>
    The code above will check for eof(), which is false so it will execute the body of the loop. In the body, it will read 1 into value and then use that in the some_func function. At that point the file pointer is after the 1 and before the first <newline>.

    Next it will check eof(), which is still false, then attempt to read in another value. Since operator>> skips over whitespace, it will skip the <newline> on the first line and read in the 2. The some_func function will then be called with 2. The file pointer will be pointing at the <newline> on the second line.

    The loop will repeat again - 3 will be read in and used, and the file pointer will be pointing at the <newline> on the third line.

    At this point, there are no more valid values in the input file. However, eof() will still return false because there is a newline in the file that hasn't been read. It doesn't know that you want to skip that. So the body of the loop will be run again. This time operator>> will be called but will fail because it will skip the <newline> and be unable to find an int to put into the variable. It will go into a fail state and leave the value variable alone. The value variable will probably still have 3 in it from the last time through the loop, so 3 will be passed to the some_func function again. This is not correct.

    Finally, the eof() function will return true because the last <newline> was read in and the end of the file was reached.

    Compare that to this code:
    Code:
    while (fin >> value)
    {
      some_func(value);
    }
    Now, remember that the return value of operator>> can be converted to true or false based on whether the read succeeded or not. So the first time through, 1 will be read into the value variable and operator>> will return true because it did not fail. The body of the loop will be executed, meaning some_func will be called with value equal to 1. The file pointer will be pointing to the <newline> on the first line just as before.

    The second number will be read in as well and used by some_func. The the third number will be read in the same way. After the third number is read, the file pointer will be at the <newline> on the last line. Then the next time through the control of the while loop, the operator>> will attempt to read a number. That will fail because after the newline is read in, there is no more data, and so fin will go into a fail state. This time, though, it will return false because it failed, and the while loop will not execute any more, so the some_func won't use any bad values.


    In your case it is ok because if operator>> fails, nothing will be read into the file_data array. As long as you don't try to use the value you just read in, you will be fine. It would be better and more conistent to just switch to this other way, though.

  15. #15
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    ok so basically eof is testing to see if its the end of the file and if it is you still end up with whatever it last had for the last variable creating the off by one? because eof has to test which has to return a value?

    but if you just test the line of input just like you would asking the user using the cin/ifstream then it directly tests that line of input so theres no way it can return a value because if nothing was inputted it cant give a value for it?

    so in short test using cin vs eof as its more practical all around.
    hooch

Popular pages Recent additions subscribe to a feed