Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » How to delete a file outside of main( ) & How to change mouse speed

Credits go to Steve Terry for helping out!
This thread is locked; no one can reply to it. rss feed Print
How to delete a file outside of main( ) & How to change mouse speed
Seraph6
Member #7,517
July 2006
avatar

I'm almost done with my first original game, but I have two little problems that I'm hooked up on.

1. In trying to delete a file, the remove() function isn't working in an if() or switch() statement or outside of main(). I want to be able to do this outside of main(), in its own function, but I've searched and searched and I can't find a single example program of that, even in C programming books. The way I'm using it is: "remove("mb1.txt");" Apparently it is returning a fail on the delete, but I have no clue as to why. If I put that same line of code in main() with no if() or switch() statements, it'll delete it. But that's useless.

EDIT: Found a solution to my second question. Thanks allegro.cc

Steve Terry
Member #1,989
March 2002
avatar

I only see one question???

Anyway can you show me your code that fails.

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Christopher Bludau
Member #5,401
January 2005

He removed it, because he solved it.
But it´s still in the title.

Seraph6
Member #7,517
July 2006
avatar

I call the function from another function in the program similar to this:

for(n=0; n<4; n++)
if((cursor->x >= sframe[n]->x + 120) && (cursor->y > sframe[n]->y) &&
   (cursor->x < sframe[n]->x + 200) && (cursor->y < sframe[n]->y + 125) &&
   (mouse_b & 1))
    trash_file(n);

And the actual function trash_file(int x) is like so:

1void trash_file(x)
2{
3 switch(x)
4 {
5 case 0:
6 remove("mb1.txt");
7 break;
8 case 1:
9 remove("mb2.txt");
10 break;
11 case 2:
12 remove("mb3.txt");
13 break;
14 case 3:
15 remove("mb4.txt");
16 break;
17 }
18}

I had it set up before so that it would return an error and exit the program if the deletion didn't work. But I guess I deleted that code.
I also tried without the switch() statement, and just called trash_file(int x) to see what would happen, and it still failed.

Steve Terry
Member #1,989
March 2002
avatar

Your code looks ok, not sure what would cause it to fail. How exactly is it failing? Is it not compiling or is the code just not doing anything? Try "./mb1.txt".

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Seraph6
Member #7,517
July 2006
avatar

The code just isn't doing anything. The program will compile and run without any errors or warnings. I also have another action occur when the user clicks that is grouped with the trash_file(int x), and it works. So the program is definitely reading the click. But when I tested remove() for a fail with...

if(remove("mb1.txt")) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("ERROR: File deletion unsuccessful", allegro_error);
}

...it confirmed that the remove was failing. Also, I just look every time to see if the file is there, and it remains there... just as stubborn as ever.

The only time I got it to work is when I typed "remove("mb1.txt");" right in the main() function with no if loops or switch statements. This, however, is of course useless.

I tried your suggestion of "./mb1.txt" and that didn't work either. I greatly appreciate the effort though.

Oh, and if it helps. The function that calls trash_file(int x) and the function trash_file(int x) itself are in two different .c files.

BAF
Member #2,981
December 2002
avatar

Are the files open?

Seraph6
Member #7,517
July 2006
avatar

