Thread: Problems with fstreams.

  1. #1
    Registered User
    Join Date
    Jun 2002
    Posts
    13

    Problems with fstreams.

    In my program, I am reading in a file ("source" - cannot be overwritten) and copying it to another file ("target") by reading and writing one line at a time. I am manipulating the data found in target within the lines, so I need a temp file ("temp_file") to hold the data while I manipulate it and write it back to target. I can copy source to target just fine, but I can't seem to copy target to temp_file. Do I need to reset the EOF flag of target? I am calling target.seekg( 0 ) and temp_file.seekp( 0 ), but I still end up with a blank temp_file, even though target fully has the original data. I am using the same method to copy source to target that I am using to copy target to temp_file. I can paste my entire code if it would help, but I think that might be excessive. Any ideas? I have been making sure to use seekg( 0 ) and seekp( 0 ), almost in excess in some cases.

    Thanks in advance!

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Since you probably originally opened target for output only, target.seekg() may not work.

    You can either close the file (target.close()) and reopen for input, or when you originally opened it, open for input and output ( target.open(filename,ios::in | ios::out) ).

    One of these two should work.

  3. #3
    Registered User
    Join Date
    Jun 2002
    Posts
    13

    Unhappy

    I opened all the files for both input and output, so that's not the problem. Well here goes...

    Code:
    #include <iostream>
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    void getNewHeader( fstream & );
    int getNumLinesHeader( fstream & );
    void getNewColumnTitles( fstream &, const int & );
    bool isNotInt( const char & );
    void transferData( fstream &, fstream & );
    void displayHeader( fstream &, int & );
    void displayData( fstream &, const int & );
    void arrangeData( fstream &, const int &, char [], int & );
    int menuChoice();
    int getNumColumns( fstream & );
    void eraseColumn( fstream &, fstream &, int & );
    void switchColumns( fstream &, fstream & );
    void quit();
    void getPastHeader( fstream & );
    void copyFile( fstream &, fstream &, char [] );
    
    
    int main() {
    
    	fstream source;
    	char sourcename[81];
    	do {
    		cout << "Enter data source file: ";
    
    		cin >> sourcename;
    		source.open( sourcename, ios::in );
    		if( !source )
    			cout << "Invalid file name: File does not exist." << endl;
    	} while( !source );
    
    	fstream target;  // stream to read from target file
    
    	bool done = false;
    	char targetname[81];
    	while( !done ) {
    		cout << "Enter data target file: ";
    		cin >> targetname;
    		if( sourcename == targetname ) {
    			cout << "Invalid file name: File already exists or " <<
    				"source file entered as target file." << endl;
    		}
    		else {
    			target.open( targetname, ios::in | ios::out | ios::nocreate );
    			if( target.is_open() ) {
    				cout << "File exists, are you sure you want " <<
    					"to overwrite the file (y/n)? ";
    				char choice;
    				cin >> choice;
    				if( choice == 'n' ) {
    					cout << "File will not be overwritten," <<
    						"please enter a new file name." <<
    						endl;
    					target.close();
    				}
    				else if( choice == 'y' ) {
    					cout << "File will be overwritten." <<
    						endl;
    					done = true;
    				}
    			}
    			else
    				done = true;
    		}
    	}
    	target.open( targetname, ios::in | ios::out | ios::noreplace );
    
    	// display the header and set the number of lines of the header
    	int header_lines = 0;
    	displayHeader( source, header_lines );
    
    	// display the data
    	displayData( source, header_lines );
    
    	getNewHeader( target );
    
    	int num_columns = getNumColumns( source );
    
    	getNewColumnTitles( target, num_columns );
    	transferData( source, target );
    
    	arrangeData( source, header_lines, targetname, num_columns );
    
    	source.close();
    	target.close();
    
    	return 0;
    
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    void displayHeader( fstream &source, int &header_lines ) {
    	header_lines = getNumLinesHeader( source );
    
    	cout << endl;
    	// display the header
    	if( header_lines > 0 ) {
    		cout << "The original header:" << endl;
    	for( int i = 0; i < header_lines; i++ ) {
    			string curr_line = "";
    		getline( source, curr_line );
    			cout << curr_line << endl;
    		}
    	}
    	else
    	cout << "Original header not displayed." << endl;
    	cout << endl;
    }
    
    void displayData( fstream &source, const int &header_lines ) {
    	cout << "How many lines of data would you like to view? ";
    	int data_lines;
    	cin >> data_lines;
    	cout << endl;
    	
    	if( data_lines > 0 ) {
    		string curr_line;
    		getline( source, curr_line );
    		cout << "The original data:" << endl;
    		for( int i = header_lines; i < header_lines + data_lines; i++ ) {
    			getline( source, curr_line );
    			cout << curr_line << endl;
    		}
    	}
    	else
    	cout << "Original data not displayed." << endl;
    	cout << endl;
    }
    
    int getNumLinesHeader( fstream &source ) {
    	source.seekg( 0 );
    	int lines = 0;
    	bool done = false;
    
    	while( !done ) {
    	char c;
    		source >> c;
    		if( isNotInt( c ) ) {
    			string temp_line;
    			getline( source, temp_line );
    				lines++;
    		}
    		else {
    			source.putback( c );
    			done = true;
    		}
    	}
    
    	source.seekg( 0 );
    	return lines;
    }
    
    bool isNotInt( const char &c ) {
    	int i = static_cast<int>( c );
    	if( c != '-' && c != '.' && ( i < 48 || i > 57 ) )
    		return true;
    	return false;
    }
    
    void getNewHeader( fstream &target ) {
    	char choice = '!';
    	while( choice != 'y' && choice != 'n' ) {
    		cout << "Would you like to include a header in the file (y/n)? ";
    		cin >> choice;
    		if( choice != 'y' && choice != 'n' )
    			cout << "Please enter either y or n." << endl;
    	}
    
    	if( choice == 'y' ) {
    		cout << "When you are done entering text, simply enter a blank" <<
    			" line." << endl;
    		string header_line = "!";
    		getline( cin, header_line );
    		bool done = false;
    
    		while( !done ) {
    			cout << "> ";
    			getline( cin, header_line );
    			if( header_line != "%" )
    				target << header_line << endl;
    			else {
    				target << endl;
    				done = true;
    			}
    		}
    	}
    }
    
    void getNewColumnTitles( fstream &target, const int &num_columns ) {
    	cout << endl;
    	cout << "There are " << num_columns << " columns of data." << endl;
    	cout << "Please enter new column titles..." << endl;
    	string new_header;
    	for( int i = 1; i < num_columns; i++ ) {
    		cout << "Column #" << i << ": ";
    		cin >> new_header;
    		target << new_header << "	|	";
    	}
    	cout << "Column #" << num_columns << ": ";
    	cin >> new_header;
    	target << new_header << endl;
    }
    
    int getNumColumns( fstream &source ) {
    	getPastHeader( source );
    	string line;
    	// capture a line of data
    	getline( source, line );
    	int i = 0, columns = 1;
    
    	bool last_space = false;
    	while( i < static_cast<int>( line.length() ) ) {
    		if( line[i] == ' ' ) {
    			if( last_space )
    				line.erase( i, 1 );
    			else {
    				i++;
    				last_space = true;
    			}
    		}
    		else {
    			last_space = false;
    			i++;
    		}
    	}
    	if( line[0] == ' ' )
    		line.erase( 0, 1 );
    	if( line[ line.length()-1 ] == ' ' )
    		line.erase( line.length()-1, 1 );
    
    	// count columns
    	for( i = 0; i < static_cast<int>( line.length() ); i++ )
    		if( line[i] == ' ' )
    			columns++;
    
    	return columns;
    }
    
    void getPastHeader( fstream &source ) {
    	source.seekg( 0 );
    
    	bool done = false;
    	int curr_line = 0, header_lines = getNumLinesHeader( source );	
    
    	string line;
    	while( !done ) {
    		getline( source, line );
    		curr_line++;
    		if( curr_line == header_lines || !source )
    			done = true;
    	}
    	getline( source, line );
    }
    
    void transferData( fstream &source, fstream &target ) {
    cout << "data transfer";
    	source.seekg( 0 );
    	source.seekp( 0 );
    	target.seekg( 0 );
    	target.seekp( 0 );
    	while( !source.eof() ) {
    cout << "...";
    		string line;
    		getline( source, line );
    		target << line << endl;
    	}
    cout << endl;
    	source.seekg( 0 );
    	source.seekp( 0 );
    	target.seekg( 0 );
    	target.seekp( 0 );
    }
    
    ///////////////////////////////////////////////////////////////////////////
    
    void arrangeData( fstream &target, const int &header_lines,
    				  char targetname[], int &num_columns ) {
    
    	int choice = -1;
    	while( choice != 3 ) {
    		choice = menuChoice();
    		if( choice != 3 ) {
    			fstream temp_file( "temp.dat", ios::in | ios::out );
    
    
    
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    ///////// PROBLEM IS IN THE NEXT FUNCTION /////////
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    
    			copyFile( target, temp_file, targetname );
    
    
    			if( choice == 1 )
    				eraseColumn( target, temp_file, num_columns );
    			else if( choice == 2 )
    				switchColumns( target, temp_file );
    		}
    		else
    			cout << "Exiting program..." << endl << endl;
    	}
    }
    
    void copyFile( fstream &target, fstream &temp_file, char targetname[] ) {
    	transferData( target, temp_file );
    	target.close();
    	target.open( targetname, ios::in | ios::out | ios::trunc );
    }
    
    int menuChoice() {
    	cout << endl << "Menu" << endl;
    	cout << "----------------------" << endl;
    	cout << "1. Erase a column." << endl;
    	cout << "2. Switch two columns." << endl;
    	cout << "3. Quit." << endl;
    	cout << "----------------------" << endl;
    
    	int choice = 0;
    	while( choice < 1 || choice > 3 ) {
    		cout << "> ";
    		cin >> choice;
    		if( choice < 1 || choice > 3 )
    			cout << "Please enter a choice 1-3." << endl;
    	}
    
    	return choice;
    }
    
    void eraseColumn( fstream &target, fstream &temp_file, int &num_columns ) {
    cout << "***ERASE COLUMN()(***" << endl;
    	bool input_ok = false;
    	int erase_column;
    
    	while( !input_ok ) {
    		cout << "Please enter the column you would like to erase," <<
    			" or 0 to exit: ";
    		cin >> erase_column;
    		if( erase_column < 0 || erase_column > num_columns )
    			cout << "Please enter a valid column." << endl;
    		else
    			input_ok = true;
    	}
    
    	if( erase_column != 0 ) {
    
    cout << "***GET PAST TARGET HEADER***"<<endl;
    		string line;
    		for( int i = 0; i < getNumLinesHeader( temp_file ); i++ ) {
    cout << "(loop)" << endl;
    			getline( temp_file, line );
    			target << line << endl;
    		}
    
    cout << "***enter big while***" << endl;
    		while( !temp_file.eof() ) {
    			getline( temp_file, line );
    			int i = 0, cur_col = 0;
    			bool last_space = true;
    			while( i < static_cast<int>( line.length() ) ) {
    cout << "***in loop***" << endl;
    				if( last_space && line[i] != ' ' ) {
    					last_space = false;
    					cur_col++;
    				}
    				else if( !last_space && line[i] == ' ' )
    					last_space = true;
    				if( cur_col != erase_column ) {
    					char c = line[i];
    					target << c;
    				}
    				i++;
    			}
    	
    			target << endl;
    		}
    
    		num_columns--;
    	}
    }

  4. #4
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Code:
    >void transferData( fstream &source, fstream &target ) {
    >cout << "data transfer";
    >	source.seekg( 0 );
    >	source.seekp( 0 );
    >	target.seekg( 0 );
    >	target.seekp( 0 );
    >	while( !source.eof() ) {
    >cout << "...";
    >		string line;
    >		getline( source, line );
    >		target << line << endl;
    >	}
    >cout << endl;
    // Add source.clear() here
    	source.clear();
    >	source.seekg( 0 );
    >	source.seekp( 0 );
    >	target.seekg( 0 );
    >	target.seekp( 0 );
    >}

  5. #5
    Registered User
    Join Date
    Jun 2002
    Posts
    13
    Thanks, what does clearing an ifstream do?

  6. #6
    Registered User
    Join Date
    Jun 2002
    Posts
    13
    Also, are there excessive seekg's I can remove? Thanks again! It works!

  7. #7
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Clearing an ifstream clears any flags which have been set. In this case the eof flag (source.eof()) had been set when you called the function earlier, so when you called the function again, the eof flag was still set). If an error occurs during a read, it also sets a flag. Some examples of flags are: isopen(), good(), bad(), fail(), eof().

  8. #8
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    You should certainly be able to remove the seekg()'s at the end of transferData():
    Code:
    void transferData( fstream &source, fstream &target ) {
    cout << "data transfer";
    	source.seekg( 0 );
    	source.seekp( 0 );
    	target.seekg( 0 );
    	target.seekp( 0 );
    	while( !source.eof() ) {
    cout << "...";
    		string line;
    		getline( source, line );
    		target << line << endl;
    	}
    cout << endl;
    	source.clear();
    This might even work:
    Code:
    void transferData( fstream &source, fstream &target ) {
    cout << "data transfer";
    	source.seekg( 0 );
    	target.seekp( 0 );
    	while( !source.eof() ) {
    cout << "...";
    		string line;
    		getline( source, line );
    		target << line << endl;
    	}
    cout << endl;
    	source.clear();

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  2. C Pointers Problems
    By mhelal in forum C Programming
    Replies: 8
    Last Post: 01-10-2007, 06:35 AM
  3. String Manipulation problems -_-
    By Astra in forum C Programming
    Replies: 5
    Last Post: 12-13-2006, 05:48 PM
  4. contest problems on my site
    By DavidP in forum Contests Board
    Replies: 4
    Last Post: 01-10-2004, 09:19 PM
  5. DJGPP problems
    By stormswift in forum C Programming
    Replies: 2
    Last Post: 02-26-2002, 04:35 PM