directory.c

ここで突然ですが、フォルダの中身の一覧を名前順にソートして*charの配列に格納できるように
directory.cを作ったので、少し説明します。
まだ名前一覧の取得しか機能が無いので、これから増えることもあるかもです。
#ifndef _DIRECTORY
#define _DIRECTORY

#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>

int dir_compare(const struct dirent **d1, const struct dirent **d2){
   return strcmp((*d1)->d_name, (*d2)->d_name);
}

// get list of sorted name of the directory content. on error return -1.
int dir_get_content(char *dirname, char ***listp){
   int i;
   struct dirent **namelist;
   int r = scandir(dirname, &namelist, NULL, dir_compare);
   if(r == -1) return -1;
   char *name;
   int s = 0;
   char **names = (char **)malloc(sizeof(char *) * (r - 2));
   for(i = 0; i < r; ++i){
      name = namelist[i]->d_name;
      if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
      names[s] = (char *)malloc(sizeof(char) * (strlen(name) + 1));
      strcpy(names[s++], name);
      free(namelist[i]);
   }
   free(namelist);
   *listp = names;
   return s;
}

#endif

ポイントはscandir関数です。
これはディレクトリの名前, (作ったstruct direntへのポインタ)のリストを格納したやつへのポインタを格納すべき住所,
struct direntのポインタでフィルタする関数, ソートに使う、(struct direntのポインタを格納したやつの住所)同士を比較する比較関数
の4つの引数を受け取り、取得したリストの数を返します。
なお、得たリストはmallocで場所が確保されているので、後にfreeする必要もあります。

opendir、readdirを使った後ソートした方が簡単に作れた気がしますが、使ったものは仕方がない。

受け取ったリストには、"."(自分自身), ".."(自分の親フォルダ)が含まれているので、リストの数から2引いた数のchar *の配列を作り、
その二つ以外だったらどこかに適当な場所を確保してそこに名前をコピーし、そのアドレスを作った配列に格納していきます。

ここでは、dir_get_content関数を作って、数やらcharやらの情報を伝えたいので、
最後に、作った配列のポインタを、(引数とした(charのポインタの配列)のポインタを格納すべき場所)が指す場所に格納し、
作った配列のサイズを返して、完成です。

例えば下のようなプログラムを作ると、その下の結果が帰ってきます。


#include <stdio.h>
#include "directory.c"

int main(){
   char *dirname = "/home/tororo7/Desktop/fun_c/";
   char **list;
   int listn = dir_get_content(dirname, &list);
   printf("there are %d contents.\n", listn);
   int k;
   for(k = 0; k < listn; ++k) printf("%s\n", list[k]);
   return 0;
}

there are 5 contents.
directory.c
network
rename.c
test
test.c