【问题标题】:C function to fill an array with strings from user inputC函数用用户输入的字符串填充数组
【发布时间】:2020-10-31 18:00:15
【问题描述】:

我被困在 C 中的编程作业上。用户必须输入一个数字,指定一个数组的大小,该数组的大小不超过 10 个元素,用于存储学生的姓名。这必须在名为 getNames 的主函数之外的单独函数中完成。每个名称最多可包含 14 个字符,并且必须从主函数中调用 getNames。这是我的代码:

#include <stdio.h> 

void getNames(char *a, int n){
    int i;
    for(i=0; i<n; i++){
        printf("Enter a name: ");
        scanf("%s", &a[i]);
    } 

}

void printNames(char *a, int n){
    int i;

    for(i=0; i<n; i++){
        printf("%s\n", &a[i]);
    }
}

void main(){
    int num; //number of names in array 'names'
    printf("Num of students: ");
    scanf("%d", &num);

    char names[num][15]; //each name is 14 characters plus
                         //a null character
    getNames(names[num], num);
    printNames(names[num], num);

}

代码编译并运行时没有语法错误,但数组未正确填充。例如:

Num of students: 5
Enter a name: Jeb
Enter a name: Bob
Enter a name: Bill
Enter a name: Val
Enter a name: Matt

返回:

JBBVMatt
BBVMatt
BVMatt
VMatt
Matt

显然写入数组时出现问题,但我不确定它是什么。

对于这个作业,我们的教授坚持我们不能使用任何全局变量。关于我们应该如何实施这一点,他的措辞相当含糊。我的第一个想法是将 getNames 中的 for 循环移动到主函数中,然后重复调用 getNames,但我想要一个将其合并到 getNames 中的解决方案。我是 C 新手,主要处理 Java,所以请多多包涵。任何帮助将不胜感激。

【问题讨论】:

    标签: arrays c function


    【解决方案1】:

    如果您发布的代码正是您正在使用的代码,那么它通过访问您的程序不拥有的内存位置来调用undefined behaviorgetNames(names[num], num);
    C 中的数组索引从 0n-1。 (或来自names[0]-names[num-1])在其他类似的调用中相同。

    下一个问题是要适应的函数原型;

    char names[num][15];  
    

    函数需要发送数组数组的地址。查看代码编辑以显示差异。

    下期是以下语句,每个后见cmets

    getNames(names[num], num);//names[n] points to memory beyond what is owned.
                              //should point to address of beginning of memory &names[0]
    printNames(names[num], num);//ditto
    

    工作代码示例,请参阅编辑说明:

    //void getNames(char *a, int n){//change *a to either a[][15] or (*a)
    void getNames(char a[][15], int n){
        int i;
        for(i=0; i<n; i++){
            printf("Enter a name: ");
            scanf("%s", a[i]);
        } 
    
    }
    
     //void printNames(char *a, int n){ //change *a to either a[][15] or (*a)
     void printNames(char a[][15], int n){
        int i;
    
        for(i=0; i<n; i++){
            printf("%s\n", a[i]);
        }
    }
    
    void main(){
        int num; //number of names in array 'names'
        printf("Num of students: ");
        scanf("%d", &num);
    
        char names[num][15]; //each name is 14 characters plus
                             //a null character
        //getNames(names[num], num);//names[n] points to memory beyond what is owned.
        //printNames(names[num], num);//ditto
        getNames(&names[0], num);
        printNames(&names[0], num);
    
    }
    

    【讨论】:

    • 谢谢好心的陌生人!这对我来说很好。我非常感谢您的意见。我们甚至还没有讨论内存分配,所以这个任务感觉就像我在一个没有手电筒的山洞里。
    • 我会在参数中交换an,然后你可以写(假设是现代编译器)void getNames(int n, char a[n][15]) { .... },对于初学者来说可能更容易掌握。
    • @HAL9000 - 因为is no guarantee 函数参数以任何特定顺序被识别,所以它是未定义的。例如,如果在int n 之前调用getNames 时看到char a[n][15],那么n 将是未定义的。但否则,这将是一个好主意。谢谢
    • 是的,没有定义调用函数之前评估参数的顺序,但是一旦调用函数,所有的参数值都被定义。现代 c (AFAIK) 确实允许将函数参数中的整数参数用作另一个函数参数中的数组大小,但大小参数必须位于数组参数之前。
    • 一些额外的解释:getNames(int n, char a[n][15]) 中没有任何内容要求在a 之前计算n,只要an 存在之前没有被引用。在保证na 都存在的函数内部,这不会发生。
    【解决方案2】:

    你可以做以下

    1. 方法

    main函数调用如下

    getNames(names, num);
    printNames(names, num);
    

    并改变如下功能

    void getNames(char (*a)[15], int n) 
    {
       ...
    }
    
    void printNames(char (*a)[15], int n)
    {
       ...
    }
    
    1. 方法,在主调用中保持不变

    void getNames(char a[5][15], int n)

    void printNames(char a[5][15], int n)

    但与其使用硬值,不如使用#define 行和列大小

    【讨论】:

      猜你喜欢
      • 2021-02-10
      • 2015-05-22
      • 1970-01-01
      • 2012-12-02
      • 2015-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      相关资源
      最近更新 更多