数据结构课程设计 仓储管理系统

 仓储管理系统

【基本功能】

把货品信息表抽象成一个线性表,货品信息(包括ID、货品名、定价、数量等)作为线性表的一个元素,实现:按ID、货品名分别查找某货品信息(包括ID、货品名、定价、数量等);收录货品(如果货品在帐中已有,则只将总库存量增加。否则插入新增信息);售出货品(如果帐中还有存货,则只将总库存量减少。如果库存为0,则提示售出失败);清除货品(删除该货品信息)、修改货品(ID、货品名和单价);排序(按定价排序--采用冒泡排序、按数量排序--采用快排)等功能。

【基本要求】

(1)分别采用单链表和顺序表实现相应功能。

(2)编写一个测试主函数,测试所实现的功能。

课程设计任务1

该程序实现了一个简单的商品库存管理系统,能够收录、删除、修改、查找、售出货品,并支持按定价和数量排序显示货品信息。

在程序中,使用了结构体定义了货品信息的数据结构,使用了动态数组来存储不定数量的货品信息。程序中还提供了扩容线性表的功能,以便存储更多的货品信息。

在菜单循环中,通过用户输入选择相应的操作。其中,插入和修改操作需要用户输入货品ID、名称、价格和数量;删除和按ID查找操作需要用户输入货品ID;按名称查找操作需要用户输入货品名称;售出操作需要用户输入货品ID。而排序和显示操作直接调用对应的函数即可。

需要注意的是,在fgets()函数读取字符串时,末尾可能会包含换行符,需要用字符串处理函数去掉。另外,在使用realloc()函数重新分配内存空间时,需要判断是否分配成功,否则会返回NULL,程序需要进行异常处理。

解释每一部分:

首先是定义了一个货品信息的结构体类型 `Product`,它包含了四个属性:`id`(整数类型)、`name`(字符数组类型,最大长度为50)、`price`(浮点数类型)和 `quantity`(整数类型)。这个结构体用于表示一个货品的详细信息。

接下来是定义了线性表的结构体类型 `List`。它包含了三个成员变量:`data`(指向 `Product` 结构体的指针)、`length`(表示当前存储的货品信息数量的整数)和 `capacity`(表示数组容量的整数)。`data` 指针将用于动态分配内存来存储货品信息数组。

`initList` 函数用于初始化线性表。它接受一个指向 `List` 结构体的指针作为参数,通过调用 `malloc` 分配了一个大小为 `sizeof(Product) * 10` 的内存块,并将其地址赋值给 `data` 指针。这样就创建了一个能够存储 10 个 `Product` 结构体的数组。同时,`length` 和 `capacity` 被初始化为 0 和 10,表示当前线性表中没有保存任何货品信息,但有足够的容量来存储。

`expandList` 函数用于扩容线性表。它接受一个指向 `List` 结构体的指针作为参数。当线性表中的存储空间不足时,即 `length` 等于 `capacity` 时,它会调用 `realloc` 函数重新分配一个更大的内存块。新的内存块的大小是原来的容量加上 10 个 `Product` 结构体的大小,然后更新 `data` 指针和 `capacity` 的值。这样就实现了线性表的扩容操作。

通过上述代码,我们定义了一个基本的线性表数据结构,其中可以存储和管理多个货品的详细信息。你可以使用 `initList` 函数初始化线性表,并通过 `expandList` 函数在需要时动态地扩展存储空间。这个数据结构为进一步实现增删改查等功能提供了基础。

```c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

```

这些是程序所需的头文件,包括标准输入输出和字符串处理的函数。

```c

typedef struct {

    int id;

    char name[50];

    float price;

    int quantity;

} Product;

```

这是一个货品信息的结构体,包含了货品的ID、名称、价格和数量等属性。

```c

typedef struct {

    Product* data;

    int length;

    int capacity;

} List;

```

这是线性表的结构体,包含了一个指向存储货品信息的数组的指针、当前存储的货品信息数量和数组的容量。

```c

void initList(List* list) {

    list->data = (Product*)malloc(sizeof(Product) * 10);

    list->length = 0;

    list->capacity = 10;

}

```

这个函数用于初始化线性表。它分配了一个初始容量为10的数组来存储货品信息,并将长度和容量都设置为0。

它会将原来的数组指针传递给realloc函数,同时计算新的容量并分配足够的内存空间。然后,它更新线性表的容量属性,以便反映新的容量大小。这样做的目的是在需要存储更多货品信息时,可以动态地扩展线性表的容量,避免因为容量不足而导致无法插入新的货品信息。在上面的代码中,realloc函数用于扩展线性表的容量。它接受线性表原来的数据指针作为第一个参数,计算新的容量并分配足够的内存空间,然后返回指向重新分配后的内存块的指针。通过将这个指针赋值给线性表的数据属性,就实现了线性表容量的扩展。

realloc是C语言中的一个函数,用于重新分配内存空间的大小。它接受两个参数:原始的内存指针和新的内存大小。

具体来说,realloc函数会根据新的内存大小重新分配内存,并将原始的内存内容复制到新的内存块中。如果新的内存大小大于原始内存大小,那么额外的内存空间将被初始化为未定义的值。如果新的内存大小小于原始内存大小,那么超出新大小的部分将被丢弃。

realloc函数的返回值是指向重新分配后的内存块的指针。如果内存分配成功,返回的指针与原始的内存指针相同;如果内存分配失败,返回NULL指针。

```c

void expandList(List* list) {

    list->data = (Product*)realloc(list->data, sizeof(Product) * (list->capacity + 10));

    list->capacity += 10;

}

```

这个函数用于扩容线性表。当存储空间不足时,它会重新分配更大的存储空间,并更新容量。

```c

void insertProduct(List* list, Product product) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == product.id) {

            list->data[i].quantity += product.quantity;

            return;

        }

    }

    if (list->length >= list->capacity) {

        expandList(list);

    }

    list->data[list->length++] = product;

}

```

这个函数用于插入货品信息。它首先检查要插入的货品是否已经存在于列表中,如果存在则增加其数量;如果不存在,则将新的货品信息插入到列表末尾。当存储空间不足时,会自动扩容。

```c

void deleteProduct(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            list->data[i] = list->data[list->length - 1];

            list->length--;

            return;

        }

    }

    printf("货品不存在\n");

}

```099

这个函数用于删除指定ID的货品信息。它会遍历整个列表,找到与给定ID匹配的货品信息,并将最后一个货品信息覆盖到要删除的位置上,然后更新长度。

```c

void modifyProduct(List* list, int id, char name[], float price) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            strcpy(list->data[i].name, name);

            list->data[i].price = price;

            return;

        }

    }

    printf("货品不存在\n");

}

```

`strcpy`是C语言中的一个字符串操作函数,用于将一个字符串复制到另一个字符串中。它接受两个参数:目标字符串和源字符串。

具体来说,`strcpy`函数会从源字符串的起始位置开始,逐个字符地复制到目标字符串中,直到遇到字符串结束符'\0'。复制完成后,目标字符串将包含与源字符串相同的内容。

函数原型如下:

```c

char* strcpy(char* dest, const char* src);

```

其中,`dest`表示目标字符串,`src`表示源字符串。函数返回一个指向目标字符串的指针。

需要注意的是,为了保证目标字符串足够大,能够存储源字符串的内容,建议在使用`strcpy`时先确保目标字符串的内存空间足够

这个函数用于修改指定ID的货品信息。它会遍历整个列表,找到与给定ID匹配的货品信息,并将名称和价格进行修改。

```c

void searchById(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

                list->data[i].quantity);

            return;

        }

    }

    printf("货品不存在\n");

}

```

这个函数用于按ID查找货品信息。它会遍历整个列表,找到与给定ID匹配的货品信息,并打印出来。

```c

void searchByName(List* list, char name[]) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (strcmp(list->data[i].name, name) == 0) {

            printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

                list->data[i].quantity);

            return;

        }

    }

    printf("货品不存在\n");

}

```

这个函数用于按货品名查找货品信息。它会遍历整个列表,找到与给定名称匹配的货品信息,并打印出来。

```c

void sellProduct(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            if (list->data[i].quantity >

```c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

```

这些是程序所需的头文件,包括标准输入输出和字符串处理的函数。

`stdlib.h`是C语言标准库中的一个头文件,提供了一些常用的函数和类型定义,涵盖了内存管理、随机数生成、字符串转换等功能。

这个头文件包含了以下常用函数的声明:

- `malloc`:用于动态分配内存空间。

- `calloc`:用于动态分配并初始化内存空间。

- `realloc`:用于重新分配已分配内存空间的大小。

- `free`:用于释放之前通过`malloc`、`calloc`或`realloc`函数分配的内存空间。

- `exit`:终止程序的执行。

- `rand`:生成伪随机数。

- `srand`:设置`rand`函数的随机数种子。

- `abs`:取整数的绝对值。

- `atoi`、`atol`、`atof`:将字符串转换为整数、长整数、浮点数。

- `system`:调用系统命令。

除了上述函数声明外,`stdlib.h`还定义了一些常用的数据类型,如`size_t`、`div_t`、`ldiv_t`、`lldiv_t`等。

需要注意的是,在使用这些函数之前,需要包含`stdlib.h`头文件,以便编译器正确识别函数声明和类型定义。

以下是一个使用`stdlib.h`头文件的示例代码:

```c

#include <stdio.h>

#include <stdlib.h>

int main() {

    int* ptr = (int*)malloc(sizeof(int)); // 动态分配一个int类型的内存空间

    if (ptr == NULL) {

        printf("内存分配失败");

        return 1;

    }

    *ptr = 42; // 在分配的内存空间中存储数据

    printf("动态分配的内存空间中的值为:%d\n", *ptr);

    free(ptr); // 释放内存空间

    return 0;

}

```

在上面的代码中,我们通过`malloc`函数动态分配了一个`int`类型的内存空间,然后将值42存储在该内存空间中。最后,使用`free`函数释放了该内存空间。

首先是主函数,这个函数负责整个程序的流程控制,根据用户输入的选项,调用不同的函数实现不同的操作。在每次输入完选项后,使用`getchar()`函数读取输入缓冲区中的换行符,避免在后续的输入操作中出现问题。

```c

int main() {

    List list;

    initList(&list);

    // 菜单循环

    while (1) {

        printf("\n===============\n");

        printf("1. 收录货品\n");

        printf("2. 删除货品\n");

        printf("3. 修改货品\n");

        printf("4. 按ID查找货品\n");

        printf("5. 按货品名查找货品\n");

        printf("6. 售出货品\n");

        printf("7. 按定价排序\n");

        printf("8. 按数量排序\n");

        printf("9. 显示货品信息\n");

        printf("0. 退出\n");

        printf("===============\n");

        printf("请选择操作:");

        int choice;

        scanf("%d", &choice);

        getchar(); // 处理输入缓冲区的换行符

        if (choice == 1) {

            // ...

        }

        else if (choice == 2) {

            // ...

        }

        // ...

        else if (choice == 0) {

            break;

        }

        else {

            printf("无效的选择\n");

        }

    }

    free(list.data);  // 释放内存

    return 0;

}

```

接下来是链表的定义和初始化函数。链表中每个节点包含一个`Product`结构体,记录货品的ID、名称、定价和数量等信息。`List`结构体则包含了链表的头指针和长度信息。

```c

typedef struct Product {

    int id;         // 货品ID

    char name[50];  // 货品名

    float price;    // 定价

    int quantity;   // 数量

} Product;

typedef struct List {

    Product* data;  // 数据数组

    int length;     // 当前数据个数

} List;

// 初始化链表,分配一个空间并将其初始化为空表

void initList(List* list) {

    list->data = (Product*)malloc(sizeof(Product) * MAX_SIZE);

    list->length = 0;

}

```

然后是添加货品、删除货品和修改货品的函数实现。这些函数都需要遍历链表查找相应的节点,然后修改其值或者删除该节点,并调整链表的结构。

```c

// 添加货品函数

void insertProduct(List* list, Product product) {

    if (list->length >= MAX_SIZE) {

        printf("超出最大容量,无法添加\n");

        return;

    }

    // 在尾部插入新节点

    list->data[list->length] = product;

    list->length++;

}

// 删除货品函数

void deleteProduct(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            // 将后面的元素向前移动覆盖该元素

            int j;

            for (j = i; j < list->length - 1; j++) {

                list->data[j] = list->data[j + 1];

            }

            list->length--;

            printf("删除成功\n");

            return;

        }

    }

    printf("货品不存在\n");

}

// 修改货品函数

void modifyProduct(List* list, int id, char* name, float price) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            strcpy(list->data[i].name, name);

            list->data[i].price = price;

            printf("修改成功\n");

            return;

        }

    }

    printf("货品不存在\n");

}

```

下面是按ID和按名称查找货品的函数。这些函数也需要遍历链表查找相应的节点,并返回查询结果。

```c

// 按ID查找货品函数

void searchById(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

                list->data[i].quantity);

            return;

        }

    }

    printf("货品不存在\n");

}

// 按名称查找货品函数

void searchByName(List* list, char* name) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (strcmp(list->data[i].name, name) == 0) {

            printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

                list->data[i].quantity);

            return;

        }

    }

    printf("货品不存在\n");

}

```

接下来是售出货品的函数。该函数需要遍历链表查找相应的节点,并修改其数量信息。

```c

// 售出货品函数

void sellProduct(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            if (list->data[i].quantity > 0) {

                list->data[i].quantity--;

                printf("售出成功\n");

            }

            else {

                printf("售出失败,库存为0\n");

            }

            return;

        }

    }

    printf("货品不存在\n");

}

```

然后是按定价排序和按数量排序的函数实现。按定价排序使用冒泡排序算法,按数量排序使用快速排序算法。这些排序算法都是经典的算法,不再赘述。

```c

// 按定价排序函数(冒泡排序)

void sortByPrice(List* list) {

    int i, j;

    for (i = 0; i < list->length - 1; i++) {

        for (j = 0; j < list->length - i - 1; j++) {

            if (list->data[j].price > list->data[j + 1].price) {

                // 交换元素

                Product temp = list->data[j];

                list->data[j] = list->data[j + 1];

                list->data[j + 1] = temp;

            }

        }

    }

}

这个函数是按照货品的定价进行排序的。具体来说,它使用冒泡排序算法,从头到尾遍历链表,比较相邻的两个节点的定价大小,如果前面的节点定价大于后面的节点,则交换这两个节点的值。这样一轮下来,最大的定价就会被移动到链表的末尾。接着再从头开始进行下一轮比较,依次类推,直到整个链表都排好序为止。

这个函数的输入参数是一个指向List结构体的指针,表示要对哪个链表进行排序。函数内部使用指向Product结构体的指针来访问每个节点的信息。

冒泡排序是一种简单直观的排序算法,它重复地遍历待排序的元素序列,比较相邻两个元素的大小,并按照指定的顺序交换它们,从而将最大(或最小)的元素逐渐"浮"到序列的末尾。冒泡排序的基本思想是通过相邻元素之间的比较和交换,使得每一轮遍历都能找到当前未排序部分的最大(或最小)元素。

在这个具体的按定价排序函数中,它使用了两层循环来实现冒泡排序。外层循环控制需要进行比较的轮数,内层循环则负责每一轮的比较和交换操作。

首先,外层循环从第一个元素开始,一直遍历到倒数第二个元素,即`list->length - 1`。这是因为在每一轮比较中,最后一个元素已经处于正确的位置上,无需再进行比较。

接着,内层循环从第一个元素开始,一直遍历到当前未排序部分的最后一个元素。在每一轮内层循环中,它会比较相邻的两个元素的定价大小,如果前面的元素的定价大于后面的元素,则交换这两个元素的值。通过这样的比较和交换操作,每一轮都能将当前未排序部分的最大定价元素"浮"到序列的末尾。

重复进行外层循环和内层循环,直至所有元素都排好序为止。

总体来说,冒泡排序的时间复杂度是O(n^2),其中n是待排序序列的长度。在最坏情况下,需要进行n-1轮比较,每轮比较需要遍历n-i次(i为已经排好序的元素个数),因此总的比较次数是n(n-1)/2。对于较小规模的序列,冒泡排序是一种简单实用的排序算法,但对于大规模数据来说效率较低。

// 按数量排序函数(快速排序)

