7.2.4 结构体与字符串
当结构体拥有字符指针类型的成员时,大家要时刻小心,保持清醒的头脑,不然很容易产生错误。例如,有一个关于学生的结构体 Stu,其定义语句如下:
可以看到,结构体 Stu 的第 2 个成员 name 被定义为 char 类型的指针,可以使用它来指向一个表示学生姓名的字符串。
下面,在主函数中来定义一个该结构体类型的结构体变量并对其进行初始化。例如:
struct Stu stu1 = {1, "Tom"};
结构体变量名为 stu1,其成员 num 被初始化为 1,成员 name 被初始化为字符串常量“Tom”的首地址。
由于成员 name 指向的是一个字符串常量,因此,不能通过指针来修改字符串的内容。例如,将学生的姓名“Tom”修改为“tom”,即将首字符从大写字母 T 修改为小写字母 t:
*stu1.name = 't';
通过指针的解引用,将所指向的字符修改为小写字母 t。由于“Tom”是一个字符串常量,因此这样的操作是不允许的,程序运行时会出现错误。
其实,解决这个问题很简单,让指针指向另外一个字符串常量就行了。例如:
stu1.name = "tom";
即将字符串常量“tom”的首地址赋值给成员 name。这并不是通过指针修改指向的对象,而只是对指针变量的重新赋值,即改变指针的指向。“Tom”与“tom”虽然只有一字之差,但却是两个不同的字符串常量,它们的内存空间和内存地址是不相同的。
但这样做也有不好的地方,首先是每次想修改字符串,都需要让指针指向一个新的字符串常量,有些麻烦。更为严重的是,无法根据用户的要求来修改字符串。因为字符串常量都是在程序编译前预先定义好的,在程序运行时,无法再定义字符串常量。
想要得到能修改的字符串,我们应该使用字符数组,只要让成员 name 指向字符数组的首地址就行了。
下面定义一个长度为 20 的字符数组 str,并将字符串常量“Tom”初始化给它。
char str[20] = "Tom";
接下来,让 stu1 的成员 name 指向字符数组 str。
stu1.name = str;
现在就可以通过成员 name 来直接修改它所指向的字符串了。例如:
*stu1.name = 't';
下面打印输出成员 name 所指向的字符串:
printf("Name: %s\n", stu1.name);
编译运行程序,结果如下:
Name: tom
可见,现在修改字符串没任何问题了,成功地将姓名修改为“tom”。
这样做也有一个需要注意的地方。例如,我们再定义一个结构体变量 stu2,并将其初始化为 stu1 的值:
struct Stu stu2 = stu1;
然后,通过 strcpy 函数将字符串常量“Jack”复制给 stu2 的成员 name 所指向的内存空间:
strcpy(stu2.name, "Jack");
现在分别打印 stu1 和 stu2 的成员 name 所指向的字符串:
printf("stu1 Name: %s\n", stu1.name); printf("stu2 Name: %s\n", stu2.name);
编译运行程序,结果如下:
stu1 Name: Jack stu2 Name: Jack
可见,两个结构体变量的成员 name 所指向的字符串都变为了“Jack”。原因是 stu1 和 stu2 的成员 name 所指向的是同一字符数组。因此,解决的办法,就是为它们各自设置不同的字符数组,即让不同的结构体变量成员 name 指向不同的字符数组空间。程序代码如下:
由于 stu1 的成员 name 指向的是字符数组 str1,而 stu2 的成员 name 指向的是字符数组 str2,因此,修改 stu2 的成员 name 所指向的字符数组 str2 时,不会影响到字符数组 str1。
编译运行程序,结果如下:
stu1 Name: Tom stu2 Name: Jack
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论