C字符串问题

时间:2010-09-08 20:44:37

标签: c

我的问题非常简单,但我真的不知道如何在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)内为此新人分配名称?

7 个答案:

答案 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)

  1. 您可以通过name分配sprintf(p->name, "%s", name);成员,但是您应该警惕溢出25个字符的缓冲区。例如,您可以snprintf(p->name, 25, "%s", name);

  2. 在编写这个程序时你应该学到的最重要的事情是你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;
}