我的问题非常简单,但我真的不知道如何在C
中操纵字符串问题是: 我有一个名为person的结构
struct person
{
char name[25] // use char *name better?
}p;
我还有一个名为p *addNewPerson(char *name)
p *addNewPerson(char *name)
{
p *newPerson = (p *)malloc(sizeof(person));
//here how can I assign the name to this new person?
...
return newPerson;
}
所以,在主要功能
中void main()
{
for(; ;)
{
char input[25];
scanf("%s", input); // is this way possible?
//shoud I do something with this "input", like input[strlen(input)-1] = '\0'
//call addNewPerson()
p *newPerson = addNewPerson(&input);
//store this newPerson in some data structure
...
}
}
澄清:问题是如何在p *addNewPerson(char *name)
内为此新人分配名称?
答案 0 :(得分:4)
p *newPerson = (p *)malloc(sizeof(person));
//here how can I assign the name to this new person?
你会这样做:
strcpy(p->name,name);
您还应将p
的使用更改为struct person
,因为p
不是类型,它是struct person
类型的全局可验证版本。将代码更改为:
struct person *addNewPerson(char *name)
{
struct person *newPerson = malloc(sizeof *newPerson);
//应该对此做点什么 “输入”,如输入[strlen(input)-1] =
不,scanf会为你终止字符串。
请注意,C中的字符串处理需要非常非常仔细地完成。
例如当您执行scanf("%s", input);
时,如果输入的姓名超过24个字符会怎样?
任何事情都可能发生。 scanf可能会溢出缓冲区,并且您会得到未定义的行为。你至少应该这样做:
int ret = scanf("%24s",buffer); //read max 24 chars, to make space for a final '\0'
if(ret == EOF) { //end of input reached.
break;
if(ret != 1) {
// for whatever reason, the conversion failed. exit, or alert the user, or whatever
}
同样在addNewPerson
的{{1}}内,strcpy可能会高兴地写过去
如果strcpy(p->name,name);
长于name
可以容纳的缓冲区,则为缓冲区。在这种特殊情况下,通过对scanf的上述修改,长度将始终为24或更小,因此它是安全的。但是一般都要非常清楚这一点。
对addNewPerson的调用应该直接传递p->name
的名称,当用作值时,数组的名称会衰减到指向该数组的第一个元素的指针;
buffer
由于 struct person *newPerson = addNewPerson(input);
是使用malloc()动态分配的,所以当你不再需要它时,请记得free()它。否则你会泄漏内存。
答案 1 :(得分:2)
你的代码中存在一个根本性的缺陷,没有人还没有接受,这值得注意。 p
不是类型,它是类型struct person
的变量声明。您的addNewPerson()
函数根本不起作用。要么适当地更改addNewPersion()
功能:
struct person *addNewPerson(char *name)
{
...
}
或定义类型p
:
typedef struct person { ... } p;
然后使用strcpy()
(相反,我建议改为strncpy()
),正如其他人所建议的那样。
struct person *addNewPerson(char *name)
{
struct person *newPerson = (struct person *)malloc(sizeof(struct person));
//strcpy(newPerson->name, name);
strncpy(newPerson->name, name, sizeof(newPerson->name)); //more safe
return newPerson;
}
答案 2 :(得分:1)
使用strcpy
复制字符串并将其存储在结构中:
strcpy(p->name, name);
另请记住检查字符串长度,使其适合name
而不会溢出。
答案 3 :(得分:1)
您可以通过name
分配sprintf(p->name, "%s", name);
成员,但是您应该警惕溢出25个字符的缓冲区。例如,您可以snprintf(p->name, 25, "%s", name);
在编写这个程序时你应该学到的最重要的事情是你malloc()需要的任何东西都是免费的()'d 。否则,您将导致内存泄漏。在main()的末尾,请确保free(newPerson);
。如果将结构成员更改为指针,则需要对其进行malloc,然后在适当的时候释放它。
答案 4 :(得分:0)
你可以通过两种方式做到这一点。
首先,如您所知,您可以将人员的成员name
从数组更改为指针。然后在addNewPerson中,你会这样做:
p *newPerson = (p *)malloc(sizeof(person));
p->name = name;
编辑:正如评论中所指出的,这本质上是坏的,你应该复制字节。我一直在参考计数土地上工作太久了。
否则,您需要将传入名称中的字节复制到struct数组中。我会这样使用strlcpy:
strlcpy(p->name, name, sizeof(p->name));
如果可用,否则使用:
strncpy(p->name, name, sizeof(p->name));
唯一的区别是,如果p->name
太长而无法容纳name
,则必须空终止p->name
。
答案 5 :(得分:0)
我宁愿调用方法constructPerson。这实际上是OOP术语中的构造函数
struct person
{
char *name; //can hold string of different sizes
}p;
p *addNewPerson(char *name)
{
p *newPerson = (p *)malloc(sizeof(person));
p->name= (char *) malloc(sizeof(char)*(strlen(name)+1));//don't forget to claim space for the '/0' character at the end of the string
strcpy(p->name,name);
return newPerson;
}
答案 6 :(得分:-1)
你不需要strcpy,你不需要malloc,你不需要sizeof等。如果在你的struct中使用char数组,例如:
typedef struct {
char name[25];
} Person;
main() {
Person person;
char name[25];
if( 1==scanf("%24s",name) )
person=*(Person*)name;
return 0;
}
或者如果您需要更多人:
main() {
Person person[2]={{"firstperson"}};
char name[25];
if( 1==scanf("%24s",name) )
person[1]=*(Person*)name;
puts( person[0].name );
puts( person[1].name );
return 0;
}