如何在C语言的函数中修改字符串数组

ee7vknir  于 2023-01-12  发布在  其他
关注(0)|答案(3)|浏览(155)

在其他语言中,我很难尝试一些超级简单的东西,但在C语言中,我得到了一个练习,它是这样的:
编写一个接收字符串数组的函数,并根据用户输入修改它。
我的代码到目前为止:

#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;
    }
}

这是错误的,正如@Eugene Sh所说:
newVal是函数的局部数组,函数返回后,genes将是悬空指针的数组:

genes[i] = newVal;

问题是我不能像invalid那样使用strcpy。我怎么才能让这个东西工作呢?

ugmeyewa

ugmeyewa1#

问题:

  • 字符串常量的指针不指向可修改内存,它们是只读的。
  • 不能从函数返回指向局部数组的指针。
  • 您需要使用strcpy或等效命令复制字符串。

挽救现有代码的最简单方法可能是使用strdup函数,该函数本质上是malloc + strcpy的组合。
strdup在编写时还不是标准的C语言,但将在今年晚些时候的C23发行版中出现。目前,您应该能够在string.h中找到它,除非您使用严格的编译器设置进行编译。)

#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
    }
}
holgip5t

holgip5t2#

您可以通过编辑代码的几个部分来实现这一点。

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

[]*运算符的优先级高于(),因此它表示指向10个字符数组的指针。

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

还有这个

fillGenes(&genes);

改为:

fillGenes(genes);

删除&,因为它已经是一个数组。
我还建议将scanf换成fgets
您可以通过删除以下内容来实现此目的:

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

加上这个

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

oxf4rvwz3#

有几种方法可以做到这一点。其中一种方法是:

#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;
}

通过分配内存并将newVal的内容复制到数组中,可以避免指针全部指向newVal的错误。

相关问题