动态数组添加元素后打印乱码
Dynamic array prints garbage after adding elements
我已经查看我的代码几个小时了,但我就是不明白为什么它不起作用。该程序使用动态数组创建购物清单。我可以很好地添加新元素。我还可以保存和读取文件中的元素。我的问题是,每当我从一个文件中读取然后添加一个新元素时,我的数组就会变得混乱,我的打印函数会打印出垃圾。它应该做的是,每当我加载一个文件或添加一个新元素时,它应该总是将它添加到列表的末尾。这是我的代码:
typedef struct ShoppingList {
int id;
char name[100];
int amount;
char unit[10];
}ShoppingList;
void PrintShoppingList( ShoppingList *list, int *itemsLoaded )
{
if ( *itemsLoaded == 0 ) {
printf( "Inköpslistan är tom.\n" );
return;
}
for ( int i = 0; i<*itemsLoaded; i++ ) {
printf( "%d\t %s\t\t %d\t %s\n", list[i].id, list[i].name, list[i].amount, list[i].unit );
}
}
void AddNewItem( ShoppingList *list, int *itemsLoaded ) {
ShoppingList *temp;
printf( "Namn på vara: " );
scanf_s( "%s", list[*itemsLoaded].name, sizeof( list[*itemsLoaded].name ) );
printf( "Antal: " );
while ( scanf_s( "%d", &list[*itemsLoaded].amount ) != 1 ) {
scanf_s( "%*s" );
printf( "Antal: " );
}
printf( "Enhet: " );
scanf_s( "%s", list[*itemsLoaded].unit, sizeof( list[*itemsLoaded].unit ) );
list[*itemsLoaded].id = *itemsLoaded;
temp = (ShoppingList*)realloc( list, ( *itemsLoaded + 2 ) * sizeof( ShoppingList ) );
if ( temp != NULL ) {
list = temp;
*itemsLoaded = *itemsLoaded + 1;
printf( "Vara lades till.\n" );
} else {
//free( list );
printf( "Kunde inte allokera minne.\n" );
}
}
void SaveShoppingListToFile( ShoppingList *list, int *itemsLoaded ) {
if ( *itemsLoaded == 0 ) {
printf( "Inköpslistan är tom. Kan ej spara.\n" );
return;
}
char filename[20];
int i;
printf( "Spara fil som: " );
scanf_s( "%s", filename, sizeof(filename) );
FILE *fp;
fopen_s( &fp, filename, "w" );
if ( fp )
{
fprintf( fp, "%d", *itemsLoaded );
for ( i = 0; i<*itemsLoaded; i++ ) {
fprintf( fp, "\n%s\n%d\n%s", list[i].name, list[i].amount, list[i].unit );
}
fclose( fp );
printf( "Fil sparad.\n" );
} else {
printf( "Kunde ej spara filen.\n" );
}
}
void LoadShoppingListFromFile( ShoppingList *list, int *itemsLoaded ) {
char filename[20];
int nEntries = 0;
ShoppingList *temp;
printf( "Läs in fil: " );
scanf_s( "%s", filename, sizeof( filename ) );
FILE *fp;
fopen_s( &fp, filename, "r" );
if ( fp )
{
fscanf_s( fp, "%d", &nEntries );
for (int i = 0; i<nEntries; i++ ) {
fscanf_s(fp, "%s", list[*itemsLoaded].name, sizeof( list[*itemsLoaded].name ) );
fscanf_s(fp, "%d", &list[*itemsLoaded].amount );
fscanf_s(fp, "%s", list[*itemsLoaded].unit, sizeof( list[*itemsLoaded].unit ) );
list[*itemsLoaded].id = *itemsLoaded;
temp = (ShoppingList*)realloc( list, ( *itemsLoaded + 2 ) * sizeof( ShoppingList ) );
if ( temp != NULL ) {
list = temp;
*itemsLoaded = *itemsLoaded + 1;
} else {
//free( list );
printf( "Kunde inte allokera minne.\n" );
}
}
fclose( fp );
printf( "Fil inläst.\n" );
} else {
printf( "Kunde ej läsa filen.\n" );
}
}
void Menu() {
int menu = 0, *itemsLoaded, index = 0;
itemsLoaded = &index;
ShoppingList *list = NULL;
list = (ShoppingList*)malloc( sizeof( ShoppingList ) );
if ( list != NULL ) {
do
{
system( "CLS" );
menu = 0;
printf( "%d\n", *itemsLoaded );
printf( "Meny\n 1 - Lägg till en vara till inköpslistan\n 2 - Skriv ut inköpslistan\n 3 - Skriv inköpslistan till fil\n 4 - Läs in inköpslista från fil\n 5 - Ändra vara\n 6 - Ta bort vara\n 7 - Avsluta\nAnge Val: " );
while ( scanf_s( "%d", &menu, sizeof( int ) ) != 1 ) {
scanf_s( "%*s" );
printf( "\nFelaktigt val. Försök igen.\n" );
printf( "Ange Val: " );
}
if ( menu < 7 ) {
switch ( menu ) {
case 1:
AddNewItem( list, itemsLoaded );
PrintShoppingList( list, itemsLoaded );
break;
case 2:
PrintShoppingList( list, itemsLoaded );
break;
case 3:
SaveShoppingListToFile( list, itemsLoaded );
break;
case 4:
LoadShoppingListFromFile( list, itemsLoaded );
PrintShoppingList( list, itemsLoaded );
break;
}
} else if ( menu > 7 || menu < 1 ) {
printf( "Felaktigt val. Försök igen." );
}
system( "pause" );
} while ( menu != 7 );
} else {
printf( "Kunde inte allokera minne." );
}
free( list );
}
int main() {
Menu();
return 0;
}
函数 void AddNewItem( ShoppingList *list, int *itemsLoaded ) {
在数组已满时重新分配 list
但指向新分配的数组的指针永远不会传递回仍使用先前值的调用者。这会调用未定义的行为。
您应该传递指针的地址,以便函数可以更新调用者的值。
int AddNewItem(ShoppingList **listp, int *itemsLoaded) {
ShoppingList *list = *listp;
printf( "Namn på vara: " );
scanf_s( "%s", list[*itemsLoaded].name, sizeof( list[*itemsLoaded].name ) );
printf( "Antal: " );
while ( scanf_s( "%d", &list[*itemsLoaded].amount ) != 1 ) {
scanf_s( "%*s" );
printf( "Antal: " );
}
printf( "Enhet: " );
scanf_s( "%s", list[*itemsLoaded].unit, sizeof( list[*itemsLoaded].unit ) );
list[*itemsLoaded].id = *itemsLoaded;
list = (ShoppingList*)realloc( list, ( *itemsLoaded + 2 ) * sizeof( ShoppingList ) );
if ( list != NULL ) {
*listp = list;
*itemsLoaded = *itemsLoaded + 1;
printf( "Vara lades till.\n" );
return 1; // success
} else {
//free( list );
printf( "Kunde inte allokera minne.\n" );
return 0; // failure
}
}
从 main()
调用此函数作为 AddNewItem( &list, itemsLoaded );
请注意,在 解析额外项目之前重新分配数组 实际上会更简单。这种方法的初始指针可以是 NULL
。
函数LoadShoppingListFromFile
也有同样的问题。
我已经查看我的代码几个小时了,但我就是不明白为什么它不起作用。该程序使用动态数组创建购物清单。我可以很好地添加新元素。我还可以保存和读取文件中的元素。我的问题是,每当我从一个文件中读取然后添加一个新元素时,我的数组就会变得混乱,我的打印函数会打印出垃圾。它应该做的是,每当我加载一个文件或添加一个新元素时,它应该总是将它添加到列表的末尾。这是我的代码:
typedef struct ShoppingList {
int id;
char name[100];
int amount;
char unit[10];
}ShoppingList;
void PrintShoppingList( ShoppingList *list, int *itemsLoaded )
{
if ( *itemsLoaded == 0 ) {
printf( "Inköpslistan är tom.\n" );
return;
}
for ( int i = 0; i<*itemsLoaded; i++ ) {
printf( "%d\t %s\t\t %d\t %s\n", list[i].id, list[i].name, list[i].amount, list[i].unit );
}
}
void AddNewItem( ShoppingList *list, int *itemsLoaded ) {
ShoppingList *temp;
printf( "Namn på vara: " );
scanf_s( "%s", list[*itemsLoaded].name, sizeof( list[*itemsLoaded].name ) );
printf( "Antal: " );
while ( scanf_s( "%d", &list[*itemsLoaded].amount ) != 1 ) {
scanf_s( "%*s" );
printf( "Antal: " );
}
printf( "Enhet: " );
scanf_s( "%s", list[*itemsLoaded].unit, sizeof( list[*itemsLoaded].unit ) );
list[*itemsLoaded].id = *itemsLoaded;
temp = (ShoppingList*)realloc( list, ( *itemsLoaded + 2 ) * sizeof( ShoppingList ) );
if ( temp != NULL ) {
list = temp;
*itemsLoaded = *itemsLoaded + 1;
printf( "Vara lades till.\n" );
} else {
//free( list );
printf( "Kunde inte allokera minne.\n" );
}
}
void SaveShoppingListToFile( ShoppingList *list, int *itemsLoaded ) {
if ( *itemsLoaded == 0 ) {
printf( "Inköpslistan är tom. Kan ej spara.\n" );
return;
}
char filename[20];
int i;
printf( "Spara fil som: " );
scanf_s( "%s", filename, sizeof(filename) );
FILE *fp;
fopen_s( &fp, filename, "w" );
if ( fp )
{
fprintf( fp, "%d", *itemsLoaded );
for ( i = 0; i<*itemsLoaded; i++ ) {
fprintf( fp, "\n%s\n%d\n%s", list[i].name, list[i].amount, list[i].unit );
}
fclose( fp );
printf( "Fil sparad.\n" );
} else {
printf( "Kunde ej spara filen.\n" );
}
}
void LoadShoppingListFromFile( ShoppingList *list, int *itemsLoaded ) {
char filename[20];
int nEntries = 0;
ShoppingList *temp;
printf( "Läs in fil: " );
scanf_s( "%s", filename, sizeof( filename ) );
FILE *fp;
fopen_s( &fp, filename, "r" );
if ( fp )
{
fscanf_s( fp, "%d", &nEntries );
for (int i = 0; i<nEntries; i++ ) {
fscanf_s(fp, "%s", list[*itemsLoaded].name, sizeof( list[*itemsLoaded].name ) );
fscanf_s(fp, "%d", &list[*itemsLoaded].amount );
fscanf_s(fp, "%s", list[*itemsLoaded].unit, sizeof( list[*itemsLoaded].unit ) );
list[*itemsLoaded].id = *itemsLoaded;
temp = (ShoppingList*)realloc( list, ( *itemsLoaded + 2 ) * sizeof( ShoppingList ) );
if ( temp != NULL ) {
list = temp;
*itemsLoaded = *itemsLoaded + 1;
} else {
//free( list );
printf( "Kunde inte allokera minne.\n" );
}
}
fclose( fp );
printf( "Fil inläst.\n" );
} else {
printf( "Kunde ej läsa filen.\n" );
}
}
void Menu() {
int menu = 0, *itemsLoaded, index = 0;
itemsLoaded = &index;
ShoppingList *list = NULL;
list = (ShoppingList*)malloc( sizeof( ShoppingList ) );
if ( list != NULL ) {
do
{
system( "CLS" );
menu = 0;
printf( "%d\n", *itemsLoaded );
printf( "Meny\n 1 - Lägg till en vara till inköpslistan\n 2 - Skriv ut inköpslistan\n 3 - Skriv inköpslistan till fil\n 4 - Läs in inköpslista från fil\n 5 - Ändra vara\n 6 - Ta bort vara\n 7 - Avsluta\nAnge Val: " );
while ( scanf_s( "%d", &menu, sizeof( int ) ) != 1 ) {
scanf_s( "%*s" );
printf( "\nFelaktigt val. Försök igen.\n" );
printf( "Ange Val: " );
}
if ( menu < 7 ) {
switch ( menu ) {
case 1:
AddNewItem( list, itemsLoaded );
PrintShoppingList( list, itemsLoaded );
break;
case 2:
PrintShoppingList( list, itemsLoaded );
break;
case 3:
SaveShoppingListToFile( list, itemsLoaded );
break;
case 4:
LoadShoppingListFromFile( list, itemsLoaded );
PrintShoppingList( list, itemsLoaded );
break;
}
} else if ( menu > 7 || menu < 1 ) {
printf( "Felaktigt val. Försök igen." );
}
system( "pause" );
} while ( menu != 7 );
} else {
printf( "Kunde inte allokera minne." );
}
free( list );
}
int main() {
Menu();
return 0;
}
函数 void AddNewItem( ShoppingList *list, int *itemsLoaded ) {
在数组已满时重新分配 list
但指向新分配的数组的指针永远不会传递回仍使用先前值的调用者。这会调用未定义的行为。
您应该传递指针的地址,以便函数可以更新调用者的值。
int AddNewItem(ShoppingList **listp, int *itemsLoaded) {
ShoppingList *list = *listp;
printf( "Namn på vara: " );
scanf_s( "%s", list[*itemsLoaded].name, sizeof( list[*itemsLoaded].name ) );
printf( "Antal: " );
while ( scanf_s( "%d", &list[*itemsLoaded].amount ) != 1 ) {
scanf_s( "%*s" );
printf( "Antal: " );
}
printf( "Enhet: " );
scanf_s( "%s", list[*itemsLoaded].unit, sizeof( list[*itemsLoaded].unit ) );
list[*itemsLoaded].id = *itemsLoaded;
list = (ShoppingList*)realloc( list, ( *itemsLoaded + 2 ) * sizeof( ShoppingList ) );
if ( list != NULL ) {
*listp = list;
*itemsLoaded = *itemsLoaded + 1;
printf( "Vara lades till.\n" );
return 1; // success
} else {
//free( list );
printf( "Kunde inte allokera minne.\n" );
return 0; // failure
}
}
从 main()
调用此函数作为 AddNewItem( &list, itemsLoaded );
请注意,在 解析额外项目之前重新分配数组 实际上会更简单。这种方法的初始指针可以是 NULL
。
函数LoadShoppingListFromFile
也有同样的问题。