简体   繁体   中英

How to modify an array of strings in C inside a function

I'm having a really hard time trying something super simple in other languages. But in C I was given an exercise that says:

Write a function that receives an array of strings and modify it based on user input.

My code so far:

#include <stdio.h>
#define GEN 3
void fillGenes(char **);

int main() {
    char *genes[GEN] = {"Gen0", "Gen1", "Gen2"};
    
    for (int i = 0; i < 3; i++) {
       printf("%s\n", genes[i]);
    }
    fillGenes(genes);
    for (int i = 0; i < 3; i++) {
       printf("%s\n", genes[i]);
    }
    return 0;
}

void fillGenes(char **genes) {
    printf("Introduce the name of %d genes.\n", GEN);
    for(int i = 0; i < GEN; i++) {
        printf ("Name of gene %d\n", i);
        char newVal[10];
        scanf("%s", newVal);
        genes[i] = newVal;
    }
}

This is wrong, as stated by @Eugene Sh:
newVal is array local to the function, after the function is returned, genes will be an array of dangling pointer:

genes[i] = newVal;

The thing is that I cannot strcpy as it is invalid . How can I make this thing to work?

Problems:

  • Pointers at string literals do not point at modifiable memory, they are read-only.
  • You cannot return a pointer to a local array from a function.
  • You need to copy strings using strcpy or equivalent.

The easiest way to salvage the existing code might be to use the strdup function, which is essentially a combination of malloc + strcpy .

( strdup is at the time this is written not yet standard C, but will be later this year in the upcoming C23 release. For now you should be able to find it in string.h unless you compile with strict compiler settings.)

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

#define GEN 3
void fillGenes(char **);

int main() {
    char *genes[GEN] = // assign the pointers to read/writeable dynamic memory:
    { 
      strdup("Gen0"), 
      strdup("Gen1"), 
      strdup("Gen2")
    }; 
    
    for (int i = 0; i < 3; i++) {
       printf("%s\n", genes[i]);
    }
    fillGenes(genes);
    for (int i = 0; i < 3; i++) {
       printf("%s\n", genes[i]);
       free(genes[i]); // clean up when done using the data
    }
    return 0;
}

void fillGenes(char **genes) {
    printf("Introduce the name of %d genes.\n", GEN);
    for(int i = 0; i < GEN; i++) {
        printf ("Name of gene %d\n", i);
        char newVal[10];
        scanf("%s", newVal);

        free(genes[i]); // clean up not to create a memory leak
        genes[i] = strdup(newVal); // create a new read/writeable copy of the local string
    }
}

You could accomplish this by editing a few parts of your code.

void fillGenes(char *genes[GEN][10])

The [] and * operator have precedence over the () , so it means the pointer to an array of 10 char. Change it to this:

void fillGenes(char (*genes)[10])

And this:

fillGenes(&genes);

to this:

fillGenes(genes); 

remove the & since it's already an array.

I would also recommend switching out scanf with fgets

You could accomplish that by removing this:

scanf("%s", genes[i]);

and adding this:

fgets(genes[i], 10, stdin);

There are a few ways to accomplish this. One of the ways is this:

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

#define GEN 3
void fillGenes(char **);
void fillGenes(char **genes) {
    printf("Introduce the name of %d genes.\n", GEN);
    for(int i = 0; i < GEN; i++) {
        printf ("Name of gene %d\n", i);
        char newVal[10];
        scanf("%s", newVal);
        genes[i]=calloc(100, 1);
        strcpy(genes[i], newVal); 
    }
}
int main() {
    char *genes[GEN] = {"Gen0", "Gen1", "Gen2"};
    
    for (int i = 0; i < 3; i++) {
       printf("%s\n", genes[i]);
    }
    fillGenes(genes);
    for (int i = 0; i < 3; i++) {
       printf("%s\n", genes[i]);
    }
    return 0;
}

By allocating memory and copying the contents of newVal to your array, you avoid making the mistake of having your pointers all point to newVal instead.

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