将字符串输入到结构数组的char指针成员

时间:2017-11-17 17:37:54

标签: c arrays struct

我正在尝试将一串字符输入到结构数组的char类型的指针成员中。程序在收到 emp [0] 的成员 name 的字符串后终止。我的代码:

#include<stdio.h>
struct Employee
{
    char *name;
    int salary;
};

int main()
{
    struct Employee emp[3];

    int i;
    for(i=0;i<3;i++)
    {
        scanf("%s%d",emp[i].name,&emp[i].salary);
    }
    printf("\nOutput:");
    for(i=0;i<3;i++)
    {
        printf("\n%s%d",emp[i].name,emp[i].salary);
    }

    return 0;
}

当没有数组时,某些变量emp的以下代码正常工作:

scanf("%s%d",emp.name,&emp.salary);

有什么建议吗?提前谢谢。

4 个答案:

答案 0 :(得分:2)

name中的struct Employee字段是指针。你永远不会给该指针赋值,但是你将它传递给scanf然后试图取消引用它。取消引用未初始化的指针会调用undefined behavior

不要将char *用于name,而是将其设为足够大的数组,以容纳您期望的任何值:

struct Employee
{
    char name[50];
    int salary;
};

答案 1 :(得分:2)

您需要初始化char指针name,然后才能将其指向用户输入的String

#include<stdio.h>
struct Employee
{
    char *name;
    int salary;
};

int main()
{
    struct Employee emp[3];

    int i;
    for(i=0;i<3;i++)
    {
        emp[i].name = (char*)malloc(3);
        scanf("%s%d",emp[i].name,&emp[i].salary);
    }
    printf("\nOutput:");
    for(i=0;i<3;i++)
    {
        printf("\n%s%d",emp[i].name,emp[i].salary);
    }

    return 0;
}

答案 2 :(得分:1)

或者您可以在将name传递给scanf之前将其分配给emp[i].name = malloc(sizeof*emp[i].name*MAX_LEN); if( !emp[i].name ) // error in malloc.

scanf

您的代码中会发生什么?

name尝试将读取的字符写入name包含的地址。 if包含的地址是不确定的(一些垃圾值)。访问它会调用未定义的行为。

当没有数组时,某些变量emp的以下代码正常工作!

它有效,但它是一种未定义的行为。下次运行相同的代码时,可能会抛出错误。

malloc后的malloc是什么?

如果NULL无法提供所请求的内存,则返回malloc。您正在检查以确保分配内存,否则您将无法访问它,因为它会调用未定义的行为。

还有什么吗?

是的,除了这一切之外还有几件事情

  • 不要投放free()的返回类型。这是不必要的。
  • 完成后,释放动态分配的内存。 (使用scanf)。
  • 检查scanf返回值以确定name[4]调用是否成功。

回复用户的评论:

  

如果你有scanf("%3s",emp[i].name)内部结构,那么你应该写   3s。此scanf限制了所读取的字符数   3ex: SET varr=!varr:#=%23! 避免缓冲区溢出。如果你进入,那就是   超过3个字符,你将只读3个字符和其余的   它们将在输入流中。

注意:问题以 OR 开头,因为另一种方式是dbush回答的问题。我不想重复它。

答案 3 :(得分:0)

通过对其他好答案的改进很少,我想介绍这个版本。

  1. 我们必须始终检查malloc()的返回,以确保在堆上分配一些所需的内存位置成功或失败。 如果失败,任何尝试访问未分配的内存都会导致未定义的行为。
  2. 我们不得在C Why not cast return of malloc()中投放malloc()的返回类型,这是危险的,请参阅第一个答案。
  3. 使用#include <stdlib.h>时明确地
  4. malloc()
  5. <强> 代码

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Employee
    {
        char *name;
        int salary;
    };
    
    int main(){
    
    
    struct Employee emp[3];
    
    printf("Enter name, salary\n");
    
    int i;
    for(i=0;i<3;i++){
        emp[i].name = malloc(40*sizeof(char));
    
        if (emp[i].name != NULL){
                    scanf("%s %d", emp[i].name, &emp[i].salary);
                }else{
                        ///If this accur, try to access inside below for loop is UB
                        printf("Cant allocate Memory for name[%d]\n", i);
                }
    }
    
    printf("\nOutput:\n");
    for(i=0;i<3;i++)
    {
        printf("%s: %d\n", emp[i].name, emp[i].salary);
    }
    
    ///Free allocated memory 
    printf("Free allocated memory\n");
    for(i=0;i<3;i++)
    {
        free(emp[i].name);
    }
    
    return 0;
    }
    

    编译并运行

    gcc -Wall so.c -o so && ./so

    <强> [提示]

    您必须在名称和工资整数之间插入空格或按Enter键。 虽然这有效,但我建议将每个部分的scanf()分开以获得用户输入的名称对,每个部分后使用命中输入键的工资,这是可读的,我认为

        scanf("%s", emp[i].name);
        scanf("%d", &emp[i].salary);
    

    [<强> 备注

    1. 尝试avoid using scanf()。感谢@Jonathan Leffler提供此链接,我窃取了from

    2. 我建议您查看scanf() leaves the new line char in the buffer,在" %c"

    3. 内扫描字符scanf()时留下前导空格
    4. malloc() documentation

    5. <强> [待办事项]

      1. "%c""%d"scanf()之间可能相似的一些研究 扫描行为,删除缓冲区。
      2. 提供一些解释,关于Heap,Stack的链接。