2013-10-18 67 views
0

我有以下程序工作,但问题是它只在给出路径时才起作用。我试图找到一种方法来设置当前工作目录的路径,如果没有路径给出。为此,我使用char * cdir = getcwd(0,0);我需要找到一种方法将其设置为argv,以便它指向该路径而不是null。任何人都可以检查我的代码,并告诉我我做错了什么。我正在使用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); 

     } 
    } 
} 
+0

是的我可以 - 三小时工作。 300英镑,这是做 –

+0

@EdHeal:这只是让我想到搬到苏格兰:D – LihO

+0

@LihO - 我希望不是阳光! –

回答

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正好指向一个字符串(指针列表上没有空终止),并且argc现在是不重要的。

 printf("%s",argv); 

这是错误的;它应该是以下其中一行:

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

您已将zapped原始参数列表并且唯一的参数left是当前目录。

 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; 
      } 

虽然你会发现'wroth'在一个体面的字典('形(古):愤怒'),你可能意思是'错误'。而对人们的嘘声是不仁慈的。此外,错误消息最好打印到标准错误;这就是它的目的。如果您使用else(或else if),则可以避开continue

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

这很好。

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

我会写这个作为当前代码结构的else子句。

由于如果用户明确将名称.作为参数传递,您将执行相同的操作,因此如果用户没有提供当前目录作为第一个参数,则很容易引起虚假事情。因为当你进入main(),条件argv[argc] == NULL是真实的,你其实可以写:

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; 
} 

尽管从别人的警告,argcargv都在main()函数的局部变量和可修改(小心)。修改argv[argc]中的数据更为狡猾,但这取决于您的代码是使用空指针标记还是使用计数。如果你使用count并且永远不能访问(修改后的)argv数组,那么你会没事的。如果你的访问超出了最终结果,那么你在大多数Unix变体上践踏(或读取)你的环境变量。

如果您确定要使用当前目录的绝对路径名称,那么您仍然可以调整我概述的方案以使用该方案。假设你工作在Linux或BSD衍生平台,给出一个空指针,当你的getcwd()版本将分配内存,所以你可以写:

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

看的是一个空指针的唯一的事情:

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

当你需要做的,而不是实行基本系统调用在现实生活中工作,可以考虑使用nftw() 遍历目录层次结构为您服务。

+0

+1获得惊人的答案。我是那个建议不要修改'argv'的人,但我并不是说它不是可以做到的 - 只是需要关心,除非有人提供了详细的howto,否则在这种情况下这可能是不值得的。 ) – LSerni