Path, Filename & ofstream

May 17, 2008 at 5:20am
Ok well before starting, I'd like to say that I'm not a pro and that I would really appreciate it if I could get precise and well explained answers. (I posted on some other forums and all they did was giving me one or two technics name that I had no idea what they were).


So I have this simple program that reads information from a .txt, does stuff with does numbers, and exports the results to .txt


To INPUT exe, we have to drop the .txt on the .exe

1
2
3
4
5
6
7
8
9
10
..........
int main(int argc, char **argv)

	{
		//Variables			
			ifstream read;
			
		//Opens the numbers txt
			read.open (argv[1]);  //Open ifstream
..........


To export, it "should" export to same folder as the exe.

1
2
3
4
5
6
7
..........
	write.open ("results.txt");  //open txt file to write to

	xport(); //prints the table in the txt file

	write.close(); //close the result file
..........



So now, my two problems are:

1. When I use this main parameter to get drag&drop .txt file, the ofstream doesn't work like before... It won't export if I don't put a PRECISE path. Therefore, when I leave it like it is now, it does nothing.

2. I want to be able to see the filename of the .txt, and if possible the path of the .txt too. When I print argv[1], it gives me both at the same time, and I'm not quite sure how I could CUT it in two.


Thanks in advance for the help
~Ph0X
May 17, 2008 at 3:15pm
Drag and drop will always execute the program in the caller's directory, not the directory of your exe. Meaning: every relative path in your program is now relative to the caller's current directory, which could be anywhere.

You can use a few simple std::string methods to split things up:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::string ExtractDirectory( const std::string& path )
  {
  return path.substr( 0, path.find_last_of( '\\' ) +1 );
  }

std::string ExtractFilename( const std::string& path )
  {
  return path.substr( path.find_last_of( '\\' ) +1 );
  }

std::string ChangeExtension( const std::string& path, const std::string& ext )
  {
  std::string filename = ExtractFilename( path );
  return ExtractDirectory( path ) +filename.substr( 0, filename.find_last_of( '.' ) ) +ext;
  }


You can use them easily:
1
2
3
4
5
6
7
8
9
10
11
12
int main( int argc, char **argv )
  {
  if (argc < 2) return 0;

  ifstream read;
  read.open( argv[1] );
  ...

  ofstream write;
  write.open( ExtractDirectory( argv[0] ) +"results.txt" );
  ...
  }


An example for changing a file extension:
1
2
3
4
5
6
7
8
  // Remove the extension
  cout << ChangeExtension( "example.txt", "" ) << endl;

  // Change an extension
  cout << ChangeExtension( "example.txt", ".doc" ) << endl;

  // Add an extension
  cout << ChangeExtension( "example.txt.", ".asc" ) << endl;


Hope this helps.
May 17, 2008 at 5:21pm
Wow, thanks alot! it worked almost perfectly. The filename worked great, and the directory output worked great too.

Only one problem

When I go to do
write.open( ExtractDirectory( argv[0] ) +"results.txt" );

I get

1
2
3
4
5
6
7
8
9
Compiling...
SizeCalculation.cpp
c:\....\sizecalculation.cpp(140) : error C2664: 'void std::basic_ofstream<_Elem,_Traits>::open(const wchar_t *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'std::string' to 'const wchar_t *'
        with
        [
            _Elem=char,
            _Traits=std::char_traits
        ]
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called


Any ideas?

Thanks again for the three functions up there! very useful.
May 17, 2008 at 11:53pm
My bad. I always forget that the stupid STL streams don't take std::string as filename arguments. It should be:
 
write.open( string( ExtractDirectory( argv[0] ) +"results.txt" ).c_str() );

Pain in the nose, isn't it?
Topic archived. No new replies allowed.