When they are deleted, no. I think I tried it with them open once (which doesn't sound right, but I tried it anyway), and I got an error.

Kitty Cat
Member #2,815
October 2002
avatar

What does it say when you use this:
allegro_message("ERROR: File deletion unsuccessful: %s", strerror(errno));? And you really should compile with warnings enabled (and not ignore them).

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

Seraph6
Member #7,517
July 2006
avatar

Thanks, that was really handy. I wasn't aware of strerror(errno).
The response was: "ERROR: File deletion unsuccessful: Permission denied"

However, as useful as that was, I'm not sure why that is the case. The file is not read only or hidden, and it shouldn't be open.

Billybob
Member #3,136
January 2003

How is the file created? What Operating System?
You need to have the necessary permissions to delete the file. Under Windows you just need to be owner, in most cases, unless you've got a crazy configuration. Under Linux, I'm not sure what permission flag it is (I'm not too studied on permissions in Linux). I suppose the write permission would do it?

Seraph6
Member #7,517
July 2006
avatar

The file was created with the games save_file(int x) function.

1void save_file(x)
2{
3 FILE* mb_save;
4
5 int tx, ty, tw, th, tr, tg, tb; //temporary numbers, mainly for float to int conversion
6
7 switch(x)
8 {
9 case 0:
10 mb_save = fopen("mb1.txt", "w+");
11
12 //save information to file
13 fprintf(mb_save, "c%-5d", r);
14 fprintf(mb_save, ":%-5d", g);
15 fprintf(mb_save, ":%-5d", b);
16 fprintf(mb_save, "\n");
17
18 for(n=0; n<MAX_SHAPES; n++)
19 if(n != 994) //for some reason, this shape doesn't get saved right, so ignore it
20 {
21 tx = shape[n]->x;
22 ty = shape[n]->y;
23 tw = shape[n]->width;
24 th = shape[n]->height;
25 tr = shape[n]->red;
26 tg = shape[n]->green;
27 tb = shape[n]->blue;
28
29 fprintf(mb_save, "s%-5d", n);
30 fprintf(mb_save, ":%-5d", shape[n]->alive);
31 fprintf(mb_save, ":%-5d", tx);
32 fprintf(mb_save, ":%-5d", ty);
33 fprintf(mb_save, ":%-5d", shape[n]->width);
34 fprintf(mb_save, ":%-5d", shape[n]->height);
35 fprintf(mb_save, ":%-5d", shape[n]->type);
36 fprintf(mb_save, ":%-5d", tr);
37 fprintf(mb_save, ":%-5d", tg);
38 fprintf(mb_save, ":%-5d", tb);
39 fprintf(mb_save, "\n");
40 }
41 break;
42 case 1:
43 mb_save = fopen("mb2.txt", "w+");
44 break;
45 case 2:
46 mb_save = fopen("mb3.txt", "w+");
47 break;
48 case 3:
49 mb_save = fopen("mb4.txt", "w+");
50 break;
51 }
52 
53 fclose(mb_save);
54}

My operating system is WinXP and I am the owner of this PC, not to mention the sole user.

juvinious
Member #5,145
October 2004
avatar

how are you running the app? Your CWD is probably not being set to the one containing the files. Open up the shell, go to the directory and run it and see if you have the same results.

__________________________________________
Paintown

Seraph6
Member #7,517
July 2006
avatar

I'm sorry, but that comment just went over my head.
If you're talking about command-line compiling, I'm just using Dev-c++ to compile.
I don't know what a CWD is and I'm not sure what you mean by open up the shell.

Johan Halmén
Member #1,550
September 2001

Both your code examples start like
void trash_file(x)
when it should be like
void trash_file(int x)

That's strange. Sure you haven't typed in the code in your post, but pasted? You should get compiler errors from that. OTOH x might be a macro that compiles fine but screws everything.

Before remove(), try to examin the state of the file and write it on the screen. Is the file open, is it protected, whatever. I bet it is open.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Jakub Wasilewski
Member #3,653
June 2003
avatar

I agree with Johan, "Permission denied" under Windows is usually only caused by the file still being open, either by the same or another process. Double-check that all handles to the file are closed.

---------------------------
[ ChristmasHack! | My games ] :::: One CSS to style them all, One Javascript to script them, / One HTML to bring them all and in the browser bind them / In the Land of Fantasy where Standards mean something.

Audric
Member #907
January 2001

Indeed, in Windows "Permission denied" means "the OS won't let you" :)

You can try Sysinternals' "Process Explorer" to check for open files: This program is very much like a task manager on steroids.

James Stanley
Member #7,275
May 2006
avatar

I think the explanation is that you are in the wrong directory. Does Dev-C++ run your programs from its bin directory or from the directory you loaded the project from?

EDIT:
You could try typing the full path to the file:

remove("C:/home/you/mb1.txt");

Or whatever Windows uses.

Seraph6
Member #7,517
July 2006
avatar

[quote Johan]it should be like
void trash_file(int x)</quote>

You're correct. However, when I changed that, it didn't fix the error.

[quote Johan]Sure you haven't typed in the code in your post, but pasted?</quote>

I copied and pasted my code right in. Except for the very first for loop near the top of this post. That was just an example. The actual code is like this.

#SelectExpand
1void update_po_menu() 2{ 3 if(cursor->x < (menu->x + 300)) 4 { 5 scroll_disabled = 1; 6 menu->state = 1; 7 for(n=0; n<4; n++) sframe[n]->alive = 1; //draw save frames 8 9 if(menu->x < 0) 10 { 11 menu->x += menu->speed; 12 if(menu->x > 0) menu->x = 0; //don't push the menu out too far 13 } 14 else //operations available once the pop-out menu is fully extended 15 { 16 //play/credits view switcher 17 if((cursor->x > 50) && (cursor->y > 20) && (cursor->x < 125) && (cursor->y < 70) && 18 (mouse_b & 1) && (view_ct == button_delay)) 19 { 20 credits = 0; 21 } 22 else if((cursor->x >= 125) && (cursor->y > 20) && (cursor->x < 200) && (cursor->y < 70) && 23 (mouse_b & 1) && (view_ct == button_delay)) 24 { 25 credits = 1; 26 } 27 else 28 { 29 view_ct++; 30 31 if(view_ct > button_delay) view_ct = button_delay; 32 } 33 34 //color pickers 35 if(cursor->y > 650) 36 { 37 //if cursor is over red color slider and left-mouse button is held 38 if((cursor->x >= 55) && (cursor->y > 656) && (cursor->x <= 210) && (cursor->y < 682) && (mouse_b & 1)) 39 { 40 r = .68 * cursor->x + 100; 41 if(r < 140) r = 140; 42 else if(r > 240) r = 240; 43 } 44 //if cursor is over green color slider and left-mouse button is held 45 else if((cursor->x >= 55) && (cursor->y > 687) && (cursor->x <= 210) && (cursor->y < 713) && (mouse_b & 1)) 46 { 47 g = .68 * cursor->x + 100; 48 if(g < 140) g = 140; 49 else if(g > 240) g = 240; 50 } 51 //if cursor is over red color slider and left-mouse button is held 52 else if((cursor->x >= 55) && (cursor->y > 718) && (cursor->x <= 210) && (cursor->y < 744) && (mouse_b & 1)) 53 { 54 b = .68 * cursor->x + 100; 55 if(b < 140) b = 140; 56 else if(b > 240) b = 240; 57 } 58 } 59 60 //save frames 61 for(n=0; n<4; n++) 62 { 63 //if cursor is over save frame... 64 if((cursor->x > sframe[n]->x) && (cursor->y > sframe[n]->y) && 65 (cursor->x < sframe[n]->x + 200) && (cursor->y < sframe[n]->y + 125)) 66 { 67 if(save_check(n) == 0) //if no save file, make save option 68 { 69 sframe[n]->red = 150; 70 sframe[n]->green = 255; 71 sframe[n]->blue = 150; 72 73 sframe[n]->type = 1; 74 75 if(mouse_b & 1) 76 { 77 save_file(n); 78 79 sframe[n]->red = 250; 80 sframe[n]->green = 255; 81 sframe[n]->blue = 250; 82 } 83 } 84 else //if there is a save file, make save/load/delete options 85 { 86 sframe[n]->type = 2; 87 88 //if cursor is over save icon 89 if((cursor->x > sframe[n]->x) && (cursor->y > sframe[n]->y) && 90 (cursor->x < sframe[n]->x + 65) && (cursor->y < sframe[n]->y + 125)) 91 { 92 sframe[n]->red = 150; 93 sframe[n]->green = 255; 94 sframe[n]->blue = 150; 95 96 if(mouse_b & 1) 97 { 98 save_file(n); 99 100 sframe[n]->red = 250; 101 sframe[n]->green = 255; 102 sframe[n]->blue = 250; 103 } 104 } 105 //if cursor is over load icon 106 else if((cursor->x >= sframe[n]->x + 65) && (cursor->y > sframe[n]->y) && 107 (cursor->x < sframe[n]->x + 120) && (cursor->y < sframe[n]->y + 125)) 108 { 109 sframe[n]->red = 150; 110 sframe[n]->green = 150; 111 sframe[n]->blue = 255; 112 } 113 //if cursor is over delete icon 114 else if((cursor->x >= sframe[n]->x + 120) && (cursor->y > sframe[n]->y) && 115 (cursor->x < sframe[n]->x + 200) && (cursor->y < sframe[n]->y + 125)) 116 { 117 sframe[n]->red = 255; 118 sframe[n]->green = 150; 119 sframe[n]->blue = 150; 120 121 if(mouse_b & 1) 122 { 123 trash_file(n); 124 125 sframe[n]->red = 255; 126 sframe[n]->green = 250; 127 sframe[n]->blue = 250; 128 } 129 } 130 } 131 } 132 //otherwise get color back to normal 133 else if((sframe[n]->red < 255) || (sframe[n]->green < 255) || (sframe[n]->blue < 255)) 134 { 135 sframe[n]->type = 0; 136 137 if(sframe[n]->red < 255) sframe[n]->red++; 138 if(sframe[n]->green < 255) sframe[n]->green++; 139 if(sframe[n]->blue < 255) sframe[n]->blue++; 140 } 141 } 142 } 143 } 144 else 145 { 146 scroll_disabled = head->state; 147 menu->state = 0; 148 for(n=0; n<4; n++) sframe[n]->alive = 0; //don't draw save frames 149 150 if(menu->x > -250) 151 { 152 menu->x -= menu->speed; 153 if(menu->x < -250) menu->x = -250; //don't push the menu in too far 154 for(n=0; n<4; n++) sframe[n]->alive = 1; //draw save frames 155 } 156 } 157}

I just figured it would be a lot of code to go through.

[quote Johan]Before remove(), try to examin the state of the file and write it on the screen. Is the file open, is it protected, whatever. I bet it is open.</quote>

Capital idea! However, file handling in C is new to me, and I wasn't really well versed with it in C++ to begin with. So I'm not sure how to do that, but I am currently googling it.

[quote Jakub]"Permission denied" under Windows is usually only caused by the file still being open, either by the same or another process. Double-check that all handles to the file are closed.</quote>

Yup, that sounds like the case. However, every function that handles a file starts with FILE* mb_save; and ends with fclose(mb_save); And it's only three functions, so it's not easy to miss one.

[quote Audric]You can try Sysinternals' "Process Explorer" to check for open files</quote>

Thanks, I will look into that.

[quote James]I think the explanation is that you are in the wrong directory. Does Dev-C++ run your programs from its bin directory or from the directory you loaded the project from?</quote>

I do believe it runs programs from the directory the project was loaded from. Also, the fact that it can be deleted in main() leads me to believe this as well.

[quote James]You could try typing the full path to the file</quote>

No good, the error remains the same. You don't think that the file being on a partitioned drive would affect it do you? I mean, this works in main(), so I assume that's not the problem.

Richard Phipps
Member #1,632
November 2001
avatar

Are you sure that no other program has the file or directory open?

Seraph6
Member #7,517
July 2006
avatar

I'm gonna throw this up in case anyone really wants to check my file handling.
Here's the only file that does any file handling on the saves.

1////////////////////////////////////////////////////////////////////////////////
2//Corey Gardner
3//Music Box.exe
4//save.c
5//7/20/2006
6////////////////////////////////////////////////////////////////////////////////
7 
8void load_file(int);
9void trash_file(int);
10int save_check(int);
11void save_file(int);
12 
13void load_file(int x)
14{
15 FILE* mb_save;
16
17 switch(x)
18 {
19 case 0:
20 mb_save = fopen("mb1.txt", "r+");
21 break;
22 case 1:
23 remove("mb2.txt");
24 break;
25 case 2:
26 remove("mb3.txt");
27 break;
28 case 3:
29 remove("mb4.txt");
30 break;
31 }
32
33 fclose(mb_save);
34}
35 
36void trash_file(int x)
37{
38 switch(x)
39 {
40 case 0:
41 remove("mb1.txt");
42 /*if(remove("mb1.txt"))
43 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
44 allegro_message("ERROR: File deletion unsuccessful: %s", strerror(errno));*/
45 break;
46 case 1:
47 remove("mb2.txt");
48 break;
49 case 2:
50 remove("mb3.txt");
51 break;
52 case 3:
53 remove("mb4.txt");
54 break;
55 }
56}
57 
58int save_check(int x)
59{
60 FILE* mb_save;
61
62 switch(x)
63 {
64 case 0:
65 mb_save = fopen("mb1.txt", "r+");
66 if(mb_save == NULL) return 0;
67 else return 1;
68 break;
69 case 1:
70 mb_save = fopen("mb2.txt", "r+");
71 if(mb_save == NULL) return 0;
72 else return 1;
73 break;
74 case 2:
75 mb_save = fopen("mb3.txt", "r+");
76 if(mb_save == NULL) return 0;
77 else return 1;
78 break;
79 case 3:
80 mb_save = fopen("mb4.txt", "r+");
81 if(mb_save == NULL) return 0;
82 else return 1;
83 break;
84 }
85
86 fclose(mb_save);
87}
88 
89void save_file(int x)
90{
91 FILE* mb_save;
92
93 int tx, ty, tw, th, tr, tg, tb; //temporary numbers, mainly for float to int conversion
94
95 switch(x)
96 {
97 case 0:
98 mb_save = fopen("mb1.txt", "w+");
99
100 //save information to file
101 fprintf(mb_save, "c%-5d", r);
102 fprintf(mb_save, ":%-5d", g);
103 fprintf(mb_save, ":%-5d", b);
104 fprintf(mb_save, "\n");
105
106 for(n=0; n<MAX_SHAPES; n++)
107 if(n != 994) //for some reason, this shape doesn't get saved right, so ignore it
108 {
109 tx = shape[n]->x;
110 ty = shape[n]->y;
111 tw = shape[n]->width;
112 th = shape[n]->height;
113 tr = shape[n]->red;
114 tg = shape[n]->green;
115 tb = shape[n]->blue;
116
117 fprintf(mb_save, "s%-5d", n);
118 fprintf(mb_save, ":%-5d", shape[n]->alive);
119 fprintf(mb_save, ":%-5d", tx);
120 fprintf(mb_save, ":%-5d", ty);
121 fprintf(mb_save, ":%-5d", shape[n]->width);
122 fprintf(mb_save, ":%-5d", shape[n]->height);
123 fprintf(mb_save, ":%-5d", shape[n]->type);
124 fprintf(mb_save, ":%-5d", tr);
125 fprintf(mb_save, ":%-5d", tg);
126 fprintf(mb_save, ":%-5d", tb);
127 fprintf(mb_save, "\n");
128 }
129 break;
130 case 1:
131 mb_save = fopen("mb2.txt", "w+");
132 break;
133 case 2:
134 mb_save = fopen("mb3.txt", "w+");
135 break;
136 case 3:
137 mb_save = fopen("mb4.txt", "w+");
138 break;
139 }
140 
141 fclose(mb_save);
142}

The only other file handling that the program does is the main() function with the data file. Speaking of which, you don't think the *argv[] in main's parameters would be causing this do you?

EDIT: I think I may have figured it out. Apparently the constant checking of if a file exists is interfering with completing other actions on the file. Which is odd because logically, the way the functions run, they shouldn't be interfering with each other. But I got rid of constantly checking on the file's existance, and it deleted fine. Now I just have to reprogram the same effect without constantly checking the file.

Steve Terry
Member #1,989
March 2002
avatar

I hope you realize your save_check function does NOT close the file if it is found, notice you return from the function yet your flcose statement is at the bottom. If you close it before returning, it should fix your issue. Why would you check to see if a file exists anyway every time in a loop? Besides that use stat instead of fopen to check if a file exists, it will be much quicker and less resources will be used.

include <stat.h>

int fexist( char *filename ) {
  struct stat buffer ;
  if ( stat( filename, &buffer ) ) return 1 ;
  return 0 ;
}

Cookies for teh win!!!!!!!

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Evert
Member #794
November 2000
avatar

What's wrong with using Allegro's exists() function?

Seraph6
Member #7,517
July 2006
avatar

Steve said:

I hope you realize your save_check function does NOT close the file if it is found

Thanks, I notice that now. Very stupid mistake that slipped by me.

Steve said:

Why would you check to see if a file exists anyway every time in a loop?

I think I did it so that... you know what? I don't remember why. Hmm...

Steve said:

Besides that use stat instead of fopen to check if a file exists, it will be much quicker and less resources will be used.

Thanks, I assume that checks the status of the file (hence "stat"). I'm not sure I completely get how it works quite yet, but it's not too hard to understand.

Evert said:

What's wrong with using Allegro's exists() function?

I'm not familiar with that function. Is there somewhere on allegro.cc I could read about it?

A note to everyone who posted here, my credits for the game are short, so I decided I could fit all who contributed help in a little thanks section of the credits.

BAF
Member #2,981
December 2002
avatar

int file_exists(const char *filename, int attrib, int *aret);

And your switch way of figuring out which file to load is very ugly. You could just make the filename based on the id:

void blah(int id)
{
    char filename[512];
    snprintf(filename, 512, "fileblah%d.txt", id); // makes fileblah{id}.txt
    fopen(filename, ...);
    // ...
}

Go to: