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

 仓储管理系统

【基本功能】

把货品信息表抽象成一个线性表,货品信息(包括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…

常用芯片学习——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;…

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…

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

您好&#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; 我这边…

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

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

【计算机网络】Socket的TCP_NODELAY选项与Nagle算法

TCP_NODELAY是一个套接字选项&#xff0c;用于控制TCP套接字的延迟行为。当TCP_NODELAY选项被启用时&#xff0c;即设置为true&#xff0c;就会禁用Nagle算法&#xff0c;从而实现TCP套接字的无延迟传输。这意味着每次发送数据时都会立即发送&#xff0c;不会等待缓冲区的填充或…

代码随想录算法训练营DAY24|回溯1

算法训练DAY24|回溯1 第77题. 组合 力扣题目链接 给定两个整数 n 和 k&#xff0c;返回 1 ... n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 上面我们说了要解决 n为100&#xff0c;k为50的情况&#xff0…

vscode连不上虚拟机,一直密码错误

最近在做毕设&#xff0c;但是vscode使用连接不上虚拟机&#xff0c;我以为是网络配置的问题&#xff0c;一顿查阅没找到原因。 后来查了一下ssh的日志&#xff0c;发现ssh有消息&#xff0c;但是也提示密码错误。 没找到密码配置格式什么的&#xff0c;经查看sshd配置文件发现…

工业相机与镜头参数及选型

文章目录 1、相机成像系统模型1.1 视场1.2 成像简化模型 2、工业相机参数2.1 分辨率2.2 靶面尺寸2.3 像元尺寸2.4 帧率/行频2.5 像素深度2.6 动态范围2.7 信噪比2.8 曝光时间2.9 相机接口 3、工业镜头参数3.1 焦距3.2 光圈3.3 景深3.4 镜头分辨率3.5 工作距离&#xff08;Worki…