void quickSortByQuantity(Product* data, int left, int right) {

    if (left >= right) {

        return;

    }

    int i = left;

    int j = right;

    Product pivot = data[left];

    while (i < j) {

        while (i < j && data[j].quantity >= pivot.quantity) {

            j--;

        }

        data[i] = data[j];

        while (i < j && data[i].quantity <= pivot.quantity) {

            i++;

        }

        data[j] = data[i];

    }

    data[i] = pivot;

    quickSortByQuantity(data, left, i - 1);

    quickSortByQuantity(data, i + 1, right);

}

```

这段代码实现了按照数量进行排序的快速排序算法。

快速排序是一种高效的排序算法,它采用分治的思想来进行排序。具体实现如下:

1. 首先,判断左边界 `left` 是否大于等于右边界 `right`,如果是,则表示已经排好序或者只有一个元素,直接返回。

2. 然后,选择数组中的一个基准元素(pivot),这里选择第一个元素 `data[left]` 作为基准元素。

3. 接着,设置两个指针 `i` 和 `j`,分别指向左右边界。

4. 进入循环,首先从右边开始,找到第一个比基准元素小的元素,将其移动到左边,并将 `j` 向左移动一位。

5. 接着,从左边开始,找到第一个比基准元素大的元素,将其移动到右边,并将 `i` 向右移动一位。

6. 重复步骤4和步骤5,直到 `i` 和 `j` 相遇。

7. 将基准元素放到相遇的位置,此时基准元素左边的元素都比它小,右边的元素都比它大。

8. 对基准元素左右两边的子数组分别进行递归调用快速排序函数,分别排序左边和右边的部分。

9. 递归结束后,数组就排好序了。

这样,通过不断地将基准元素放到正确的位置,最终实现了按照数量进行排序。快速排序的平均时间复杂度为 O(nlogn),但在最坏情况下会退化到 O(n^2)。然而,快速排序通常比其他排序算法更快,并且在实践中表现良好。

最后是显示货品信息的函数实现。该函数遍历链表,按照指定的格式输出每个节点的信息。

```c

// 显示货品信息函数

void showProducts(List* list) {

    int i;

    for (i = 0; i < list->length; i++) {

        printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

            list->data[i].quantity);

    }

}

