簡體   English   中英

如何將一個字符指針數組從函數返回到main?

[英]How to return an array of character pointers from a function back to main?

我正在嘗試將具有 .txt 擴展名的文件列表存儲到我當前工作目錄中的數組中。 我已經把數組放在一起了,現在我只需要返回它。 我是 C 新手,不習慣指針情況。 如何返回一個字符指針數組? 我創建了數組,並根據我在目錄中找到的文本文件數量進行分配。

當我嘗試編譯時遇到兩個錯誤,這讓我相信我對指針的理解與我想象的不同。 我也一直讀到我的數組在從函數返回時會被銷毀,因為它在堆棧上。 我不知道如何解決這個問題。 歡迎任何幫助或批評。

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

如果您希望getTxtFilesInDir返回一個字符串數組,它應該返回一個char** ,而不是一個char*

此外,您不需要將變量聲明為static 當您希望該變量對於函數的所有調用保持相同時,您可以將函數中的變量聲明為static 在這種情況下,這可能不是您想要做的。

無需修改太多初始代碼,您可以先為一組字符串分配內存,然后在有新條目時調整其大小。 在本例中,我立即執行此操作,因為realloc(NULL, somesize)與執行malloc(somesize) 這就是為什么初始化*tmp = 0txtFiles = 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 在您的情況下,您已經分配了足夠的內存,因此無需分配。 並且當您使用strncpy ,限制應綁定到目標可用的字節數,而不是源可用的字節數,否則您復制的字節數可能會多於應有的字節數。 在您的情況下,您將無法獲得有效的 c 字符串,因為您只能復制到dir->d_name的長度,因此不會復制'\\0'終止。

男人

#include <string.h> char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n);

[...]

strncpy()函數類似,除了最多復制src n個字節。 警告:如果src的前n個字節中沒有空字節,則放置在 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM