从函数返回2d数组

时间:2016-01-14 22:35:47

标签: c arrays

我有一个加载数据并将它们放入数组的函数

char array_of_string() {
    char **array;
    size_t size = 5;
    size_t index = 0;
    size_t length = 0;
    int rd;
    char *line;
    array = (char **) malloc(size * sizeof(char*));
    while ((rd = getline(&line, &length, 0) != -1) {
      array[index] = malloc(strlen(line) + 1 * sizeof(char));
      strncpy(array[index], line);
      index++    
    }

   free(line);
   return array;
}

int main() { 
  char **here;
  here = array_of_strings();
}

但这不起作用,这是尝试的最终成果,我怎样才能让它发挥作用?

2 个答案:

答案 0 :(得分:1)

如评论中所述,您有几个问题需要纠正。从“为什么getline无效?”开始getlineFILE *流指针而不是文件描述符作为其第三个参数。使用stdin代替0可以解决问题。剩下的问题涉及分配。这些已经在评论中讨论过,更正的例子如下所示。

您将遇到的最大问题是“我怎么知道实际读取了多少行?”您有硬编码'5',但如果您阅读的内容少于5

要回答这个问题,您至少需要将指针作为参数传递给array_of_string函数,并使用index值更新它的值,以便读取的行数是在调用函数中可用(在这种情况下为main())。这样,你总能知道读取的行数。例如:

char **array_of_string (size_t *n)
{
    ...
    free (line);

    *n = index;  /* update n with index, so available in main() */

    return array;
}

您的下一个挑战是“我如何检查以确保我没有阅读,并尝试存储超过5行?”然后,“如果我有超过5行读取,该怎么办?”,“那又怎么样?”。这是您从读取循环中break或更好地使用realloc函数重新分配array以增加可用指针数的位置。 (你可以添加任意多个,但标准的方法是加倍你当前的指针数量 - 这种方法如下所示。)

#define MAXLN 5
...
char **array_of_string (size_t *n)
{
    ...
    size_t maxln = MAXLN;
    ...
    while ((rd = getline(&line, &length, stdin)) != -1)
    {
        ...
        array[index++] = strdup(line); /* alloc & copy  */

        if (index == maxln) {   /* check limit reached  - reallocate */
            char **tmp = realloc (array, maxln * sizeof *array * 2);
            if (!tmp) {
                fprintf (stderr, "error: realloc - memory exhausted.\n");
                *n = index;
                return array;
            }
            array = tmp;  /* set new pointers to NULL */
            memset (array + maxln, 0, maxln * sizeof *array);
            maxln *= 2;
        }
    }
    ...
}

将所有部分组合在一起,您可以执行以下操作,最初会分配一些合理预期的指针数来保存您希望读取的行数。如果您在阅读完成之前达到了该限制,则只需realloc指向 2X 的指针数。 (realloc使用tmp指针保护array realloc realloc如果array = tmp;失败,可以防止丢失所有现有数据。如果#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXLN 5 char **array_of_string (size_t *n); int main (void) { char **here = NULL; size_t i, lines = 0; /* assign array_of_string to here, check return */ if (!(here = array_of_string (&lines))) { fprintf (stderr, "error: array_of_string return NULL.\n"); return 1; } for (i = 0; i < lines; i++) /* print lines */ printf (" line[%3zu] : %s\n", i, here[i]); for (i = 0; i < lines; i++) /* free lines */ if (here[i]) free (here[i]); free (here); /* free here */ return 0; } char **array_of_string (size_t *n) { char **array = NULL; char *line = NULL; size_t index = 0, length = 0, maxln = MAXLN; ssize_t rd = 0; if (!(array = calloc (MAXLN, sizeof *array))) { fprintf (stderr, "error: virtual memory exhausted.\n"); return NULL; } while ((rd = getline(&line, &length, stdin)) != -1) { while (rd > 0 && (line[rd-1] == '\r' || line[rd-1] == '\n')) line[--rd] = 0; /* strip carriage return or newline */ array[index++] = strdup(line); /* alloc & copy */ if (index == maxln) { /* check limit reached - reallocate */ char **tmp = realloc (array, maxln * sizeof *array * 2); if (!tmp) { fprintf (stderr, "error: realloc - memory exhausted.\n"); *n = index; return array; } array = tmp; /* set new pointers to NULL */ memset (array + maxln, 0, maxln * sizeof *array); maxln *= 2; } } free(line); /* free memory allocated by getline */ *n = index; /* update n with index, so available in main() */ return array; } 成功,则只需指定gcc -Wall -Wextra -o bin/stdintst stdintst.c 1}})

如果您对此有任何疑问,请查看以下内容并告知我们:

cat ../dat/damages.txt
Personal injury damage awards are unliquidated
and are not capable of certain measurement; thus, the
jury has broad discretion in assessing the amount of
damages in a personal injury case. Yet, at the same
time, a factual sufficiency review insures that the
evidence supports the jury's award; and, although
difficult, the law requires appellate courts to conduct
factual sufficiency reviews on damage awards in
personal injury cases. Thus, while a jury has latitude in
assessing intangible damages in personal injury cases,
a jury's damage award does not escape the scrutiny of
appellate review.

Because Texas law applies no physical manifestation
rule to restrict wrongful death recoveries, a
trial court in a death case is prudent when it chooses
to submit the issues of mental anguish and loss of
society and companionship. While there is a
presumption of mental anguish for the wrongful death
beneficiary, the Texas Supreme Court has not indicated
that reviewing courts should presume that the mental
anguish is sufficient to support a large award. Testimony
that proves the beneficiary suffered severe mental
anguish or severe grief should be a significant and
sometimes determining factor in a factual sufficiency
analysis of large non-pecuniary damage awards.

编译 - 启用警告

$ ./bin/stdintst <../dat/damages.txt
 line[  0] : Personal injury damage awards are unliquidated
 line[  1] : and are not capable of certain measurement; thus, the
 line[  2] : jury has broad discretion in assessing the amount of
 line[  3] : damages in a personal injury case. Yet, at the same
 line[  4] : time, a factual sufficiency review insures that the
 line[  5] : evidence supports the jury's award; and, although
 line[  6] : difficult, the law requires appellate courts to conduct
 line[  7] : factual sufficiency reviews on damage awards in
 line[  8] : personal injury cases. Thus, while a jury has latitude in
 line[  9] : assessing intangible damages in personal injury cases,
 line[ 10] : a jury's damage award does not escape the scrutiny of
 line[ 11] : appellate review.
 line[ 12] :
 line[ 13] : Because Texas law applies no physical manifestation
 line[ 14] : rule to restrict wrongful death recoveries, a
 line[ 15] : trial court in a death case is prudent when it chooses
 line[ 16] : to submit the issues of mental anguish and loss of
 line[ 17] : society and companionship. While there is a
 line[ 18] : presumption of mental anguish for the wrongful death
 line[ 19] : beneficiary, the Texas Supreme Court has not indicated
 line[ 20] : that reviewing courts should presume that the mental
 line[ 21] : anguish is sufficient to support a large award. Testimony
 line[ 22] : that proves the beneficiary suffered severe mental
 line[ 23] : anguish or severe grief should be a significant and
 line[ 24] : sometimes determining factor in a factual sufficiency
 line[ 25] : analysis of large non-pecuniary damage awards.

(或使用编译器的类似选项)

输入文件

valgrind

使用/输出

segfault

内存错误检查

在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在释放时释放它不再需要了。

必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已释放所有内存你分配的记忆。

对于Linux $ valgrind ./bin/stdintst <../dat/damages.txt ==12233== Memcheck, a memory error detector ==12233== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==12233== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==12233== Command: ./bin/stdintst ==12233== line[ 0] : Personal injury damage awards are unliquidated line[ 1] : and are not capable of certain measurement; thus, the <snip> line[ 24] : sometimes determining factor in a factual sufficiency line[ 25] : analysis of large non-pecuniary damage awards. ==12233== ==12233== HEAP SUMMARY: ==12233== in use at exit: 0 bytes in 0 blocks ==12233== total heap usage: 31 allocs, 31 frees, 1,989 bytes allocated ==12233== ==12233== All heap blocks were freed -- no leaks are possible ==12233== ==12233== For counts of detected and suppressed errors, rerun with: -v ==12233== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) 是正常的选择。有许多微妙的方法可以滥用新的内存块。使用内存错误检查器可以识别任何问题并验证您分配的内存的正确使用情况,而不是通过{{1}}找出问题。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。

{{1}}

始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误

如果您有任何其他问题,请与我们联系。

答案 1 :(得分:0)

如果您要将array_of_string保留在main函数之外(这是一个好主意),那么您应该传递一个指向数组的指针,以便您可以直接编辑数组本身的内容。如果在作用域中声明或分配内存,则一旦作用域结束,它将自动释放。如果您然后尝试访问该内存,则会得到未定义的结果。 Pass array to function in C

此外:

while ((rd = getline(&line, &length, 0) != -1) {
  array[index] = malloc(strlen(line) + 1 * sizeof(char));

Getline会将长度更改为已分配字符串的大小。您可以删除strlen(line)并将其替换为length,或者使用rd代替以节省一些CPU周期。请记住,rd和长度可能不同。 Getline(3)