在我的代码中,我试图从用户获取字符串作为输入,并将它们存储在指针数组中。但是,我的代码只在指针数组的所有元素中存储最后输入的字符串。我需要做什么修改?
我的代码是:
#include <stdio.h>
#include <string.h>
void main()
{
char *names[ 4 ], name[ 10 ];
for ( int i = 0; i < 4; i++ ) {
printf( "Enter your name: " );
scanf( "%s", name );
names[ i ] = name;
}
for ( int i = 0; i < 4; i++ )
printf( "n* %s", names[ i ] );
}
输出为:
输入你的名字:Anna输入你的名字:米其林输入你的名字:史蒂文输入您的名字:Jacob
雅各雅各雅各雅各
浅Vs深拷贝:
给定两个指针p和q,语句:p = q;
不会将q
指向的内存的内容复制到p
指向的内存的内容。它复制指针值,这样p
和q
现在都指向相同的内存,并且当使用q
时,通过p
对内存的任何更改都会反映出来。这被称为浅拷贝。
char *names[ 4 ];
声明了一个包含4个指向char
指针的数组。注意,这只是为指针分配内存。
然后,在循环中:
for ( int i = 0; i < 4; i++ ) {
printf( "Enter your name: " );
scanf( "%s", name );
names[ i ] = name;
}
将缓冲区name
的地址分配给数组中的每个指针。
问题:最后一次迭代后name
的内容是什么?
答:雅各。
在内存中,它看起来像这样:names[0] ----
|
names[1] ----
|----> address of ```name```
names[2] ----
|
names[3] ----
解引用并打印这些指针的内容,然后每次打印Jacob
。
可能的修复:
按照注释的建议使用二维数组
使用
malloc
为字符串分配内存,并将其地址分配给指针。然后,您可以使用strcpy
或POSIX的strdup
将缓冲区name
的内容复制到每个指针指向的内存区域(这被称为深度复制)。
注意:strdup
使用malloc
为字符串分配内存,所以不要忘记free
它。
strdup()函数返回一个指向新字符串的指针字符串s的副本。新字符串的内存为通过malloc(3)获得,可以通过free(3)释放。(Linux的手册页)
main()
定义错误
从C11:
程序启动时调用的函数命名为main。的实现没有为这个函数声明原型。应该是用int返回类型定义不带参数:
int main (void)
{ /* ... */ }
或带两个形参(这里称为Argc和argv,尽管可以使用任何名称,因为它们是本地的函数中声明它们):
int main (int argc, char *argv[])
{ /* ... */ }
或同等学历;或者以其他实现定义的方式。
缓冲区溢出漏洞:
scanf("%s", name);
等价于:
gets(name);
它将愉快地继续读取输入并溢出缓冲区。
可以考虑使用fgets
:
fgets (name, sizeof (name), stdin);
fgets
最多读取n - 1
个字符,并以null结束字符串。
或者使用scanf
:
scanf("%9s", name);