zeboidlund
zeboidlund

Reputation: 10157

Check if a file is a specific type in C

I'm writing my first C program, though I come from a C++ background.

I need to iterate through a directory of files and check to see if the file is a header file, and then return the count.

My code is as follows, it's pretty rudimentary I think:

static int CountHeaders( const char* dirname ) {

    int header_count = 0;
    DIR* dir_ptr;
    struct dirent* entry;

    dir_ptr = opendir( dirname );

    while( ( entry = readdir( dir_ptr ) ) )
    {
        if ( entry->d_type == DT_REG )
        {
            //second if statement to verify the file is a header file should be???
            ++header_count;
        }
    }

    closedir( dir_ptr );

    return header_count;
}

What would be a good if statement to check to see if the file is a header?

Upvotes: 3

Views: 5422

Answers (6)

Alok Save
Alok Save

Reputation: 206636

Simply check if the file extension is .h, something like:

const char *ext = strrchr (entry->d_name, '.');     
if ((ext != NULL) && (!strcmp (ext+1, "h"))) {
     // header file
}

Ofcourse, note that this assumes all your header files have an .h extension, which may or may not be true, the C standard does not mandate that header files must have an .h extension.

Upvotes: 3

chacham15
chacham15

Reputation: 14281

There are some much better methods than checking the file extension.

Wikipedia has a good article here and here. The latter idea is called the magic number database which essentially means that if a file contains blah sequence then it is the matching type listed in the database. Sometimes the number has restrictions on locations and sometimes it doesnt. This method IMO is more accurate albeit slower than file extension detection.

But then again, for something as simple as checking to see if its a header, this may be a bit of overkill XD

Upvotes: 2

paxdiablo
paxdiablo

Reputation: 882626

Each dirent structure has a d_name containing the name of the file, so I'd be looking to see if that followed some pattern, like ending in .h or .hpp.

That would be code along the lines of:

int len = strlen (entry->d_name);
if ((len >= 2) && strcmp (&(entry->d_name[len - 2]), ".h") == 0))
    header_count++;
if ((len >= 4) && strcmp (&(entry->d_name[len - 4]), ".hpp") == 0))
    header_count++;

Of course, that won't catch truly evil people from calling their executables ha_ha_fooled_you.hpp but thanfkfully they're in the minority.

You may even want to consider an endsWith() function to make your life easier:

int endsWith (char *str, char *end) {
    size_t slen = strlen (str);
    size_t elen = strlen (end);
    if (slen < elen)
        return 0;
    return (strcmp (&(str[slen-elen]), end) == 0);
}
:
if (endsWith (entry->d_name, ".h"))   header_count++;
if (endsWith (entry->d_name, ".hpp")) header_count++;

Upvotes: 2

Christian Stieber
Christian Stieber

Reputation: 12496

That's up to you.

The easiest way is to just look at the filename (d_name), and check whether it ends with something like ".h" or ".hpp" or whatever.

Opening the file and actually reading it to see if it's valid c/c++, on the other hand, will be A LOT more complex... you could run it through a compiler, but not every header works on its own, so that test will give you a lot of false negatives.

Upvotes: 0

rjz
rjz

Reputation: 16510

You probably just want to check the file extension. Using dirent, you would want to look at d_name.

Upvotes: 0

Bart Friederichs
Bart Friederichs

Reputation: 33573

You could check if the last few characters are one of the header-file extensions, .h, .hpp, etc. Use the dirent struct's d_name for the name of the file.

Or, you could run the 'file' command and parse its result.

Upvotes: 1

Related Questions