0

次のプログラムが動作していますが、パスが指定されている場合にのみ動作するという問題があります。パスが指定されていない場合、現在の作業ディレクトリへのパスを設定する方法を見つけようとしています。そのために私は char *cdir = getcwd(0,0); を使用しています。null の代わりにそのパスを指すように、argv に設定する方法を見つける必要があります。誰でも私のコードをチェックして、私が間違っていることを教えてもらえますか? これをコンパイルするためにUNIXシステムを使用しています。

#include <dirent.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>


typedef struct stat Sub;
typedef struct dirent Dir;


void skimPath(const char *);

main(int argc, char *argv[])
{
    int i;
    Sub path;
    char *cdir = getcwd(0,0);

    if (argc <= 1)
    {
       /*
       this is the part i'm having trouble with, everything else works. I need a way to set  
       the path that is in cdir, to argv, so that it would work just like the case below      
       where argc is more than 2
       */

        argv = &cdir;
        printf("%s",argv);
        for (i = 1; i < argc; i++)
        {
            if (stat(*(argv + i), &path) == -1)
            {
                printf("WROTH PATH, DIRECTORY NOT FOUND \n%s\n", *(argv + i) ); 
                continue; 
            }

            if (S_ISDIR(path.st_mode)) 
                skimPath(*(argv + i));
        }
    }

    if (argc >= 2)
    {

        for (i = 1; i < argc; i++)
        {
            if (stat(*(argv + i), &path) == -1)
            {
                printf("WROTH PATH, DIRECTORY NOT FOUND \n%s\n", *(argv + i) ); 
                continue;
            }

            if (S_ISDIR(path.st_mode)) 
                skimPath(*(argv + i));

        }
    }
}


void skimPath(const char *dirName)
{
    char str[100];
    DIR *dir;
    Sub path;
    Dir *d;
    if ((dir = opendir(dirName)) == NULL)
    {
        printf(str, "File or Directory Could Not Open");
    }

    while ((d = readdir(dir)) != NULL)
    {
        // check if directory is d or d's paren   
        if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) 
            continue; // if ture rest will be ignored from while loop

        // saves in a buffer pointed by str
        sprintf(str, "%s/%s", dirName, d->d_name);


        if (stat(str, &path) == -1)
        {
            continue;
        }

        //checks to see if its a d
        if (S_ISDIR(path.st_mode))
        {
            printf("%s \n",d->d_name);

            // directory goes in str
            skimPath(str);

        }
    }   
}
4

1 に答える 1

1

あなたのコードを分析することはできますが、あなたがやろうとしていることはかなり奇妙です (詳しく言えば、あなたが望むことを行う方法は他にもあると思います)。

main(int argc, char *argv[])
{
    int i;
    Sub path;
    char *cdir = getcwd(0,0);

常に使用するとは限らないためcdir、使用するブロック内で宣言することができます (すべきです)。 getcwd()特に、複数のマウントされたファイルシステムを処理する必要がある場合、特に NFS マウントされたファイルシステムがある場合は、高価な機能です。

    if (argc <= 1)
    {
       /*
       this is the part i'm having trouble with, everything else works. I need a way to set  
       the path that is in cdir, to argv, so that it would work just like the case below      
       where argc is more than 2
       */

        argv = &cdir;

この声明は「正当」ですが、あなたはその結果について考えていません。argv正確に 1 つの文字列 (ポインターのリストに null 終端がない)を指すようになり、argc重要ではなくなりました。

        printf("%s",argv);

これは間違っています; 次の行のいずれかである必要があります。

printf("%s\n", argv[0]);
printf("%s\n", *argv);
printf("%s\n", cdir);

元の引数リストを消去したため、残っている唯一の引数は現在のディレクトリです。

        for (i = 1; i < argc; i++)
        {

argv現在は を指しているためcdir、引数を反復処理することはできません。二重に、インデックス 1 から開始することはできません。

            if (stat(*(argv + i), &path) == -1)

はい、argv[i]そのように書くことができますが、なぜそうするのですか?

            {
                printf("WROTH PATH, DIRECTORY NOT FOUND \n%s\n", *(argv + i) ); 
                continue; 
            }

まともな辞書 ('adj (古語): 怒っている') で 'wroth' を見つけることができますが、おそらく 'wrong' を意味します。そして、人に向かって叫ぶのは不親切です。また、エラー メッセージは標準エラーに出力するのが最適です。それが目的です。else(またはelse if)を使用した場合は、 continue.

            if (S_ISDIR(path.st_mode)) 
                skimPath(*(argv + i));
        }
    }

このくらいでOKです。

    if (argc >= 2)
    {
        ...
    }

elseこれを現在のコード構造の句として書きます。

ユーザーが名前を引数として明示的に渡す場合も同じことを行うため、ユーザーが.現在のディレクトリを指定しなかった場合に、最初の引数として現在のディレクトリを指定することで、偽物を作成することは非常に魅力的です。を入力するmain()と、条件argv[argc] == NULLが true になるため、実際には次のように記述できます。

int main(int argc, char **argv)
{
    if (argc == 1)
        argv[argc++] = ".";

    assert(argc > 1);
    for (int i = 1; i < argc; i++)
    {
        ...code from the if (argc >= 2) part of your code...
    }
    return 0;
}

複数の引数を挿入する必要がある場合は、次のように、もう少し複雑な手順を踏む必要があります。

if (argc < XXX)
{
    static char *alt_argv[] = { 0, "xyz", "pqr", "abc", 0 };
    alt_argv[0] = argv[0];
    argv = alt_argv;
    argc = (sizeof(alt_argv) / sizeof(alt_argv[0])) - 1;
}

他の人からの警告にもかかわらず、 は関数内のローカル変数であり、argc(慎重に) 変更できます。のデータを変更するのは危険に近いですが、コードでヌル ポインター センティネルを使用するかカウントを使用するかによって異なります。カウントを使用し、(変更された)配列の終わりを超えてアクセスしない場合は、問題ありません。最後までアクセスすると、ほとんどの Unix バリアントで環境変数を踏みにじる (または環境変数から読み取る) ことになります。argvmain()argv[argc]argv

現在のディレクトリの絶対パス名を使用することに決めた場合でも、私が概説したスキームをそれで動作するように適応させることができます。Linux または BSD 派生プラットフォームで作業していると仮定するとgetcwd()、ヌル ポインターが指定されたときに のバージョンがメモリを割り当てるため、次のように記述できます。

if (argc == 1)
    argv[argc++] = getcwd(NULL, 0);

注意すべき唯一のことは、null ポインターです。

for (i = 1; i < argc && argv[i] != NULL; i++)
    ...

基本的なシステム コールを練習する代わりに、実際にジョブを実行する必要がある場合はnftw() 、ディレクトリ階層をトラバースするために を使用することを検討してください。

于 2013-10-19T01:27:39.060 に答える