简体   繁体   中英

Unable to print string from 2D array in struct?

I'm from the Python/JS world, so I'm having issues wrapping my head around strings and arrays in C.

I'm attempting to create a struct -- FileInfo -- which contains a 2D array so that I can store a number of email addresses. I have a function -- createFileInfo() -- which creates the struct, manages memory for the struct and array indexes, assigns an email address to the array, and returns a pointer to the struct:

typedef struct FileInfo {
    char **emailArr;

} FileInfo;

FileInfo *createFileInfo(int count) {
    FileInfo *fi = malloc(sizeof(FileInfo));

    char *buffer;
    char *emailPrefix = "test";
    char *emailDomain = "@test.com";

    for (int i=0; i<count; ++i) {
        fi->emailArr[i] = malloc(count * sizeof(char));
    }

    snprintf(buffer, sizeof(char), "%s%s", emailPrefix, emailDomain);

    for (int i=0; i<count; ++i) {
        for(int j=0; j<count; ++j) {
            fi->emailArr[i][j] = *buffer;
        }
    }

    return fi;
}

Then, in my main() function, I'm trying to create a pointer to the struct and print the index that contains the email address. However, I cannot get the string to print.

int main() {
    int count = 1;
    FileInfo *fi = createFileInfo(count);

    for (int i=0; i<count; ++i) {
        for(int j=0; j<count; ++j) {
            fprintf(stdout, "test %s\n", fi->emailArr[i][j]);
        }
    }

    for (int i=0; i<count; ++i) {
        free(fi->emailArr[i]);
    }

    free(fi);

    return 0;
}

What am I doing incorrectly? I'm also having quite the time with memory management; is memory allocation the issue?

In order to allocate a 2D dynamic array in C , you would need to do this instead, assuming that your 2D array is of dimensions N x M, where N is the number of emails, and M a number large enough to be able to store the email (that is something bigger than the length of the longest email to be stored, +1 for the C-string Null Terminator):

fi->emailArr = malloc( N*sizeof(char *) );
for(int i = 0 ; i < N ; i++)
  fi->emailArr[i] = malloc( M*sizeof(char) );

In your attempt you missed the dynamic allocation which is just before the for loop.


You should also allocate memory for your buffer pointer. Now you do:

char *buffer;
snprintf(buffer, sizeof(char), "%s%s", emailPrefix, emailDomain);

but buffer has no memory allocated for it, so no place to store the string. You could do this instead:

size_t email_len = strlen(emailPrefix) + strlen(emailDomain);
char *buffer = malloc(email_len + 1);   // +1 for the Null Terminator
snprintf(buffer, email_len, "%s%s", emailPrefix, emailDomain);

I also changed the call to populate the buffer, since the 2nd parameter of snprintf() , n , is the "Maximum number of bytes to be used in the buffer".


Putting everything together, a complete, minimal and basic example would look like this:

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

typedef struct FileInfo {
    char **emailArr;

} FileInfo;

FileInfo *createFileInfo(int count) {
    FileInfo *fi = malloc(sizeof(FileInfo));

    char *emailPrefix = "test";
    char *emailDomain = "@test.com";
    size_t email_len = strlen(emailPrefix) + strlen(emailDomain);
    char *buffer = malloc(email_len + 1);   // +1 for the Null Terminator
    snprintf(buffer, email_len + 1, "%s%s", emailPrefix, emailDomain);

    fi->emailArr = malloc( count * sizeof(char *) );
    for(int i = 0 ; i < count; i++)
        fi->emailArr[i] = malloc( (email_len + 1) * sizeof(char) );

    for(int i = 0 ; i < count; i++)
        strcpy(fi->emailArr[i], buffer);

    return fi;
}

int main(void) {
    int count = 1;
    FileInfo *fi = createFileInfo(count);

    for (int i = 0; i < count; ++i) {
        printf("%s\n", fi->emailArr[i]);
    }

    for (int i = 0; i < count; ++i) {
        free(fi->emailArr[i]);
    }
    free(fi);

    return 0;
}

Output:

test@test.com

Now of course, once you understand this piece of code, you could, if you like, think of how you would generalize this code to handle more emails than one.

  1. emailArr is not initialized. You should initialize it first:

f->emailArr = malloc(number_of_char_arrays * sizeof(char*))

  1. buffer is not initialized, too:

buffer = malloc(char_array_length * sizeof(char))

  1. About snprintf 's 2nd argument:

    Maximum number of bytes to be used in the buffer. The generated string has a length of at most n-1, leaving space for the additional >terminating null character. size_t is an unsigned integral type.

It should be at least 14 if you want it to copy emailPrefix and emailDomain to buffer .

  1. fprintf(stdout, "test %s\\n", fi->emailArr[i][j]);

fi->emailArr[i][j] is a single character. You should only use the first index if you want to print it by %s .

In the createFileInfo function you're effectively creating a count*count char array, which I doubt is what you want and with count = 1 it can't contain the string "test@test". You should be allocating the size of the string you want to store, not "count" chars.

    int size = 9; //this should probably be a parameter of the function
    for (int i=0; i<count; ++i) {
        fi->emailArr[i] = malloc(size * sizeof(char));
    }

And you should allocate emailArr itself first (more on this here )

   fi->emailArr = malloc(count * sizeof(char *));

You're also trying to copy the string in the wrong way; right now you're copying the pointer to buffer in each character of the string, which means each "string" is actually an array of pointers and cannot be printed as a string (I'm surprised it even compiles). It also means that if the content buffer points to changes, every element in your array will change. You need to use strncpy to do what you want.

    for (int i=0; i<count; ++i) {
        strncpy(fi->emailArr[i], buffer, size);
    }

You also forgot to allocate memory for buffer.

I suggest you try some simpler programs involving strings to familiarize yourself with pointer logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM