Hey Guys所以基本上我正在编写一个程序,在那里你提示用户他想要存储多少个名字。然后根据他的响应创建指针。之后,你提示他要向指针添加多少个名字。所以基本上我试图通过使用realloc来扩展相同的阵列,但我不确定我是否正确使用它(显然不是因为它不起作用) 基本上我希望用户已经输入的名字按原样保留,并且程序开始向用户询问他想要输入的下一个名字。例如,如果用户第一次输入数字2.然后他写了两个名字,然后要求再添加2个名字,程序应该保留前两个名字并准备存储在firstNames [2]。谢谢!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int amount;
//Asking user for number of records to input
printf("Please indicate the number of records you want to enter:");
scanf("%d", &amount);
printf("\n");
//Declaring dynamic array for first names
char **firstNames = (char**)malloc(amount * sizeof(char));
for (int i = 0; i < amount; i++)
{
firstNames[i] = (char*)malloc(1 * sizeof(char));
}
//Prompting user for first name, last name, and scores
for (int count = 0; count < amount; count++)
{
printf("Enter first name for user %d:", count + 1);
scanf("%s", firstNames[count]);
}
int add;
printf("How many users do you want to add now:");
scanf("%d", &add);
int sum = amount + add;
firstNames = (char**)realloc(firstNames, sum * sizeof(char));
for (int count = amount; count < sum; count++)
{
printf("Enter first name for user %d:", count + 1);
scanf("%s", firstNames[count]);
}
return 0;
}
答案 0 :(得分:2)
您有很多方面遇到麻烦。正如我原来的评论中所提到的,在担心重新分配之前,必须先正确分配内存。不是调用realloc
并将回报分配给firstNames
,而是创建临时指针以将realloc
的回报分配给更好。如果realloc
失败,则会返回NULL
。这意味着所有现有数据都将丢失,因为您刚刚分配了firstNames = NULL
。在将重新分配的空间分配给realloc
之前,使用临时指针可以测试firstNames
是否成功。
想到你的代码,还有其他几个方面可以改进。 始终初始化变量(零可以)。为什么?尝试从未初始化的变量中读取未定义的行为(错误)。您的输入例程至关重要。特别是使用scanf
和阅读int/char
数据。您必须确保在再次调用scanf
之前清空输入缓冲区,否则它将使用newline
(按[enter]
生成)作为下一个值,导致程序跳过后面的scanf
语句。您可以使用scanf
使用newline
来正确刷新输入缓冲区(stdin
),并谨慎选择format string
。
当您获得输入时验证它! Knucklehead用户将输入任何内容。
初始化pointer to pointers
时,通常最好使用calloc
进行初始分配,而不是malloc
。 calloc
将所有值初始化为(零),从而阻止从未初始化的变量中读取。
关于程序流程,您需要最小化循环次数并消除不必要的代码块。如果没有其他原因,减少错误的机会。仔细思考你的循环。当您的所有操作都可以在一个中进行时,您使用了多个循环来计算相同的数字。这不是一个敲门声,这只是一个帮助您简化代码的建议。
当您要求在重新分配之前输入多少用户时,如果输入0
会发生什么?你应该怎么处理?最好以您希望的方式检查和响应,而不是将其留给计算机认为可能未定义的内容。
这些是要点。我把这些想法纳入了一个例子。它总是可以改进,但我认为这将帮助您处理输入问题,并为您提供简化流程的示例。虽然没有必要,但我创建了几个函数来处理打印和释放内存。请记住,如果你分配内存,你有责任跟踪它并在完成后释放它。足够!这是一个例子。如果您有疑问,请告诉我。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void print_users (char **array, int sz); /* funciton to print users */
void free_memory (char **array, int sz); /* function to free memory */
int main (void)
{
int amount = 0; /* always intialize all variables */
int i = 0;
//Asking user for number of records to input
printf("\nEnter the number of records to enter: ");
scanf("%d%*c", &amount); /* read int, discard newline */
printf("\n");
if (!amount) /* validate records to enter */
{
fprintf (stderr, "\nerror: invalid input.\n\n"); /* if realloc fails, error and exit */
return 1;
}
//Declaring dynamic array for first names
char **firstNames = calloc (amount, sizeof (*firstNames)); /* using your variable for sizeof (x) */
for (i = 0; i < amount; i++) /* prevents mistaken sizeof (wrong) */
{ /* calloc initializes to NULL (zero) */
firstNames[i] = malloc (sizeof (**firstNames)); /* same for malloc */
//Prompting user for first name, last name, and scores
printf (" first name for user %d : ", i + 1);
scanf ("%m[^\n]%*c", &firstNames[i]); /* read string and newline (discarded) */
}
int add = 0;
printf ("\nAny *additional* users to add: ");
scanf ("%d%*c", &add); /* read int, discard newline */
printf ("\n");
if (!add)
{
print_users (firstNames, amount);
free_memory (firstNames, amount);
return 0;
}
int sum = amount + add;
char **tmp = NULL;
tmp = realloc (firstNames, sum * sizeof (*firstNames)); /* never realloc actual pointer to data */
/* if realloc fails pointer set to NULL */
if (!tmp) /* validate realloc succeeded */
{
fprintf (stderr, "\nerror: reallocation failed.\n\n"); /* if realloc fails, error and exit */
return 1;
}
firstNames = tmp; /* now assign to pointer */
for (i = amount; i < sum; i++) /* why new var count, use i */
{
firstNames[i] = malloc (sizeof (**firstNames)); /* allocate new Names, prompt & store */
printf (" first name for user %d : ", i + 1);
scanf ("%m[^\n]%*c", &firstNames[i]);
}
print_users (firstNames, sum);
free_memory (firstNames, sum);
return 0;
}
void print_users (char **array, int sz)
{
printf ("\nUsers firstNames:\n\n"); /* output users collecte in firstNames */
int i = 0;
for (i = 0; i < sz; i++)
printf (" user[%d] %s\n", i, array[i]);
}
void free_memory (char **array, int sz)
{
int i = 0;
for (i = 0; i < sz; i++) /* free allocated memory */
if (array[i])
free (array[i]);
if (array)
free (array);
}
使用示例:
$ ./bin/reallocptr
Enter the number of records to enter: 2
first name for user 1 : Jack
first name for user 2 : Jill
Any *additional* users to add: 2
first name for user 3 : Mike
first name for user 4 : Moe
Users firstNames:
user[0] Jack
user[1] Jill
user[2] Mike
user[3] Moe
注意:请参阅下面的附录,否则4-bytes
内存将在退出时保持未释放状态。
<强>附录强>
正如所指出的,只有一个char分配给每个firstName[i]
指针,这些指针不足以分配完整的字符串。通常,实际上firstName[i]
字符串分配可以使用strdup
或scanf
等具有适当format string
的函数自动处理。要使用scanf
完全处理字符串,需要进行以下更改:
//Declaring dynamic array for first names
char **firstNames = calloc (amount, sizeof (*firstNames)); /* using your variable for sizeof (x) */
for (i = 0; i < amount; i++) /* prevents mistaken sizeof (wrong) */
{ /* calloc initializes to NULL (zero) */
// firstNames[i] = malloc (sizeof (**firstNames)); /* let scanf auto-allocate */
//Prompting user for first name, last name, and scores
printf (" first name for user %d : ", i + 1);
scanf ("%m[^\n]%*c", &firstNames[i]); /* read string and newline (discarded) */
}
...
for (i = amount; i < sum; i++) /* why new var count, use i */
{
// firstNames[i] = malloc (sizeof (**firstNames)); /* allocate new Names, prompt & store */
printf (" first name for user %d : ", i + 1);
scanf ("%m[^\n]%*c", &firstNames[i]);
}
更改为free_memory()
void free_memory (char **array, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
if (array[i])
free (array[i]);
if (array)
free (array);
}
<强>输出/验证强>
Enter the number of records to enter: 2
first name for user 1 : Jack
first name for user 2 : Jill
Any *additional* users to add: 2
first name for user 3 : Larry
first name for user 4 : Moe
Users firstNames:
user[0] Jack
user[1] Jill
user[2] Larry
user[3] Moe
==13690==
==13690== HEAP SUMMARY:
==13690== in use at exit: 0 bytes in 0 blocks
==13690== total heap usage: 10 allocs, 10 frees, 468 bytes allocated
==13690==
==13690== All heap blocks were freed -- no leaks are possible
答案 1 :(得分:1)
char **firstNames = (char**)malloc(amount * sizeof(char));
这是一个双指针,需要为指向您信息的指针分配内存。
所以它应该是
char **firstNames = malloc(amount * sizeof(char *));/* No need to cast malloc() */
稍后你正在为这个内存做realloc()
,你需要处理realloc()失败。所以使用临时指针来存储realloc()
的返回值并分配地址回到firstNames
。
firstNames[i] = (char*)malloc(1 * sizeof(char));
你在每次迭代中分配一个字节,以便读取你需要更多内存的字符串。
答案 2 :(得分:1)
内存分配中的一些更正。
#define SIZE 10
char **firstNames = malloc(amount * sizeof(char *));
for (i = 0; i < amount; i++)
{
firstNames[i] = malloc(SIZE * sizeof(char));
}
首先malloc
为您要存储的条目分配内存
由于条目是指向另一个内存的指针,因此请使用malloc(amount * sizeof(char *))
第二个malloc
只是为你要存储的实际字符串分配内存
其中SIZE
是每个条目的字节数。
现在您想要添加更多用户,因此您使用realloc
。
int sum = amount + add;
firstNames = realloc(firstNames, sum * sizeof(char *));
/* Add the following to your code */
for (i = amount; i < sum; i++)
firstNames[i] = malloc(SIZE * sizeof(char));
printf("Total Names: \n");
for ( i = 0; i < sum; i++)
printf("%s\n", firstNames[i]);
这里第二个malloc
用于为新添加的用户分配内存
它从(i = amount)
开始,因为已经分配了amount
内存。