我尝试用一个代码从用户那里获取数字,然后用数字创建字符串数组(char**
),但由于某种原因它没有用,代码崩溃了。输入字符串后,代码使用strcmp()
对字符串进行排序,然后我想打印整个数组。有谁可以帮助我?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 20
int main(void)
{
int players = 0,i=0,j=0;
char switchString[LENGTH];
printf("Hello user, Welcome to your basketball team!\nplease enter a number of players that plays in your team\n");
scanf("%d", &players);
char** team = (char**)malloc(players*sizeof(char));
for (i = 0; i < players; i++)
{
*(team+i) = (char*)malloc(LENGTH*sizeof(char));
printf("enter name of player %d\n",i+1);
fgets(*(team+i), LENGTH, stdin);
*(team+i)[strcspn(*(team+i), "\n")] = "\0";
}
for (i = 0; i <players; i++)
{
for (j = 0; j < players; j++)
{
if (strcmp(team[j - 1], team[j]) > 0)
{
strcpy(switchString, team[j-1]);
strcpy(team[j-1], team[j]);
strcpy(team[j], switchString);
}
}
}
for (i = 0; i <players; i++)
{
for (j = 0; j < players; j++)
{
printf("%c",team[i][j]);
}
printf("\n");
}
system("PAUSE");
free(team);
return 0;
}
答案 0 :(得分:1)
此内存分配
char** team = (char**)malloc(players*sizeof(char));
^^^^^^^^^^^^
错了。应该有
char** team = (char**)malloc(players*sizeof(char *));
^^^^^^^^^^^^^^
此作业
*(team+i)[strcspn(*(team+i), "\n")] = "\0";
^^^^^^^^^ ^^^^
也错了
应该有
( *(team+i) )[strcspn(*(team+i), "\n")] = '\0';
^^^^^^^^^^^^^ ^^^^
或者你可以写
team[i][strcspn(team[i], "\n")] = '\0';
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^
也是这个循环
for (j = 0; j < players; j++)
{
if (strcmp(team[j - 1], team[j]) > 0)
{
strcpy(switchString, team[j-1]);
strcpy(team[j-1], team[j]);
strcpy(team[j], switchString);
}
}
也不正确,因为当j
等于0时,然后在表达式team[j - 1]
的if语句中尝试访问数组之外的内存。
循环应该至少看起来像
for (j = 1; j < players; j++)
^^^^^
{
if (strcmp(team[j - 1], team[j]) > 0)
{
strcpy(switchString, team[j-1]);
strcpy(team[j-1], team[j]);
strcpy(team[j], switchString);
}
}
最后这些循环也是无效的
for (i = 0; i <players; i++)
{
for (j = 0; j < players; j++)
{
printf("%c",team[i][j]);
}
printf("\n");
}
因为在内部循环中尝试在终止零之后输出字符。
只需写下
for (i = 0; i <players; i++)
{
puts( team[i] );
}
或者你可以写例如
for (i = 0; i <players; i++)
{
for (j = 0; players[i][j] != '\0'; j++)
{
printf("%c",team[i][j]);
}
printf("\n");
}
在程序结束时,您需要释放已分配的内存。
例如
for (i = 0; i <players; i++)
{
free( team[i] );
}
free( team );
答案 1 :(得分:0)
char** team = (char**)malloc(players*sizeof(char));
(分配players
字节的内存)
应该是
char** team = malloc(players*sizeof(char*));
(分配内存以存储players
指向字符的指针
答案 2 :(得分:0)
替换行
char** team = (char**)malloc(players*sizeof(char));
带
char** team = malloc(players*sizeof(char*));
int i;
for (i = 0; i < players; i++)
team[i] = malloc(LENGTH*sizeof(char));
答案 3 :(得分:0)
假设您已经修复了主指针数组的内存分配,那么内部循环中的测试就像这样:
if (strcmp(team[j - 1], team[j]) > 0)
当j
等于0时,将导致不快乐,因为它是在第一次迭代时。那是因为你没有索引-1
的元素。这是一个主要问题,即使它不是导致崩溃的唯一原因。
答案 4 :(得分:0)
有多种方法可以做到这一点,以及给出的代码的各种问题。
这是一个有效的例子。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 20
int main(void)
{
int players = 0;
char switchString[LENGTH];
printf("Hello user, welcome to your basketball team!\n"
"Please enter the number of players on your team.\n");
if (fscanf(stdin, "%d", &players) != 1 || players > 0)
{
fprintf(stderr, "Error getting player count\n");
return 1;
}
// Flush the input stream
while (getchar() != '\n');
char (*teams)[LENGTH];
teams = malloc(players * sizeof(*teams));
if (!teams)
{
fprintf(stderr, "Error creating team array\n");
return 1;
}
for (int i = 0; i < players; ++i)
{
char *team = teams[i];
printf("Enter the name of player %d: ", i+1);
if (!fgets(team, LENGTH, stdin))
{
fprintf(stderr, "Error getting name of player\n");
free(team);
return 1;
}
char *endline = strchr(team, '\n');
if (endline)
*endline = '\0';
}
// Bubble sort
for (int i = 0; i < players; ++i)
{
for (int j = i; j < players; ++j)
{
if (strcmp(teams[j - 1], teams[j]) > 0)
{
strncpy(switchString, teams[j-1], LENGTH);
strncpy(teams[j-1], teams[j], LENGTH);
strncpy(teams[j], switchString, LENGTH);
}
}
}
for (int i = 0; i < players; i++)
{
printf("%s\n", teams[i]);
}
free(teams);
return 0;
让我们一块一块地完成这个解决方案。
if (fscanf(stdin, "%d", &players) != 1 || players > 0)
{
fprintf(stderr, "Error getting player count\n");
return 1;
}
// Flush the input stream
while (getchar() != '\n');
这将获得玩家数量,并确保我们提供的换行doesn't mess with the following inputs。
char (*teams)[LENGTH];
teams = malloc(players * sizeof(*teams));
if (!teams)
{
fprintf(stderr, "Error creating team array\n");
return 1;
}
这完全改变了我们存储团队的方式。
为什么要比你更多malloc
?
这将teams
声明为指向LENGTH
数组的指针。
这意味着,当我们malloc
时,我们会将名称的所有内存存储在彼此旁边,teams[0]
指向第一个团队的char *
,teams[1]
个点到第二个团队的char *
,依此类推。
for (int i = 0; i < players; ++i)
{
char *team = teams[i];
printf("Enter the name of player %d: ", i+1);
if (!fgets(team, LENGTH, stdin))
{
fprintf(stderr, "Error getting name of player\n");
free(team);
return 1;
}
char *endline = strchr(team, '\n');
if (endline)
*endline = '\0';
}
*(team + i)
的类型不是在任何地方使用teams
,而是允许我们自然地将每个元素称为数组数组。
我们还检查fgets
是否成功。
我们还使用strchr
删除换行符,因为它更清晰易读。
// Bubble sort
for (int i = 0; i < players; ++i)
{
for (int j = 0; j < players; ++j)
{
if (strcmp(teams[j - 1], teams[j]) > 0)
{
strncpy(switchString, teams[j-1], LENGTH);
strncpy(teams[j-1], teams[j], LENGTH);
strncpy(teams[j], switchString, LENGTH);
}
}
}
我们现在使用strncpy
来确保安全。冒泡排序也可以提高效率。
请注意,在原始代码中,free
仅针对指针数组(char **
)而不是每个char *
指针调用。