首页 > 解决方案 > 如何在 C 中存储结构指针,以免数据丢失?

问题描述

我有这个代码

#include "stdio.h"
#include "stdlib.h"
#include <string.h>

typedef struct {
  char   brand[40];
  int    year;
  int    km;
  float  price;
}Autos;

int userInput;
void menu();
void scanCars(Autos *pointer);
void print_struct(Autos *pointer);


int main(int argc, char const *argv[])
{
  Autos *pointerCar, Cars;
  pointerCar=&Cars;
  pointerCar=(Autos  *)malloc(5*sizeof(Autos));
  int value= 1;
    while (value)
    {
    menu();
      switch (userInput)
      {
        case 1:
         scanCars(pointerCar);

          break;
        case 2:
          print_struct(pointerCar);

          break;
        case 3:
          value=0;
          break;
      }

    }
  free(pointerCar);
  return 0;
}
void menu()
{
    printf("1) Input Cars:\n" );
    printf("2) Print Cars:\n" );
    printf("3) Exit\n" );
    scanf("%d", &userInput );
    printf("=================\n" );
}
void scanCars(Autos *pointer)
{
  printf("1) Scanning CARS:\n");
  for (int i = 0; i < 2; i++)
  {
    printf("Brand:");
    scanf("%s", (pointer+i)->brand);

    printf("Year: ");
    scanf("%d", &(pointer+i)->year );

    printf("Kilometros:");
    scanf("%d",&(pointer+i)->km );

    printf("price: ");
    scanf("%f",&(pointer+i)->price );
  }
    printf("=================\n" );

}
void print_struct(Autos *pointer)
{
  for (int i = 0; i < 3; i++)
  {
    printf("Car #[%d]\n",i+1 );
    printf("Brand: %s\n",(pointer+i)->brand);
    printf("Year: %d\n",(pointer+i)->year );
    printf("Kilometraje: %d\n",(pointer+i)->km );
    printf("Price: $%.2f\n",(pointer+i)->price );
    printf("=================\n" );
  }

}

该代码运行良好,可以存储一些汽车数据,然后在需要时打印出来。

问题:

当我第二次尝试存储新车数据时,我丢失了最后一次输入。所以我的问题是如何存储一个新的结构数组并打印整个数据:

例子:

  1. 每个*pointerCar有 5 辆汽车
  2. 那么如何保存*pointerCar to array[3] of pointerCars
  3. 我总共将拥有 15 辆汽车,但每辆汽车将拥有 5 辆汽车

我的问题是,每次我运行代码时,我从最后一辆车中写入的数据都会被重写。 输入汽车的图像 用于打印汽车的图像
在此处输入图像描述

标签: cpointersdata-structuresstructure

解决方案


首先,为了使代码更具可读性和更易于调试,需要避免一些事情:

Autos *pointerCar, Cars;- 不要那样做,它会加重可读性。我假设您想声明两个指针:pointerCar- 用于单个汽车和cars一组汽车。在您的代码中,您声明了一个指针pointerCar变量 Cars

建立一个命名约定并坚持下去。如果您将 CamelCase 用于类型,请不要将其用于变量(使用 camelCase 或 snake_case 代替)。不要对类型使用复数。我会这样写:

Auto *single_car;
Auto *cars;

用于calloc结构和数组初始化,因为它用零填充分配的内存,这很方便。

cars = (Auto*) calloc(5, sizeof(Auto));

现在的问题

您丢失了最后一个输入,因为每次调用该scanCars函数时,您都会一次又一次地传递相同的指针。您*pointerCar指向一个由 5 个 Auto 组成的数组,然后用数据填充它scanCars并从函数返回。下次scanCars调用时,它会将相同的指针作为参数传递并覆盖数据。

我总共将拥有 15 辆汽车,但每辆汽车将有 5 辆汽车;

这里有问题。您只定义了一种类型:(Autos应该只是Auto)。如果您为 5 个 Auto 分配空间,您将获得一个指向内存的指针,该内存已准备好存储 5 个 Auto 结构,仅此而已。

如果您想将您的汽车分组到某种形式的假设车库,您必须创建一个指向汽车的指针表(或者简单地说:汽车表的表)。例如:

Auto *garage[3];
garage[0] = (Auto*) calloc(5, sizeof(Auto));
garage[1] = (Auto*) calloc(5, sizeof(Auto));
garage[2] = (Auto*) calloc(5, sizeof(Auto));

现在每个元素都garage包含一个由 5 个 Autos 组成的数组。要访问车库中的汽车,您将编写:garage[1][0].year.

现在您可以将车库传递给您的scanCars功能:scanCars(garage[0]). 记得调整 for 循环scanCars,因为它设置为只填充 2 辆汽车,现在应该有 5 辆。


推荐阅读