Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
140 views
in Technique[技术] by (71.8m points)

c - return 2d array from function

I have an function that loads data and put them into an array

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

but this does not work , this is the ebst result of trying , how can i make it work?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As mentioned in the comment, you have several issues to correct. Starting with "Why is getline not working?" getline takes a FILE * stream pointer not a file descriptor as its third parameter. Using stdin instead of 0 will correct the problem. The remaining problems deal with allocation. Those have been discussed in the comments and corrected examples are shown below.

The biggest issue you will run into, is "How will I know how many lines were actually read?" You have hard-coded '5', but what if you read less than 5?

To answer the question, you need to, at minimum, pass a pointer as a parameter to your array_of_string function, and update it value with the index value so that the number of lines read is available back in the calling function (main() in this case). That way, you always know the number of lines read. For example:

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

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

    return array;
}

Your next challenge is "How do I check to make sure I don't read, and try to store, more than 5 lines?" Then, "What do I do if I have more than 5 lines to read?", "Then what?". That is where you either break from your read loop or, better, use the realloc function to reallocate array to increase the number of pointers available. (you can add as many as you want, but a standard approach is to double the current number of pointers you have -- that approach is shown below).

#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 = index;
                return array;
            }
            array = tmp;  /* set new pointers to NULL */
            memset (array + maxln, 0, maxln * sizeof *array);
            maxln *= 2;
        }
    }
    ...
}

Putting all the pieces together, you could do something like the following, which initially allocate some reasonably anticipate number of pointers to hold the number of lines you expect to read. If you reach that limit before your read is done, you simply realloc the number of pointers to 2X current. (you realloc using a tmp pointer to protect against loss of all existing data in array if realloc fails. if realloc succeeds, you simply assign array = tmp;)

Take a look at the following and let me know if you have any questions about it:

#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.
");
        return 1;
    }

    for (i = 0; i < lines; i++) /* print lines */
        printf (" line[%3zu] : %s
", 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.
");
        return NULL;
    }

    while ((rd = getline(&line, &length, stdin)) != -1)
    {
        while (rd > 0 && (line[rd-1] == '
' || line[rd-1] == '
'))
            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 = 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;
}

Compile - with warnings enabled

gcc -Wall -Wextra -o bin/stdintst stdintst.c

(or using similar options for your compiler)

Input File

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.

Use/Output

$ ./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.

Memory Error Check

In any code your write that dynamically allocates memory, you have 2 responsibilites regarding any block of memory allocated: (1) always preserves a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.

It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated.

For Linux valgrind is the normal choice. There are many subtle ways to misuse a new block of memory. Using a memory error checker allows you to identify any problems and validate proper use of of the memory you allocate rather than finding out a problem exists through a segfault. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.

$ 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)

Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.

Let me know if you have any further questions.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...