简体   繁体   English

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

[英]Input string to a char pointer member of an array of structure

I'm trying to input a string of characters to a pointer member of char type of an array of structure. 我正在尝试将字符串输入到结构数组的char类型的指针成员。 The program is terminating after it receives the string for the member name of emp[0] . 程序在收到成员名称emp [0]的字符串后终止。 My code: 我的代码:

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

When without array, the following code for some variable emp is working fine: 如果不使用数组,则以下用于某些变量emp代码可以正常工作:

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

Any suggestions? 有什么建议么? Thanks in advance. 提前致谢。

The name field in struct Employee is a pointer. struct Employeename字段是一个指针。 You never give that pointer a value, but you pass it to scanf which then attempts to dereference it. 您永远不会给该指针一个值,而是将其传递给scanf ,然后它尝试取消引用它。 Dereferencing an uninitialized pointer invokes undefined behavior . 取消引用未初始化的指针会调用未定义的行为

Instead of using a char * for name , make it an array large enough to hold whatever value you expect: 而不是使用char *作为name ,而是使它成为足以容纳您期望的任何值的数组:

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

You need to initialize char pointer name before can point it to a String entered by user. 您需要先初始化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;
}

Or you can allocate something to name before passing it to scanf . 或者,您可以先分配一些name然后再将其传递给scanf

emp[i].name = malloc(sizeof*emp[i].name*MAX_LEN);
if( !emp[i].name )
// error in malloc.

What happens in your code? 您的代码会怎样?

scanf tries to write the characters read to the address contained by name . scanf尝试将读取的字符写到name包含的地址中。 The address contained by name is indeterminate (some garbage value). name包含的地址不确定(某些垃圾值)。 Accessing it calls for undefined behavior. 访问它需要未定义的行为。

When without array, the following code for some variable emp is working fine! 如果不使用数组,则以下用于某些变量emp的代码可以正常工作!

It works but it is an undefined behavior. 它可以工作,但这是未定义的行为。 The very next time you run the same code it may throw error. 下次您运行相同的代码时,可能会引发错误。

What is that if after malloc ? ifmalloc之后是什么?

In case malloc fails to provide with the requested memory it returns NULL . 万一malloc无法提供所请求的内存,它将返回NULL You are checking that to be sure that memory is allocated otherwise you won't access it because it invokes undefined behavior. 您正在检查以确保已分配内存,否则将无法访问它,因为它会调用未定义的行为。

Is there anything else?? 还有别的事吗??

yes there are couple of things apart from all this 是的,除了这一切,还有几件事

  • Don't cast the return type of malloc . 不要转换malloc的返回类型。 It's unnecessary. 没必要
  • Free the dynamically allocated memory after you are done working with it. 使用完动态分配的内存后,请释放它。 (using free() ). (使用free() )。
  • Check the scanf return value to be sure about whether the scanf call succedes. 检查scanf返回值,以确保scanf调用是否成功。

Reply to user's comment: 回复用户评论:

If you have name[4] inside struct then you should write scanf("%3s",emp[i].name) . 如果在struct中有name[4] ,则应编写scanf("%3s",emp[i].name) This 3s limits the characters read by scanf to 3 avoiding buffer overflow. 3sscanf读取的字符限制为3避免缓冲区溢出。 The thing is if you enter more than 3 characters you will read only 3 characters and rest of them will be in input stream. 关键是,如果您输入的字符数超过3个,则您只会读取3个字符,其余字符将出现在输入流中。

Note: The question starts with an OR because the other way is what is answered by dbush. 注意:问题以OR开头,因为另一种方法是dbush回答的问题。 I didn't want to repeat it. 我不想重复。

By little improvement on others good answers, I want to introduce this version. 通过对其他好的答案进行一点改进,我想介绍这个版本。

  1. We must always check return of malloc() to ensure success or its failure on allocate some desired memory location(s) on the Heap. 我们必须始终检查malloc()返回,以确保在堆上分配某些所需的内存位置时成功或失败。 If it fails, any try to access that unallocated memory cause Undefined Behavior. 如果失败,则任何尝试访问该未分配内存的操作都会导致未定义行为。
  2. We must not cast return type of malloc() in C Why not cast return of malloc() its dangerous, see first answer. 我们一定不要在C中malloc()返回类型。 为什么不强制转换malloc()的返回是危险的,请参阅第一个答案。
  3. #include <stdlib.h> explicitly when using malloc() . 使用malloc()时显式#include <stdlib.h>

Code

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

Compile and Run 编译并运行

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

[Hint] [暗示]

You must insert an space or hit enter, between Name and salary integer. 您必须在姓名和工资整数之间插入一个空格或按Enter键。 Although this works but i recommend to separate scanf() for each section to get user input for pair of name, salary with hit enter key after each, this is readable, i think . 尽管这可行,但是我建议为每个部分单独分配scanf()以获得用户输入的姓名,薪金,然后按回车键,这是可读的, 我认为

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

[ Notes ] [ 注意事项 ]

  1. Try to avoid using scanf() . 尝试避免使用scanf() Thanks for @Jonathan Leffler for providing this link that i steal from 感谢@Jonathan Leffler提供了我其中窃取的链接

  2. I recommend to take a look at scanf() leaves the new line char in the buffer , leaving a leading space when scan character " %c" inside scanf() 我建议看看scanf()将新行char留在缓冲区中 ,当scanf()扫描字符" %c"留一个前导空格

  3. malloc() documentation malloc()文档

[ToDo] [去做]

  1. Some Research on possible similarity between "%c" , "%d" in scanf() behavior in scanning, remove buffer. scanf()行为中的"%c""%d"之间的相似性进行一些研究,删除缓冲区。
  2. provide some explain, links on Heap, Stack. 提供一些解释,有关堆,堆栈的链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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