我正在尝试将一串字符输入到结构数组的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);
有什么建议吗?提前谢谢。
答案 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
包含的地址是不确定的(一些垃圾值)。访问它会调用未定义的行为。
它有效,但它是一种未定义的行为。下次运行相同的代码时,可能会抛出错误。
malloc
后的malloc
是什么?如果NULL
无法提供所请求的内存,则返回malloc
。您正在检查以确保分配内存,否则您将无法访问它,因为它会调用未定义的行为。
是的,除了这一切之外还有几件事情
free()
的返回类型。这是不必要的。scanf
)。scanf
返回值以确定name[4]
调用是否成功。 回复用户的评论:
如果你有
scanf("%3s",emp[i].name)
内部结构,那么你应该写3s
。此scanf
限制了所读取的字符数3
到ex: SET varr=!varr:#=%23!
避免缓冲区溢出。如果你进入,那就是 超过3个字符,你将只读3个字符和其余的 它们将在输入流中。
注意:问题以 OR 开头,因为另一种方式是dbush回答的问题。我不想重复它。
答案 3 :(得分:0)
通过对其他好答案的改进很少,我想介绍这个版本。
malloc()
的返回,以确保在堆上分配一些所需的内存位置成功或失败。
如果失败,任何尝试访问未分配的内存都会导致未定义的行为。malloc()
的返回类型,这是危险的,请参阅第一个答案。#include <stdlib.h>
时明确地malloc()
。<强> 代码 强>
#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);
[<强> 备注 强>
尝试avoid using scanf()
。感谢@Jonathan Leffler提供此链接,我窃取了from
我建议您查看scanf() leaves the new line char in the buffer,在" %c"
scanf()
时留下前导空格
<强> [待办事项] 强>
"%c"
中"%d"
,scanf()
之间可能相似的一些研究
扫描行为,删除缓冲区。