C 如何按值而非引用添加字符串
我正在用C语言制作一个非常简单的TODOlist 我的add函数使用C 如何按值而非引用添加字符串,c,arrays,string,pointers,strcpy,C,Arrays,String,Pointers,Strcpy,我正在用C语言制作一个非常简单的TODOlist 我的add函数使用char*作为参数。当我将它添加到我的char**提醒列表时,它会添加缓冲区的内存地址,而不是字符串的值 当我运行下面给定的源代码时,问题变得很明显 如果您尝试[a]添加一个字符串,说“Test”,然后发出[p]rint命令,将打印一个“p” 我知道这是因为我的列表[0]中有一个指向我的缓冲区的指针,所以当缓冲区的值发生变化时,我列表中的值也会发生变化 我的C已经生锈了,我知道strcpy()可以解决这个问题吗?但这是通常的处理
char*
作为参数。当我将它添加到我的char**
提醒列表时,它会添加缓冲区的内存地址,而不是字符串的值
当我运行下面给定的源代码时,问题变得很明显
如果您尝试[a]添加一个字符串,说“Test”,然后发出[p]rint命令,将打印一个“p”
我知道这是因为我的列表[0]
中有一个指向我的缓冲区的指针,所以当缓冲区的值发生变化时,我列表中的值也会发生变化
我的C已经生锈了,我知道strcpy()
可以解决这个问题吗?但这是通常的处理方式吗
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int size = 0;
int capacity = 50;
char **list;
void initList() {
list = malloc( capacity * sizeof( char * ) );
for (int i = 0; i < capacity; i++ ) {
list[i] = malloc( 256 * sizeof( char ) );
}
}
void saveReminders() {
}
void add( char *reminder ) {
list[size++] = reminder;
}
void delete( int index ) {
}
void print() {
for ( int i = 0; i < size; i++ )
printf( "%s\n", list[i] );
}
void quit() {
saveReminders();
exit( 0 );
}
void readReminders() {
}
void helpMenu() {
printf( "Enter a command:\n" );
printf( "[a]dd a reminder\n" );
printf( "[d]elete a reminder\n" );
printf( "[p]rint all reminders\n" );
printf( "[q]uit\n" );
}
void menu() {
helpMenu();
while ( 1 ) {
char buffer[64];
int index = 0;
printf( "> " );
scanf( "%s", buffer );
if ( strcmp( buffer, "a" ) == 0 ) {
printf( "Enter a reminder:\n> " );
scanf( "%s", buffer );
add( buffer );
helpMenu();
}else if ( strcmp( buffer, "d" ) == 0 ) {
printf("Remove which index?\n> " );
scanf( "%d", &index );
delete( index );
helpMenu();
}else if ( strcmp( buffer, "p" ) == 0 ) {
print();
helpMenu();
}else if ( strcmp( buffer, "q" ) == 0 ) {
quit();
}
}
}
int main( int argc, char* argv[] ) {
initList();
menu();
}
#包括
#包括
#包括
int size=0;
国际通行能力=50;
字符**列表;
void initList(){
列表=malloc(容量*sizeof(字符*);
对于(int i=0;i”);
scanf(“%s”,缓冲区);
if(strcmp(缓冲器,“a”)==0){
printf(“输入提醒:\n>”;
scanf(“%s”,缓冲区);
添加(缓冲区);
帮助菜单();
}else if(strcmp(缓冲区,“d”)==0){
printf(“删除哪个索引?\n>”;
scanf(“%d”和索引);
删除(索引);
帮助菜单();
}else if(strcmp(缓冲区,“p”)==0){
打印();
帮助菜单();
}else if(strcmp(缓冲区,“q”)==0){
退出();
}
}
}
int main(int argc,char*argv[]){
initList();
菜单();
}
是的,你认为这是对的。在代码中,不要指定指针本身,而是执行以下操作
strcpy(list[size++], reminder);
复制内容。有关参考信息,请参阅
如果您想使用第二种方法,您也不需要为每个列表[i]
使用malloc()
。您可以直接使用返回值并将其分配给每个列表[i]
,而不是使用malloc()
然后再使用strcpy()
也就是说,还有一些需要注意的问题
- 在使用
list[size++]
之前,请确保size
小于容量
,否则您将导致分配的内存溢出,从而产生错误
scanf(“%s”,缓冲区)代码>应该是scanf(“%63s”,缓冲区)代码>以防止任何可能的缓冲区溢出
- 在使用返回的指针之前,请始终检查
malloc()
的返回值是否成功
sizeof(char)
在C标准中定义为1
。将其用作乘数是多余的
而不是:
list[size++] = reminder
使用
或者更好的是,在扫描时,记住写入的字符数,将其传递给add(),然后执行以下操作:
strncpy(list[size++], reminder, len)
您需要复制字符串;)我在想这个问题,但想知道这是否是解决这个问题最常用的方法?我想我只是在问是否每个人都这么做。。感谢OP在将内容分配给列表[size++]
@chqrlie Yes,fair point之前还应测试大小
。谢谢你的留言,我会在答案中加上<代码>strnpy
-->strncpy
,不,strncpy无论如何都不是更安全的strcpy版本。:)不要使用strncpy
,尤其是源字符串的长度作为额外参数<如果源字符串长于length参数,则code>strncpy不会'\0'
终止目标缓冲区。这个函数很容易出错。使用Sourav Gosh回答中的strdup()
方法。
strncpy(list[size++], reminder, len)