```

以上就是整个程序的实现。通过这个简单的货物管理系统,我们可以了解到链表的实现和操作,以及常见的排序算法的实现方法。

源代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// 货品信息结构体

typedef struct {

    int id;  // 货品ID

    char name[50];  // 货品名称

    float price;  // 货品价格

    int quantity;  // 货品数量

} Product;

// 线性表结构体

typedef struct {

    Product* data;  // 指向存储货品信息的数组的指针

    int length;  // 当前存储的货品信息数量

    int capacity;  // 数组的容量

} List;

// 初始化线性表

void initList(List* list) {

    list->data = (Product*)malloc(sizeof(Product) * 10);  // 初始分配存储空间

    list->length = 0;  // 初始长度为0

    list->capacity = 10;  // 初始容量为10

}

// 扩容线性表

void expandList(List* list) {

    list->data = (Product*)realloc(list->data, sizeof(Product) * (list->capacity + 10));  // 重新分配更大的存储空间

    list->capacity += 10;  // 更新容量

}

// 插入货品信息

void insertProduct(List* list, Product product) {

    int i;

    // 判断货品是否已存在

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == product.id) {

            // 货品已存在,增加库存量

            list->data[i].quantity += product.quantity;

            return;

        }

    }

    // 货品不存在,插入新增信息

    if (list->length >= list->capacity) {

        expandList(list);  // 如果存储空间不足,扩容

    }

    list->data[list->length++] = product;  // 插入新的货品信息

}

// 删除货品信息

void deleteProduct(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            // 将最后一个元素覆盖要删除的元素

            list->data[i] = list->data[list->length - 1];

            list->length--;  // 更新长度

            return;

        }

    }

    printf("货品不存在\n");

}

// 修改货品信息

void modifyProduct(List* list, int id, char name[], float price) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            strcpy(list->data[i].name, name);  // 修改名称

            list->data[i].price = price;  // 修改价格

            return;

        }

    }

    printf("货品不存在\n");

}

// ID查找货品信息

void searchById(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

                list->data[i].quantity);

            return;

        }

    }

    printf("货品不存在\n");

}

// 按货品名查找货品信息

void searchByName(List* list, char name[]) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (strcmp(list->data[i].name, name) == 0) {

            printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

                list->data[i].quantity);

            return;

        }

    }

    printf("货品不存在\n");

}

// 售出货品

void sellProduct(List* list, int id) {

    int i;

    for (i = 0; i < list->length; i++) {

        if (list->data[i].id == id) {

            if (list->data[i].quantity > 0) {

                list->data[i].quantity--;

                printf("售出成功\n");

            }

            else {

                printf("售出失败,库存为0\n");

            }

            return;

        }

    }

    printf("货品不存在\n");

}

// 按定价排序(冒泡排序)

void sortByPrice(List* list) {

    int i, j;

    for (i = 0; i < list->length - 1; i++) {

        for (j = 0; j < list->length - i - 1; j++) {

            if (list->data[j].price > list->data[j + 1].price) {

                // 交换元素

                Product temp = list->data[j];

                list->data[j] = list->data[j + 1];

                list->data[j + 1] = temp;

            }

        }

    }

}

// 按数量排序(快速排序)

void quickSortByQuantity(Product* data, int left, int right) {

    if (left >= right) {

        return;

    }

    int i = left;

    int j = right;

    Product pivot = data[left];

    while (i < j) {

        while (i < j && data[j].quantity >= pivot.quantity) {

            j--;

        }

        data[i] = data[j];

        while (i < j && data[i].quantity <= pivot.quantity) {

            i++;

        }

        data[j] = data[i];

    }

    data[i] = pivot;

    quickSortByQuantity(data, left, i - 1);

    quickSortByQuantity(data, i + 1, right);

}

// 显示货品信息

void showProducts(List* list) {

    int i;

    for (i = 0; i < list->length; i++) {

        printf("ID: %d, 货品名: %s, 定价: %.2f, 数量: %d\n", list->data[i].id, list->data[i].name, list->data[i].price,

            list->data[i].quantity);

    }

}

int main() {

    List list;

    initList(&list);

    // 菜单循环

    while (1) {

        printf("\n===============\n");

        printf("1. 收录货品\n");

        printf("2. 删除货品\n");

        printf("3. 修改货品\n");

        printf("4. ID查找货品\n");

        printf("5. 按货品名查找货品\n");

        printf("6. 售出货品\n");

        printf("7. 按定价排序\n");

        printf("8. 按数量排序\n");

        printf("9. 显示货品信息\n");

        printf("0. 退出\n");

        printf("===============\n");

        printf("请选择操作:");

        int choice;

        scanf("%d", &choice);

        getchar(); // 处理输入缓冲区的换行符

        if (choice == 1) {

            Product product;

            printf("请输入货品ID");

            scanf("%d", &product.id);

            getchar();

            printf("请输入货品名:");

            fgets(product.name, 50, stdin);

            product.name[strlen(product.name) - 1] = '\0'; // 去掉末尾的换行符

            printf("请输入货品定价:");

            scanf("%f", &product.price);

            printf("请输入货品数量:");

            scanf("%d", &product.quantity);

            insertProduct(&list, product);

            printf("收录成功\n");

        }

        else if (choice == 2) {

            int id;

            printf("请输入要删除的货品ID");

            scanf("%d", &id);

            deleteProduct(&list, id);

        }

        else if (choice == 3) {

            int id;

            printf("请输入要修改的货品ID");

            scanf("%d", &id);

            getchar();

            char name[50];

            printf("请输入新的货品名:");

            fgets(name, 50, stdin);

            name[strlen(name) - 1] = '\0'; // 去掉末尾的换行符

            float price;

            printf("请输入新的货品定价:");

            scanf("%f", &price);

            modifyProduct(&list, id, name, price);

        }

        else if (choice == 4) {

            int id;

            printf("请输入要查找的货品ID");

            scanf("%d", &id);

            searchById(&list, id);

        }

        else if (choice == 5) {

            char name[50];

            printf("请输入要查找的货品名:");

            getchar();

            fgets(name, 50, stdin);

            name[strlen(name) - 1] = '\0'; // 去掉末尾的换行符

            searchByName(&list, name);

        }

        else if (choice == 6) {

            int id;

            printf("请输入要售出的货品ID");

            scanf("%d", &id);

            sellProduct(&list, id);

        }

        else if (choice == 7) {

            sortByPrice(&list);

            printf("按定价排序完成\n");

        }

        else if (choice == 8) {

            quickSortByQuantity(list.data, 0, list.length - 1);

            printf("按数量排序完成\n");

        }

        else if (choice == 9) {

            showProducts(&list);

        }

        else if (choice == 0) {

            break;

        }

        else {

            printf("无效的选择\n");

        }

    }

    free(list.data);  // 释放内存

    return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/640663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++版QT:电子时钟

digiclock.h #ifndef DIGICLOCK_H #define DIGICLOCK_H ​ #include <QLCDNumber> ​ class DigiClock : public QLCDNumber {Q_OBJECT public:DigiClock(QWidget* parent 0);void mousePressEvent(QMouseEvent*);void mouseMoveEvent(QMouseEvent*); public slots:voi…

JVM常量池详解

欢迎大家关注我的微信公众号&#xff1a; 目录 Class常量池与运行时常量池 字符串常量池 字符串常量池的设计思想 三种字符串操作(Jdk1.7 及以上版本) 字符串常量池位置 字符串常量池设计原理 String常量池问题的几个例子 八种基本类型的包装类和对象池 Class常量…

防范水坑攻击:了解原理、类型与措施

水坑攻击是一种常见的网络攻击方式&#xff0c;它利用了人类在互联网上的行为习惯&#xff0c;诱导用户访问恶意网站或下载恶意软件&#xff0c;从而获取用户的个人信息或控制用户的计算机系统。本文将介绍水坑攻击的原理、类型和防范措施。 一、水坑攻击的原理 水坑攻击&…

Cyber RT 服务通信

场景&#xff1a; 用户乘坐无人出租车过程中&#xff0c;可能临时需要切换目的地&#xff0c;用户可以通过车机系统完成修改&#xff0c;路径规划模块需要根据新的目的地信息重新规划路径&#xff0c;并反馈修正后的结果给用户&#xff0c;那么用户的修正请求数据与修正结果是如…

使用STM32的SPI接口实现与外部传感器的数据交互

一、引言 外部传感器是嵌入式系统中常用的外设&#xff0c;用于检测环境参数、采集数据等。通过STM32微控制器的SPI接口&#xff0c;可以与外部传感器进行数据交互&#xff0c;从而实现数据的采集和控制。本文将介绍如何使用STM32的SPI接口实现与外部传感器的数据交互&#xff…

Web 安全之水坑攻击(Watering Hole Attack)详解

目录 什么是水坑攻击&#xff08;Watering Hole Attack&#xff09; 水坑攻击的原理 水坑攻击的实施案例 水坑攻击的防范方法 小结 什么是水坑攻击&#xff08;Watering Hole Attack&#xff09; 水坑攻击&#xff08;Watering Hole Attack&#xff09;是一种精心策划的网…

常用芯片学习——HC245芯片

HC245三态输出八路总线收发器 使用说明 这些八路总线收发器专为数据总线之间的异步双向通信而设计。控制功能实现可更大限度地减少外部时序要求。根据方向控制 (DIR) 输入上的逻辑电平&#xff0c;此类器件将数据从 A 总线发送至 B 总线&#xff0c;或者将数据从 B 总线发送至…

Windows安装Anaconda教程

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十八&#xff09;——Windows安装Anaconda教程 本文是我实践后写的&#xff0c;无脑跟随安装即可 在我看来&#xff0c;Anaconda的图标如同一只灵蛇咬住了自己的尾巴&#xff0c;优美而神秘。 全称&…

网络安全全栈培训笔记(55-服务攻防-数据库安全RedisHadoopMysqla未授权访问RCE)

第54天 服务攻防-数据库安全&Redis&Hadoop&Mysqla&未授权访问&RCE 知识点&#xff1a; 1、服务攻防数据库类型安全 2、Redis&Hadoop&Mysql安全 3、Mysql-CVE-2012-2122漏洞 4、Hadoop-配置不当未授权三重奏&RCE漏洞 3、Redis-配置不当未授权…

JVM的组成部分(类加载器、运行时数据区、执行引擎、本地库接口)

目录 JVM作用 JVM构成 1.类加载器 类加载子系统&#xff1a; 类加载器的分类&#xff1a; 双亲委派机制&#xff1a; 2.运行时数据区 程序计数器 虚拟机栈 本地方法栈 堆 方法区 3.执行引擎 4.本地库接口 JVM作用 jvm是将字节码文件加载到虚拟机中&#xff0c;…

lc11 盛最多水的容器

问题&#xff1a;给一个整数数组&#xff0c;数组中的元素值为高&#xff0c;数组元素之间的距离为边&#xff0c;计算任意两个元素之间的面积&#xff08;以元素值低的为高&#xff09;&#xff0c;求最大面积 题解&#xff1a;双指针题解 //设计算法&#xff1a;先计算索引…

2024年【广东省安全员B证第四批(项目负责人)】新版试题及广东省安全员B证第四批(项目负责人)作业模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广东省安全员B证第四批&#xff08;项目负责人&#xff09;新版试题参考答案及广东省安全员B证第四批&#xff08;项目负责人&#xff09;考试试题解析是安全生产模拟考试一点通题库老师及广东省安全员B证第四批&…

一.Winform使用Webview2(Edge浏览器核心) 创建demo(Demo1)实现回车导航到指定地址

Winform使用Webview2创建demo1实现回车导航到指定地址 往期目录参考文档实现1.安装visual studio2.创建单窗口应用3.修改项目中的窗体名称MainForm4.添加按钮5.添加窗口Demo16.在Demo1中添加WebView2 SDK7.在Demo1窗体中选择添加textbox和webview28.在MainForm.cs窗体中添加but…

[ComfyUI进阶教程] lcm+Lora+Controlnet工作流工作流

这是一个使用了LCMlora加载器CN&#xff08;depthtile&#xff09;的工作流。 工作流特性&#xff1a; LCM lora加载器&#xff0c;加快生成图片的时间。 配置了3个lora加载器&#xff0c;用来进行人物和风格设定。 提示词编辑器&#xff0c;预制了默认的动态提示词。 使用了…

【RabbitMQ】交换机详解看这一篇就够了

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《RabbitMQ实战》。&#x1f3af;&#x1f3af; &am…

PointNet系列【语义分割】自定义数据的模型训练

目录 一、平台 二、数据 三、代码 3.1 文件组织结构 3.2 lasDataLoader.py 读取数据 3.3 修改原始模型的通道数量 3.4 lasTrainSS.py【训练】 3.5 lasTestSS.py【预测】 一、平台 Windows 10 GPU RTX 3090 CUDA 11.1 cudnn 8.9.6 Python 3.9 Torch 1.9.1 cu111…

每个人都可以是架构师,每个人都需要培养架构思维

您好&#xff0c; 如果喜欢我的文章或者想上岸大厂&#xff0c;可以关注公众号「量子前端」&#xff0c;将不定期关注推送前端好文、分享就业资料秘籍&#xff0c;也希望有机会一对一帮助你实现梦想 什么是架构 “架构”&#xff0c;即架设、构建。完成对于平台的合理架设&am…

VMware安装Linux-Redhat7.9 详细步骤

目录 一、安装准备二、安装步骤 一、安装准备 Redhat 7.9 镜像下载 VMware安装步骤可查看文章&#xff1a;https://blog.csdn.net/a2279338659/article/details/126346345 可去官网下载&#xff0c;或者加群下载镜像资源。 二、安装步骤 创建新的虚拟机&#xff1a; 我这边…

Java学习(二十二)--正则表达式

介绍 为什么需要 正则表达式是处理文本的利器&#xff1b; 基本介绍 正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;。它是一个强大的字符串处理工具&#xff0c;可以对字符串进行查找、提…

语音模块学习——LSYT201B模组(深圳雷龙科技)

目录 引子 处理器 外设 音频 蓝牙 模组展示 引子 关注我的老粉们应该知道我之前用过语音模块做东西&#xff0c;那个比较贵要50多。 今天这个淘宝20元左右比那个便宜&#xff0c;之前那个内核是51的&#xff0c;一个8位机。 后面我做东西的时候语音模块可能会换成这个&…