On 11/18/2015 12:54 PM,
ag...@drrob1.com wrote:
> I am trying to learn how to use scandir with c++ on Ubuntu 14.04.
Use Boost file system library.
> I have been able to get the example in the man page working, but this
> does not use a filter. I'm trying to understand how to use the filter
> param. I found code online and works, but I don't understand what it
> is doing and how to make it more flexible. Fragments of my attempts
> to understand what is going on remain below. The template of scandir
> says it takes a filter function. I have found that if this filter
> function does not have a const dirent * param, it will not compile
> under gcc. Needless to say, I don't always (are really ever) care
> about files that begin with 'a'. I am interested in, say, files that
> end in ".txt" but I don't understand what's needed here.
>
> I am coming to C++ after many years of modula-2 programming with
> stonybrook m-2. Pointers in m-2 are much easier to understand.
> Pointers in C++ are much more complex. This confusion is compounded
> by the lack of a proper array type in C++. So pointers are used much
> more extensively than in the Wirthian languages.
>
> Thanks,
> Rob
>
> #include <sys/types.h>
> #include <sys/dir.h>
> #include <sys/param.h>
All the above are system specific, non-portable. Avoid that by using
Boost file system library.
> #include <stdio.h>
> #include <unistd.h>
> #include <cstring>
> #include <cstdio>
> #include <fstream>
> #include <sstream>
> #include <iostream>
> #include <cstdlib>
> #include <cctype>
> #include <cmath>
> #include <ctime>
> #include <string>
> using namespace std;
>
> char pathname[MAXPATHLEN];
> char input[MAXPATHLEN];
Global variables are ungood. Raw arrays are ungood. MAXPATHLEN is
system-specific, non-portable; avoid that by using Boost file system
library.
> int * result;
Global variables are ungood. Uninitialized pointers are ungood.
> // From example I found online
> int filter(const dirent * filterpattern)
> {
> return (filterpattern->d_name[0] == 'a');
> }
This returns logical True if the first letter of d_name is "a". For C++
and C99 and later the function result type should be "bool".
> int main()
> {
> int count,i;
> dirent * * files;
> dirent * filterpattern;
> char * CurrentPathName;
>
> CurrentPathName = getcwd(pathname,MAXPATHLEN);
> if (pathname == NULL )
> {
> cout << "Error getting path" << endl;
> exit(0);
Exit value 0 means success. Exit with `EXIT_FAILURE` or a non-zero
system specific value to indicate failure. And in "main", just "return":
that invokes "exit" automatically.
> }
>
> filterpattern = new dirent; // almost forgot that I have to
> allocate this.
No, you don't have to allocate the "dirent" dynamically. You could and
should just declare it as a local variable. But at a higher level, you
shouldn't be doing this at all: avoid all that by using the Boost file
system library.
> cout << "Current Working Directory = " << pathname << ", " <<
> CurrentPathName << ", MAXPATHLEN = " << MAXPATHLEN << endl;
In Windows a "char" based string is not sufficient to hold an arbitrary
path. So for Windows you need to use wide strings. The Boost file system
library does that automatically for you.
> count = scandir(".", & files, filter, alphasort);
>
> if (count <= 0)
> {
> cout << "No files in this directory" << endl;;
> exit(0);
> }
>
> cout << "Number of files = " << count << endl;
> for (i=0; i < count-1; ++i)
> {
> cout << files[i]->d_name << ", ";
> free(files[i]);
> }
>
> cout << files[i]->d_name << endl;
> free(files);
> }
>
Cheers & hth.,
- ALf