Frage

I am trying to read in from a text file in C. The method I am trying to create will return an array of strings having every line from the text file an index of the array. I can't figure out what I am doing wrong although I am sure it is something very simple.

// returns an array of strings from a text file; lines is the number of lines
char *file_array(int lines) 
{
    char text[50][150],buffer[150];

    int i=0;
    FILE *file_in;
    file_in=fopen("test.txt","r");

    if (file_in == NULL) {
        printf("Error opening file\n");
    }

    while (fgets(buffer,150,file_in)) {
        strcpy(text[i],buffer);
        i++;
    }

    fclose(file_in);
    return text;
}

int main()
{
    //totalLines is used to get the sizeof the array; this is the number of lines
    //in the text file
    int totalLines;
    totalLines = lines();   

    char *strings_from_file[totalLines];
    strings_from_file = file_array(totalLines);

    printf("index 2 of text file: %s",strings_from_file[2]);

    return 0;
}

I get this error when compiling

io.c:110:20: error: incompatible types when assigning to type ‘char *[(sizetype)(totalLines)]’ from type ‘char *’ strings_from_file = file_array(totalLines);
                ^
    fabio93@fabio93:~/Documents/c_apps/io_test$ gcc -o str_arr_file io.c 
    io.c: In function ‘file_array’:
    io.c:86:2: warning: return from incompatible pointer type [enabled by default]
      return text;
      ^
    io.c:86:2: warning: function returns address of local variable [-Wreturn-local-addr]
    io.c: In function ‘main’:
    io.c:110:20: error: incompatible types when assigning to type ‘char *[(sizetype)(totalLines)]’ from type ‘char *’ strings_from_file = file_array(totalLines);

I would consider myself a beginner in C, so please help me out. Thank you.

War es hilfreich?

Lösung

In your function, you create variable on stack which gets lost when function returns. So return text is undefined behaviour. Better way is to allocate space on heap using malloc and return that.

char **file_array(int lines) 
{
    char **text;
    text = malloc(sizeof(char*)*50);   //no of strings
    for(int i=0;i<50;i++)
        text[i] = malloc(sizeof(char)*150);  ..no of chars in each string


    //do things with text..you can use in same way as your example

    return text;
}

In your main program, use double pointer

char ** strings_from_file;
strings_from_file = file_array(totalLines);

Andere Tipps

If you have to work with double pointers through a function (passing a double pointer as parameter aka triple pointer!), here are some codes I wrote a very long time ago to address specifically that problem.

I hope it can be useful to those having trouble with double/triple pointers. Note that I'm working with integers, but the idea also applies to other types.


Double pointer via function (triple pointer)

I think the important things to note are the following syntaxes

  • how to declare int ***coco_a
  • how to allocate1 *coco_a = (int **) calloc(ROW, sizeof(int *));
  • how to allocate2 (*coco_a)[i] = (int *) calloc(COL, sizeof(int));
  • how to populate scanf("%d", &(*coco_a)[i][j]);

It took me a long time to realize that &(*coco_a) works and &*coco_a (or coco_a) does not work!

Here's the test code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ROW 2
#define COL 2

void aloca(int ***coco_a)
{   
    *coco_a = (int **) calloc(ROW, sizeof(int *));
    int i;
    for(i=0; i<ROW; ++i) {
        (*coco_a)[i] = (int *) calloc(COL, sizeof(int));
        int j;
        for(j=0; j<COL; ++j) {
            scanf("%d", &(*coco_a)[i][j]);
        }
    }
}

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

    int **coco_m;
    aloca(&coco_m);

    int i, j;
    /*for(i=0; i<ROW; ++i)
        for(j=0; j<COL; ++j)
            scanf("%d", &coco_m[i][j]);*/

    for(i=0; i<ROW; ++i)
        for(j=0; j<COL; ++j)
            printf("coco[%d][%d] = %d\n", i, j, coco_m[i][j]);

    return 0;
}

The following illustrates the usage of contiguous versus non-contiguous double pointers.

Contiguous versus non-contiguous allocation

#include <stdlib.h>
#include <stdio.h>

#define ROW 2
#define COL 3


int main(void)
{
    int i, j, val = 0;

    /* Allocation and assignment */
    int **doub_pointer = (int **) calloc(ROW, sizeof(int *));
    printf("\ndoub_pointer        = %d\n", doub_pointer);        

    for(i=0; i < ROW; ++i) {
            doub_pointer[i] = (int *) calloc(COL, sizeof(int));
            if(i == 0) printf("*doub_pointer       = %d\n", *doub_pointer);
            for(j=0; j < COL; ++j) {
                    doub_pointer[i][j] = val++;
                    printf("&doub_pointer[%d][%d] = %d\n", i, j, &doub_pointer[i][j]);
            }
    }

    /* Printing */
    for(i=0; i < ROW; ++i) {
            for(j=0; j < COL; ++j){
                    printf("doub_pointer[%d][%d] = %d\n", i, j, doub_pointer[i][j]);
            }
    }
    printf("sizeof(doub_pointer)    = %d\n", sizeof(doub_pointer)/sizeof(int));
    printf("sizeof(doub_pointer[0]) = %d\n", sizeof(doub_pointer[0])/sizeof(int));

    /* Freeing */
    for(i=0; i < ROW; ++i) free(doub_pointer[i]);
    free(doub_pointer);

    /*******************************************************************/

    val = 0;

    /* Allocation and assignment */
    int (*pointer)[COL] = (int (*)[COL]) calloc(ROW, sizeof(int [COL]));
    printf("\npointer        = %d\n", pointer);

    for(i=0; i < ROW; ++i) {
            for(j=0; j < COL; ++j){
                    pointer[i][j] = val++;
                    printf("&pointer[%d][%d] = %d\n", i, j, &pointer[i][j]);
            }
    }

    /* Printing */
    for(i=0; i < ROW; ++i) {
            for(j=0; j < COL; ++j){
                    printf("pointer[%d][%d] = %d\n", i, j, pointer[i][j]);
            }
    }
    printf("sizeof(pointer)    = %d\n", sizeof(pointer)/sizeof(int));
    printf("sizeof(pointer[0]) = %d\n", sizeof(pointer[0])/sizeof(int));

    /* Freeing */
    free(pointer);        

    /*******************************************************************/

    int true_2D[ROW][COL];
    printf("\nsizeof(true_2D)     = %d\n", sizeof(true_2D)/sizeof(int));

    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top