|
Home > Archive > Unix Programming > January 2006 > Recursion problem using C
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Recursion problem using C
|
|
| Dreamcatcher 2006-01-29, 9:32 pm |
| Hello,
I'm trying to learn some C, reading my book, Beginning Linux Programming
I came across the following program. The program is supposed to walk
through directory's and print all its subdirectories. However the
program never seems to get out of the loop its in. I tried finding the
error but I don't see where it goes wrong, hopefully someone can shed a
light on this, source code is pasted below
/*
* This program should list the directory's + subdirs
* The search should begin on the location specief in
* main()
*
* This is a program taken from "Beginning Linux Programming"
*/
#include <unistd.h>
#include <stdio.h>
#include <dirent.h> /* All header files */
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
/* Here we write the printdir function */
void printdir(char *dir, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
/* We use opendir() to check wether the
directory from main() exists */
if((dp = opendir(dir)) == NULL) {
fprintf(stderr,"cannot open directory: %s\n", dir);
return;
}
/* If the directory exists we use chdir() to go into the
directory.
If the directory does not exist we printf above error
We use a recursive while loop to make sure it continues
aslong as
there are unlisted directory's */
chdir(dir);
while((entry = readdir(dp)) != NULL) {
lstat(entry -> d_name, &statbuf);
if(S_ISDIR(statbuf.st_mode)) {
if (strcmp(".", entry -> d_name) == 0)
continue;
printf("%*s%s/\n", depth,"", entry -> d_name);
printdir(entry -> d_name, depth + 4);
}
else printf("%*s%s/\n", depth,"", entry -> d_name);
}
/* When the program is doen crawling through the directory's
it use chdir()
to go back to the parent directory where it calls
closedir() to close the
opendir stram */
chdir("..");
closedir(dp);
}
int main()
{
printf("Directory scan of /home/roeland/programming:\n");
printdir("/home/roeland/programming",0); /* The
directory that needs to be listed */
printf("Done!\n");
return 0;
}
I have tried to debug the code and I think the program lies in the
"printdir(entry -> d_name, depth + 4);" line however, I still don't see
why this happens
| |
| Casper H.S. Dik 2006-01-29, 9:32 pm |
| Dreamcatcher <roeland.hemsteede@gmail.com> writes:
> if(S_ISDIR(statbuf.st_mode)) {
> if (strcmp(".", entry -> d_name) == 0)
> continue;
You are forgetting to skip "..".
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| Giorgos Keramidas 2006-01-29, 9:32 pm |
| On Fri, 27 Jan 2006 14:32:27 +0100, Dreamcatcher <roeland.hemsteede@gmail.com> wrote:
> I'm trying to learn some C, reading my book, Beginning Linux Programming
> I came across the following program. The program is supposed to walk
> through directory's and print all its subdirectories. However the program
> never seems to get out of the loop its in. I tried finding the error but
> I don't see where it goes wrong, hopefully someone can shed a light on
> this, source code is pasted below
The program has some logical errors. You use something similar to this:
opendir(foo);
chdir(foo);
while (readdir(foo)) {
}
chdir("..");
This is wrong, because you have no guarantee that ".." is the right path to
take after the loop exits.
| |
| Thomas Maier-Komor 2006-01-29, 9:32 pm |
| Dreamcatcher wrote:
> Hello,
>
> I'm trying to learn some C, reading my book, Beginning Linux Programming
> I came across the following program. The program is supposed to walk
> through directory's and print all its subdirectories. However the
> program never seems to get out of the loop its in. I tried finding the
> error but I don't see where it goes wrong, hopefully someone can shed a
> light on this, source code is pasted below
>
>
> /*
> * This program should list the directory's + subdirs
> * The search should begin on the location specief in
> * main()
> *
> * This is a program taken from "Beginning Linux Programming"
> */
>
> #include <unistd.h>
> #include <stdio.h>
> #include <dirent.h> /* All header files */
> #include <string.h>
> #include <sys/stat.h>
> #include <stdlib.h>
>
> /* Here we write the printdir function */
> void printdir(char *dir, int depth)
> {
>
> DIR *dp;
> struct dirent *entry;
> struct stat statbuf;
>
> /* We use opendir() to check wether the
> directory from main() exists */
> if((dp = opendir(dir)) == NULL) {
> fprintf(stderr,"cannot open directory: %s\n", dir);
> return;
> }
>
> /* If the directory exists we use chdir() to go into the
> directory.
> If the directory does not exist we printf above error
>
> We use a recursive while loop to make sure it continues
> aslong as
> there are unlisted directory's */
>
> chdir(dir);
> while((entry = readdir(dp)) != NULL) {
> lstat(entry -> d_name, &statbuf);
> if(S_ISDIR(statbuf.st_mode)) {
> if (strcmp(".", entry -> d_name) == 0)
> continue;
> printf("%*s%s/\n", depth,"", entry -> d_name);
> printdir(entry -> d_name, depth + 4);
> }
> else printf("%*s%s/\n", depth,"", entry -> d_name);
> }
>
> /* When the program is doen crawling through the directory's it
> use chdir()
> to go back to the parent directory where it calls
> closedir() to close the
> opendir stram */
>
> chdir("..");
> closedir(dp);
> }
>
> int main()
> {
>
> printf("Directory scan of /home/roeland/programming:\n");
> printdir("/home/roeland/programming",0); /* The directory
> that needs to be listed */
> printf("Done!\n");
>
> return 0;
> }
>
> I have tried to debug the code and I think the program lies in the
> "printdir(entry -> d_name, depth + 4);" line however, I still don't see
> why this happens
I guess you are trying to run this program under Linux. In this case you
might want to know about strace (which has been inspired by Solaris'
truss). Try running your executable with strace, then you might
understand much faster what is going on and why it doesn't do what you
expect.
e.g.:
$ strace ./a.out
HTH,
Tom
| |
| Pascal Bourguignon 2006-01-29, 9:32 pm |
| Dreamcatcher <roeland.hemsteede@gmail.com> writes:
> Hello,
>
> I'm trying to learn some C, reading my book, Beginning Linux
> programming I came across the following program. The program is
> supposed to walk through directory's and print all its
> subdirectories. However the program never seems to get out of the loop
> its in. I tried finding the error but I don't see where it goes wrong,
> hopefully someone can shed a light on this, source code is pasted
> below
> [...]
> if (strcmp(".", entry -> d_name) == 0)
> continue;
You need to special case the directory ".." too. This is the parent directory.
Since . and .. are the first two entries normally, the directories
you'll be walking will be:
/home/roeland/programming
/home/roeland/programming/. (ignored)
/home/roeland/programming/.. = /home/roeland
/home/roeland/. (ignored)
/home/roeland/.. = /home
/home/. (ignored)
/home/.. = /
/. (ignored)
/.. = /
/. (ignored)
/.. = /
/. (ignored)
/.. = /
/. (ignored)
/.. = /
....
> I have tried to debug the code and I think the program lies in the
> "printdir(entry -> d_name, depth + 4);" line however, I still don't
> see why this happens
Before using gdb or any other debugger on a program, you should insert
printf statement at strategical points.
For example if you added:
printf("dir=%s\n",dir);
before:
if((dp = opendir(dir)) == NULL) {
you would see the problem immediately.
--
__Pascal Bourguignon__ http://www.informatimago.com/
"Klingon function calls do not have "parameters" -- they have
"arguments" and they ALWAYS WIN THEM."
| |
| Alex Fraser 2006-01-29, 9:32 pm |
| "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
news:86bqxxn5ay.fsf@flame.pc...
> On Fri, 27 Jan 2006 14:32:27 +0100, Dreamcatcher
<roeland.hemsteede@gmail.com> wrote:
[snip][vbcol=seagreen]
> The program has some logical errors. You use something similar to this:
>
> opendir(foo);
> chdir(foo);
> while (readdir(foo)) {
> }
> chdir("..");
>
> This is wrong, because you have no guarantee that ".." is the right path
> to take after the loop exits.
What else could it reasonably be?
Alex
| |
| Dreamcatcher 2006-01-29, 9:32 pm |
| Alex Fraser wrote:
> "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
> news:86bqxxn5ay.fsf@flame.pc...
> <roeland.hemsteede@gmail.com> wrote:
> [snip]
>
> What else could it reasonably be?
>
> Alex
>
>
It is sorted, I changed "if (strcmp(".", entry -> d_name) == 0)" to "if
(strcmp(".", entry -> d_name) == 0 || strcmp("..", entry -> d_name) == 0)"
Thanks for the help!
| |
| Victor Wagner 2006-01-29, 9:32 pm |
| Alex Fraser <me@privacy.net> wrote:
: "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
: >
: > opendir(foo);
: > chdir(foo);
: > while (readdir(foo)) {
: > }
: > chdir("..");
: >
: > This is wrong, because you have no guarantee that ".." is the right path
: > to take after the loop exits.
: What else could it reasonably be?
Any place in the file system where there is a symbolic link to
directory.
--
| |
| Giorgos Keramidas 2006-01-29, 9:32 pm |
| On Fri, 27 Jan 2006 14:47:08 -0000, "Alex Fraser" <me@privacy.net> wrote:
> "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
> news:86bqxxn5ay.fsf@flame.pc...
> <roeland.hemsteede@gmail.com> wrote:
> [snip]
>
> What else could it reasonably be?
Pretty much anything. Just think of:
chdir("/tmp");
printdir("/etc", 0);
|
|
|
|
|