Create a directory if not present..

I created a 'Sudoku' program, that can load and save the game boards. I have it to look in the path of the game, and save into the sub-directory, called "SAVES", but if I give the program to someone, I don't want it to mess up if there isn't a "SAVES" directory. How can I check if the directory is there, then create it, if it isn't? Here is the Load function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
void Load_Game(int sudoku_board[][9], int start_board[][9])
{
	int i, j, sud_games, len, ch;
	string sud_file, File_Location = "";
	string rub(24,' '), border(78,'\xCD');
	string File_Name,Sudoku_Name;
	GetCurrentPath(CurrentPath);  // Gets path to executable
	i=0;
	while(CurrentPath[i] !=NULL)
	{
		File_Location = File_Location + CurrentPath[i];
		i++;
	};
	
	File_Location = File_Location + "\\Saves\\"; // Adds 'Saves' directory for search
			
	Box( 2,23,8,34,12,light_green,black,2,light_gray,dark_gray);
	BoxLineAcross(4,23,11,34);
	BoxLineAcross(4,23,15,34);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 48);
	gotoXY(28,20);
	cout << "\xB3 \xBA \xB3 \xB3 \xBA \xB3 \xB3 \xBA \xB3 \xB3 \xBA \xB3";
	for ( i=0;i<9;i++ )
	{
		gotoXY(31+(i*2),20);
		if ( sudoku_board[i][6] > 0)
			cout << sudoku_board[i][8];
		else
			cout << " ";
	}

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 160);
	 string dir = string(".");
    vector<string> files = vector<string>();
	getdir(File_Location,files);
    sud_games = 0;
    for (unsigned int i = 1;i < files.size();i++)
	{
        	len = files[i].length();
			sud_file = "";
			for ( j=0;j < len;j++)
			{
				if (files[i][j]!= '.')
					sud_file = sud_file+files[i][j];
				else
					break;
			}
			files[i-1] = sud_file;
			sud_games++;
	}
	sud_games--;
	gotoXY(30,9, "Load which file name");
	gotoXY(33,10, "into the grid?");
	gotoXY(28,16, "Use the Up and Down keys");
	gotoXY(27,17, "to select the desired file,");
	gotoXY(31,18, "then press 'Enter'.");
	i=1;
	
	gotoXY(32,13, files[i]);
	gotoXY(27,14,"\x1F");
	do
	{
		ch = _getch();
		switch(ch)
		{
		case ENTER:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 112);
			Sudoku_Name = files[i];
			gotoXY(1,0,border);
			len = (80-Sudoku_Name.length())/2;
			gotoXY(len-2,0,"\xB5 "+Sudoku_Name+" \xC6");

			break;
		case UP:  // Scrolls file names upward
			if(i-1 > 0)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 160);
				i--;
				if (i > 1)
					gotoXY(27,12,"\x1E");
				else
					gotoXY(27,12," ");
				gotoXY(27,14,"\x1F");

				gotoXY(32,13, rub);
				gotoXY(32,13, files[i]);
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 176);
				gotoXY(29,28,"Load an Existing Game");
			}
			else
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 176);
				gotoXY(29,28,"   Top of file list  ");
			}
			break; 
		
		case DOWN: // Scrolls file names down
			if(i+1 <= sud_games)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 160);
				i++;
				gotoXY(27,12,"\x1E");
				gotoXY(27,14," ");
				
				if (i < sud_games)
					gotoXY(27,14,"\x1F");
				
				gotoXY(32,13, rub);
				gotoXY(32,13, files[i]);
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 176);
				gotoXY(29,28,"Load an Existing Game");
			}
			else
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 176);
				gotoXY(29,28," Bottom of file list ");
			}
		}
		
	} while ( ch != ENTER);
	
	File_Name = File_Location + Sudoku_Name + ".sud";
	
	ifstream infile(File_Name.c_str());

		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 176);
		for (i=0;i<9;i++)
		{
			for ( j=0;j<9;j++)
			{
				infile >> sudoku_board[j][i];
				gotoXY((j*2)+31,(i*2)+6);
				if ( sudoku_board[j][i] > 0 )
					cout << sudoku_board[j][i];
			}
		}
		for (i=0;i<9;i++)
		{
			for ( j=0;j<9;j++)
			{
				infile >> start_board[j][i];
			}
		}
		infile.close();

	ReNew( sudoku_board ); // Clears the request, leaving the board
	Get_Numbers(sudoku_board, 0, 0 );
}
The WinAPI function you're looking for is CreateDirectory:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx

Don't bother checking to see if the directory already exists, just try to create it anyway. Worst-case scenario is that the directory already exists and the function just won't do anything.
@NGen

Thanks for this info, but I am unable to get it working. I'll just add in the note that the "Saves" directory must first be created whatever directory the game is installed to.
The WinAPI function should work, assuming you're on windows. Manipulating the file system is the job of the OS, so you have to invoke the OS commands to do so. Try calling GetLastError afterwards to see what, if anything, went wrong with the function.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
@ResidentBiscuit

I tried it again, with the same results. I try to compile and it fails with..

1>------ Build started: Project: Sudoku_Game, Configuration: Debug Win32 ------
1>Compiling...
1>Sudoku_Game.cpp
1>.\Sudoku_Game.cpp(886) : error C2664: 'CreateDirectory' : cannot convert parameter 1 from 'const char *' to 'LPCTSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>Sudoku_Game - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


The function, up to the code to create the directory, is..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Load_Game(int sudoku_board[][9], int start_board[][9])
{
	int i, j, sud_games, len, ch;
	string sud_file, File_Location = "";
	string rub(24,' '), border(78,'\xCD');
	string File_Name,Sudoku_Name;
	GetCurrentPath(CurrentPath);
	i=0;
	while(CurrentPath[i] !=NULL)
	{
		File_Location = File_Location + CurrentPath[i];
		i++;
	};
	File_Location = File_Location + "\\Testing\\";
	CreateDirectory(File_Location.c_str(), NULL);
// Rest of function.  Shown above in OP 


And lastly, the beginning of the #includes

1
2
3
4
5
#include <stdafx.h>
#include <stdio.h>
#include <dirent.h>
#include <direct.h> // for getcwd
#include <stdlib.h> // for MAX_PATH 


For the life of me, I can't figure WHY it doesn't create a directory.
The error tells you what to do,
either CreateDirectory(reinterpret_cast<LPCTSTR>(File_Location.c_str()),NULL);
or CreateDirectory((LPCTSTR)File_Location.c_str(), NULL);
Last edited on
@naraku9333

I changed the CreateDirectory() statement in my code to what you show, and yes, it compiles. BUT, the directory name it creates is..
睜楨整楮整就潄畣敭瑮屳楖畳污匠畴楤〲㠰停潲敪瑣屳畓潤畫䝟浡履畓潤畫䝟浡履慓敶屳촀췍췍췍췍췍췍췍췍﷽﷽
I tried both versions. One after the other. Yes, I am using a US computer, and no, I don't know that language. Very frustrating. Getting closer, but it seems, still a ways away.

EDIT: The quote I pasted looked like Chinese characters. After I hit 'Submit', they look like gibberish, not like the original.
Last edited on
I would check the value of the string. Or perhaps you need a wstring instead?
Thank you all, for your help in trying to fix this problem I'm having. I think I'll call it quits on trying to create the directory, and just tell the user to create one in the same directory as the game. It's a lot easier. If someone wants the code so they try getting it to work, please PM me, and I'll send it. I'm not worried about it being used as homework, since it's too advanced to be beginners code. A teacher would spot it immediately.
I wouldn't mind taking a look at it.
The error tells you what to do,
either CreateDirectory(reinterpret_cast<LPCTSTR>(File_Location.c_str()),NULL);
or CreateDirectory((LPCTSTR)File_Location.c_str(), NULL);
Nooooooooo

I really can't say this enough. Do not cast!

In this case the compiler is telling you that you have a type mismatch.
1
2
3
4
5
6
1
1>Compiling...
1>Sudoku_Game.cpp
1>.\Sudoku_Game.cpp(886) : error C2664: 'CreateDirectory' : cannot convert parameter 1 from 'const char *' to 'LPCTSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>Sudoku_Game - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
C++ is all about detecting your errors at compile time!

The problem is that you are using Unicode-16 strings, but you're trying to pass in an ASCII string.
1
2
3
4
5
6
void Load_Game(int sudoku_board[][9], int start_board[][9])
{
	TCHAR szPath[MAXPATH];
	GetCurrentPath(szPath);
	_tcsncpy(szPath, _T("\\Testing\\"), MAXPATH);
	CreateDirectory(szPath, NULL);
@kbw

Thanks, but that didn't work, either.

Compiler Error...
1>------ Build started: Project: Sudoku_Game, Configuration: Debug Win32 ------
1>Compiling...
1>Sudoku_Game.cpp
1>.\Sudoku_Game.cpp(927) : error C2664: 'wcsncpy' : cannot convert parameter 1 from 'char [260]' to 'wchar_t *'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>.\Sudoku_Game.cpp(928) : error C2664: 'CreateDirectory' : cannot convert parameter 1 from 'char [260]' to 'LPCTSTR'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>Sudoku_Game - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Code used..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Load_Game(int sudoku_board[][9], int start_board[][9])
{
	int i, j, sud_games, len, ch;
	string sud_file, File_Location = "";
	string rub(24,' '), border(78,'\xCD');
	string File_Name,Sudoku_Name;
	/* Old style
GetCurrentPath(CurrentPath);
	i=0;
	while(CurrentPath[i] !=NULL)
	{
		File_Location = File_Location + CurrentPath[i];
		i++;
	};
	File_Location = File_Location + "\\Saves\\";
	*/
	char szPath[_MAX_PATH]; // Changed MAXPATH to _MAX_PATH or I get "'1>.\Sudoku_Game.cpp(925) : error C2065: 'MAXPATH' : undeclared identifier' error
	GetCurrentPath(szPath);
	_tcsncpy(szPath, _T("\\Testing\\"), _MAX_PATH);
	CreateDirectory(szPath, NULL);


Maybe the GetCurrentPath(...) function is wrong.

Here is what I have..
1
2
3
4
void GetCurrentPath(char* buffer)
{
_getcwd(buffer, _MAX_PATH);
}


Very frustrating.
Last edited on
Sorry, I used your code without checking. This is what you ought to be using.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364934(v=vs.85).aspx

Try this:
1
2
3
4
5
6
7
8
void Load_Game(int sudoku_board[][9], int start_board[][9])
{
	const size_t nMaxPath = 512;	// large enough?
	TCHAR szPath[nMaxPath];
	GetCurrentDirectory(nMaxPath, szPath);

	_tcsncpy(szPath, _T("\\Testing\\"), nMaxPath);
	CreateDirectory(szPath, NULL);

Also, you may want to take a look at this.
http://www.cplusplus.com/forum/windows/78463/#msg422834
Last edited on
@kbw

I used your method, and the program compiled with just one warning.
1>------ Build started: Project: Sudoku_Game, Configuration: Debug Win32 ------
1>Compiling...
1>Sudoku_Game.cpp
1>.\Sudoku_Game.cpp(104) : warning C4996: 'wcsncpy': This function or variable may be unsafe. Consider using wcsncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        C:\Programn\Microsoft Visual Studio 9.0\VC\include\string.h(275) : see declaration of 'wcsncpy'
1>Linking...
1>Embedding manifest...
1>Sudoku_Game - 0 error(s), 1 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========


I ran the program, but no directory is created. I even moved it into the main function, so it would be created before I try using the Load file function, but got same result. I tried changing _tcsncpy to wcsncpy_s. It took away the warning and still compiles, but still no directory is created.
Hopefully, it doesn't make a difference, but I'm using MS Visual C++ 2008 Express.
... Time passes while I try new things ...

Okay, now it works. I made one small change to your code above. Now it's.
1
2
3
4
5
6
7
8
void Load_Game(int sudoku_board[][9], int start_board[][9])
{
	const size_t nMaxPath = 512;	// large enough?
	TCHAR szPath[nMaxPath];
	GetCurrentDirectory(nMaxPath, szPath);

	_tcsncpy(szPath, _T("Testing"), nMaxPath);
	CreateDirectory(szPath, NULL);


I took off the two pairs of slashes surrounding "Testing", and the directory was created.

Thank you both for all the help, and patience, with my problem. Now, I'll add to the load function, a check to see if there ARE files in there to be loaded, so it doesn't crash if it's empty.

I'll mark this thread as "Solved" !!!

Topic archived. No new replies allowed.