返回一个数组,同时告诉他这个数组的长度?

时间:2017-06-25 17:30:55

标签: c arrays

我想过滤传入的字符串数组,如下所示:

char **
filter_vids(char **vids, size_t n) {
    int i;
    int count = 0;
    char ** filted = malloc(n * sizeof(char *));
    for(i = 0; i < n; i++){
        filted[i] = (char*)malloc(50 * sizeof(char));
    }
    for(i = 0; i < n; i++) {
        if(some_filter(vids[i])) {
            strcpy(filted[count++], vids[i]);
            printf("in filter:%s\n", vids[i]);
        }
    }
    return filted;
}

但调用者可能不知道返回数组的长度,它可以提取counter变量,所以返回数组的最佳做法是什么,同时告诉他正确的数组长度? 比如

char **
filter_vids(char **vids, size_t n, int *output_length)

使用output_length的最佳做法是什么?

我将此功能编辑为此,作为您的建议: char ** filter_vids(char **vids, size_t n) { int i; int count = 0; char ** filted = malloc((n + 1) * sizeof(char *)); for(i = 0; i < n; i++) { if(vids[i][0] <= 'f') { filted[count++] = strdup(vids[i]); } } filted[count] = NULL; return filted; }

2 个答案:

答案 0 :(得分:1)

要传递一个指向整数长度变量的指针,其值在函数中设置肯定是一个好方法。正如Malcolm所说,它也是通用的,可用于没有“无效”成员的值集。

对于带有无效空指针值的指针,可以使用空指针标记有效条目的结尾。例如,C运行时用于将命令行参数传递给main的字符串指针数组因此终止。

选择哪种方法取决于调用者如何使用生成的数组。如果按顺序处理,(while *p){ ..; ++p; }感觉不合时宜。另一方面,如果您需要随机访问并且必须执行等效的strlen才能对数组执行任何操作,那么最好通过指向长度的变量返回长度

两个评论:

首先,注意

之间的区别
  • 指向空字符串的有效指针(如果有人调用,假设myProg par1 "" par2argv[2]可能是指向零字节的有效指针);
  • 和一个无处指向的空指针;在示例中,argv[4]将是空指针,指示参数列表的结尾。

其次,你需要malloc更多的内存,这对于更长的字符串和/或严格的过滤器来说是浪费的。您可以在if子句中按需分配字符串。

答案 1 :(得分:1)

这些是常见选项:

  1. 通过指针接收允许的大小作为参数,用实际大小覆盖它,返回数组作为返回值。
  2. 通过指针接收输出数组作为参数,根据需要更新,返回实际大小作为返回值。
  3. 将一个sentinel值附加到输出数组(此处为空指针),如另一个答案所示。
  4. 使用更复杂的数据结构作为返回值。您可以使用结构,该结构存储数组或链表的大小。
  5. 示例(未经测试):

    typedef char* mystring;
    typedef mystring* mystringarray;
    typedef struct { mystringarray *arr; size_t size } mysizedstringarray;
    
    /* returns filtered array, size will be updated to reflect the valid size */
    mystringarray* myfun1(mystringarray in, size_t* size);
    
    /* out will be allocated and populated, actual size is returned */
    size_t myfun2(mystringarray in, size_t size, mystringarray* out);
    
    /* output array contains valid items until sentinel value (NULL) is reached */
    mystringarray* myfun3(mystringarray in, size_t size);
    
    /* returns filtered array with actual size */
    mysizedstringarray myfun4(mystringarray in, size_t size);