1

So im writing a program to open a directory, get all the files inside, and then read the contents of each file. currently i successfully got all the file names in a string array. the print files[] loop shows all the file names, but the loop to check frequency does not read the files correctly. how do i successfully read an array of file names and then scan each of their contents?

//Open Directory
        DIR *dr = opendir(path);
        struct dirent *de;
        if(dr == NULL){
                printf("Could not open directory");
                return 0 ;
        }
        const char* files[100];
        int buffer=0;
        //Read Directory Files
        while((de = readdir(dr)) != NULL){
                files[buffer] = de->d_name;
                buffer++;
        }
        for(int x = 0; x <= buffer; x++){
                printf("%s" , files[x]);
        }
        closedir(dr);
        //Check Frequency
        for(int i = 0; i <= buffer; i++){
                int ch;
                FILE *fp;
                fp = fopen(files[i], "r");
                if(fp == NULL)
                        continue;
                ch = fgetc(fp);
                while(ch != EOF){
                        ch = tolower(ch);
                        if(ch>=97 && ch<= 122){
                                alphabetfreq[ch-97]++;
                        }
                        ch = fgetc(fp);
                }
        fclose(fp);
5
  • The problem seems to be in the "Check Frequency" loop Commented Jul 19, 2019 at 1:21
  • 5
    You cannot simply assign the pointer from de->d_name to your array. de->d_name is an internal variable and likely reused by readdir. You should allocate for each name and store the name instead of a pointer to de->d_name Commented Jul 19, 2019 at 1:29
  • You may want to look at C writing readdir to char array variable? Commented Jul 19, 2019 at 1:32
  • 1
    alphabetfreq[] definition and much else missing. Review minimal reproducible example Commented Jul 19, 2019 at 2:46
  • The posted code is missing the check for a sub directory. The posted code is missing the check for . and .. file names. The posted code is missing the check for symbolic links Commented Jul 20, 2019 at 7:22

1 Answer 1

1

There are multiple things wrong with the program. But the main reason why it is not reading the files is that you are just passing the file names to fopen(), so it is looking for them in current directory and returning null values. Also you are not handling the null results carefully. And the condition in the loop should x < buffer and not x <= buffer.

#include<stdio.h>
#include<dirent.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>

int main()
{
  int alphabetfreq[100], i;
  for(i = 0; i < 100; i++){
    alphabetfreq[i] = 0;
  }
  char path[] =  "/home/path_to_directory/";
  DIR *dr = opendir(path);
       struct dirent *de;
       if(dr == NULL){
               printf("Could not open directory");
               return 0 ;
       }
       const char* files[100];
       int buffer=0;
       //Read Directory Files
       while((de = readdir(dr)) != NULL){
               files[buffer] = de->d_name;
               buffer++;
       }
       for(int x = 0; x < buffer; x++){
               printf("%s" , files[x]);
       }
       closedir(dr);
       printf("\n");
       //Check Frequency
       for(int i = 0; i < buffer; i++){
               int ch;
               FILE *fp;
               char * file = malloc(strlen(path) + strlen(files[i]) + 1);
               strcpy(file, path);
               strcat(file, files[i]);
               fp = fopen(file, "r");
               if(fp == NULL)
              {
                printf("no file %s\n", file);
                continue;
              }
               ch = fgetc(fp);
               while(ch != EOF){
                       ch = tolower(ch);
                       if(ch>=97 && ch<= 122){
                               alphabetfreq[ch-97]++;
                       }
                       ch = fgetc(fp);
               }

       fclose(fp);
     }

     for(i = 0; i < 26; i++)
     {
       printf("%c %d\n", i+97, alphabetfreq[i]);
     }
}

This is working for me.

Sign up to request clarification or add additional context in comments.

3 Comments

files[buffer] = de->d_name; suffers from the same problem noted in the comments under the original question.
Additionally the number of file names is hard coded; there might be more than 100 files. And why not allocate the space for each filename including the path in the loop reading the directory? Your source doesn't free the memory, anyway.
I think it is okay to copy pointer value from de->d_name because we only need to read it(at least in this case). The better option would be creating a pointer array of de type and store the return values there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.