如何将一个字符指针数组从函数返回到main?

时间:2018-02-07 22:24:30

标签: c arrays pointers

我试图将扩展名为.txt的文件列表存储到当前工作目录的数组中。我已经把阵列放在一起了,现在我只需要把它归还。我是C的新手,我不熟悉指针的情况。我怎样才能返回一个char指针数组?我创建了数组,并根据我在目录中找到的文本文件分配了它。

我尝试编译时遇到两个错误,这让我相信我对指针的理解不是我想的那样。我也一直在读取从函数返回时我的数组将被销毁,因为它在堆栈中。我不知道如何解决这个问题。欢迎任何帮助或批评。

    // prototypes
    char* getLine();
    void replaceWord();
    char * getTxtFilesInDir(char*);
    bool isTxt(char *);

    int main(int argc, char **argv) {

       // Check to see if correct number of arguments is given
       if (argc < 4) {
          printf("ERROR: Not enough parameters supplied. Please supply a find,"
                "replace, and prefix parameter and try again.\n");
          return -1;
       }

       // Initialize variables
       char *find, *replace, *prefix;
       find=argv[1];
       replace=argv[2];
       prefix=argv[3];
       char cd[1024];

       // Get the Current working directory to grab files
       if (getcwd(cd, sizeof(cd)) != NULL) {
          printf("Current working dir is: %s\n", cd);
       } else {
          perror("getcwd() error");
       }

       // Get the values of the arguments
       printf("Value of find: %s\nValue of replace: %s\nValue of prefix: %s\n",
             find, replace, prefix);

       // create an array of the files that are valid
       char* files = getTxtFilesInDir(cd);

       return 0;

    }
char*  getTxtFilesInDir(char* directory) {
   DIR *d;
   struct dirent *dir;
   d = opendir(directory);
   int n=0, i=0;

   // get the number of text files in the directory
   if (d) {
      while((dir = readdir(d)) != NULL) {
         if (isTxt(dir->d_name)) {
            n++;
         }
      }
   }

   rewinddir(d);
   // Create the array of text files depending on the size
   static char* txtFiles[n];

   // add the text files to the array
   if (d) {
      printf("Found: \n");
      while ((dir = readdir(d)) != NULL)
      {
         if (isTxt(dir->d_name)) {
            printf("%s\n", dir->d_name);
            txtFiles[i]= (char*) malloc (strlen(dir->d_name)+1);
            strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
            i++;

         }
      }
      closedir(d);
   }
   return txtFiles;
}

bool isTxt(char *file) {
   size_t len = strlen(file);
   return len > 4 && strcmp(file + len -4, ".txt") == 0;
}

1 个答案:

答案 0 :(得分:1)

如果你希望getTxtFilesInDir返回一个字符串数组,它应该 返回char**,而不是char*

此外,您无需将变量声明为static。你声明一个变量 在函数static中,当您希望变量保持不变时 所有函数调用。在这种情况下,这可能不是你想要的 做。

如果不修改过多的初始代码,可以先分配内存 对于一个字符串的arrray,然后在你有一个新的条目时调整它的大小。在 这个例子我立即这样做,因为realloc(NULL, somesize)与...相同 做malloc(somesize)。这就是为什么初始化*tmp = 0和。{ txtFiles = NULL,所以这个技巧有效。您还应该将指针传递给存储条目数的size_t

char **getTxtFilesInDir(const char* directory, size_t *len) {
    if(directory == NULL || len == NULL)
        return NULL;

    ...

    *len = 0;
    char **txtFiles = NULL, **tmp;
    char *str;

    if (d) {
      printf("Found: \n");
      while ((dir = readdir(d)) != NULL)
      {
         if (isTxt(dir->d_name))
         {
             tmp = realloc(txtFiles, (len+1) * sizeof *textFiles);
             if(tmp == NULL)
                 return txtFiles; // return what you've got so far


             str = malloc(strlen(dir->d_name) + 1);
             if(str == NULL)
             {
                 if(txtFiles == NULL) // first time, free everything
                 {
                     free(tmp);
                     return NULL;
                 }

                 return tmp; // return all you've got so far
             }

             strcpy(str, dir->d_name); // no need of strcnpy, you've allocated
                                       // enough memory
             txtFiles = tmp;
             txtFiles[(*len)++] = tmp;
         }
      }
      closedir(d);

      return txtFiles;
}

这里的重要部分是1.如何使用realloc扩展内存。然后呢 使用malloc为字符串分配内存。我在txtFiles = tmp;之前这样做, 所以我不必写许多if(...==NULL)。如果有的话 在此过程中错误,该函数返回它已有的所有文件名 存储

现在main你做了:

int main(int argc, char **argv)
{
    ...

    size_t len = 0;
    char **files = getTxtFilesInDir(cd, &len);

    if(file == NULL)
    {
        fprintf(stderr, "No files found\n");
        return 1;
    }

    for(size_t i = 0; i < len; ++i)
        printf("file: %s\n", files[i]);

    // freeing memory
    for(size_t i = 0; i < len; ++i)
        free(files[i]);

    free(files);

    return 0;
}

我还想对您的原始复制方式发表评论:

strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
当你想限制要复制的字节数时,

strncpy很棒。在 你已经分配了足够的内存,所以没有必要。和 当您使用strncpy时,限制应该绑定到字节数 可用于目的地,而不是源,否则您可能会复制更多 字节比它应该的。在您的情况下,您将无法获得有效的C字符串,因为您 限制复制到dir->d_name的长度,所以'\0' - 终止 不会被复制。

  

man strcpy

#include <string.h>

char *strcpy(char *dest, const char *src);

char *strncpy(char *dest, const char *src, size_t n);
     

[...]

     

strncpy()函数类似,只是复制了nsrc个字节。 警告:如果第一个n中没有空字节   src的字节,dest中的字符串不会以空值终止。

当您使用strncpy时,必须确保该副本是有效的字符串 自己设置'\0' - 终止字节。因为你已经分配了 字符串的strlen(dir->d_name)+1个字节:

strncpy(txtFiles[i], dir->d_name, strlen(dir->d_name));
textFiles[i][strlen(dir->d_name)] = 0;

程序的退出值也是unsigned值,从0到255。 在main中,您应该在出错时返回1而不是-1