c - 创建动态分配的链表
问题描述
我正在尝试创建一个游戏,并且在用户进入游戏的某个时刻,将为该玩家创建一个结构。如果玩家输入其名称,游戏会提示玩家以下内容:
Type player name:> George
Choose one of the following Otions:
[+]1) to remove George from player List.
[+]0) to keep George.
玩家需要输入 3 个名称并决定是删除还是保留其中一个或全部。
我遇到的问题是,如果玩家决定从列表中删除一个或多个,我无法保留创建的(保留的)列表。
这是可以编译的程序的一部分:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PERCENT 5
#define LEFT "left"
#define RIGHT "Right"
struct node {
int player_ID;
struct node* prev;
struct node* next;
char move_player[256];
char player_name[ 31 ];
} node;
struct node *root;
struct node *current;
struct node *player_node( int player_ID, const char *player_name );
void delete_player ( void *player_list );
int main( void )
{
char name[256] = { 0 };
int i = 0, clean;
root = player_node( PERCENT, RIGHT );
current = root;
do{
struct node *player = player_node( PERCENT, LEFT );
player->prev = current;
current->next = player;
current = player;
printf( "Type player name:> ");
if ( fgets( name, 256, stdin ) == NULL )
{
printf("Error, fgets()\n");
exit( EXIT_FAILURE );
}
name[ strcspn( name, "\n" ) ] = '\0';
strncpy( player->player_name, name, strlen( name ) );
printf( "Choose one of the following Otions:\n" );
printf( "\t[+]1) to remove %s from player List.\n", current->player_name );
printf( "\t[+]0) to keep %s.\n", current->player_name );
int opt = 0;
if ( scanf( "%d", &opt) != 1 )
{
printf("Error, scanf()\n");
}else if ( opt == 1 )
{
delete_player ( player );
}
while ( ( clean = getchar() ) != '\n' && clean != EOF );
i++;
}while( i < 3 );
struct node *tmp = root->next;
while ( tmp != NULL )
{
printf( "Name = %s", tmp->player_name );
tmp = tmp->next;
}
free( root );
}
struct node *player_node( int player_ID, const char *const movement )
{
struct node *player = malloc( sizeof( struct node ) );
player->prev = NULL;
player->next = NULL;
player->player_ID = player_ID;
strncpy( player->move_player, movement, strlen( movement) );
strncpy( player->player_name, "NULL", 5 );
return player;
}
void delete_player ( void *player_list )
{
struct node *local_client = (struct node* )player_list;
if ( local_client == current )
{
current = local_client->prev;
current->next = NULL;
} else
{
local_client->prev->next = local_client->next;
local_client->next->prev = local_client->prev;
}
free( local_client );
}
如果代码达到这个:
struct node *tmp = root->next;
while ( tmp != NULL )
{
printf( "Name = %s", tmp->player_name );
}
列表中没有剩余玩家,因为列表没有打印出来。
为什么列表是空的?
解决方案
使用strcpy()
而不是strncpy()
. 后者并不比前者更安全。
改变:
strncpy(player->player_name, name, strlen( name ));
到:
strcpy(player->player_name, name);
对这个调用做同样的事情:
strncpy( player->move_player, movement, strlen( movement) );
因为在这两种情况下,您都没有复制 NULL 终止符。
然后,whenprintf()
或任何标准字符串函数处理您的字符串,它不知道何时停止......
您的问题的核心是[strlen()
] 3计算字符串的长度,而不考虑 NULL 终止符:
C 字符串的长度由终止空字符决定:AC 字符串与字符串开头和终止空字符之间的字符数一样长(不包括终止空字符本身)。
我也会strncpy( player->player_name, "NULL", 5 );
变成同质的。
如果必须使用strncpy()
,则只需在第三个参数中添加 1,如下所示:
strncpy(player->player_name, name, strlen( name ) + 1);
但是,请记住,strncpy()
在此代码中使用是没有意义的,只会降低可读性,因为它会增加复杂性并降低代码的简洁性。
推荐阅读
- javascript - 围绕一个点旋转,物体不断地走得更远
- eclipse - ld: 找不到 -lSystem 的库
- tensorflow - Tensorflow MNIST Sequential - ValueError:层顺序的输入0与层不兼容:输入形状的预期轴-1具有
- swift - 沿着我的 gps 位置路径添加多边形的更好方法?
- azure - 将 Kusto Explorer 连接到 Log Analytics
- node.js - 更改主题标签的文本输入颜色反应原生 mobx
- python - 海运折线图样式导致重复的图例条目
- r - 年度数据的圆形图
- visual-studio-code - 如何关闭 Markdown 文件的 VS Code 自动格式化?
- python-3.x - 如何删除字典 pandas env 列表中的键/值对