C语言零基础入门教程:225-274节

225. 常见 math.h 数学库函数汇总

在这段代码中,你展示了如何使用标准 C 库中的一些常见数学函数,如 sqrt()fabs()ceil()floor()fmod()。这些函数都是在 math.h 中定义的,并且可以处理常见的数学运算。

主要函数:
  1. sqrt(x) - 计算 x 的平方根。x 必须是非负数。
    • 输入:16.0
    • 输出:4.0(因为 sqrt(16.0) 等于 4.0
  2. fabs(x) - 返回 x 的绝对值。
    • 输入:-5.7
    • 输出:5.7(因为 fabs(-5.7) 等于 5.7
  3. ceil(x) - 向上取整,返回大于或等于 x 的最小整数。
    • 输入:2.3
    • 输出:3.0(因为 ceil(2.3) 等于 3.0
  4. floor(x) - 向下取整,返回小于或等于 x 的最大整数。
    • 输入:2.7
    • 输出:2.0(因为 floor(2.7) 等于 2.0
  5. fmod(x, y) - 返回 x 除以 y 的余数。
    • 输入:x = 5.5, y = 2.0
    • 输出:1.5(因为 5.5 % 2.0 等于 1.5
完整代码:
#define _USE_MATH_DEFINES
#include <stdio.h>
#include <inttypes.h>
#include <math.h>

int main(void) {

    // 输入数据
    double num_sqrt = 16.0;      // 要求的平方根的数
    double num_fabs = -5.7;      // 要求的绝对值的数
    double num_ceil = 2.3;       // 向上取整的数
    double num_floor = 2.7;      // 向下取整的数
    double num1_fmod = 5.5;      // 求余数的被除数
    double num2_fmod = 2.0;      // 求余数的整数

    // 计算结果
    double result_sqrt = sqrt(num_sqrt);
    double result_fabs = fabs(num_fabs);
    double result_ceil = ceil(num_ceil);
    double result_floor = floor(num_floor);
    double result_fmod = fmod(num1_fmod, num2_fmod);

    // 输出结果
    printf("sqrt(%.2f) = %.2f\n", num_sqrt, result_sqrt);
    printf("fabs(%.2f) = %.2f\n", num_fabs, result_fabs);
    printf("ceil(%.2f) = %.2f\n", num_ceil, result_ceil);
    printf("floor(%.2f) = %.2f\n", num_floor, result_floor);
    printf("fmod(%.2f, %.2f) = %.2f\n", num1_fmod, num2_fmod, result_fmod);

    return 0;
}

代码说明:

  1. 宏定义
    • #define _USE_MATH_DEFINES 使得 math.h 库中的常量如 M_PI(圆周率)可以使用。虽然在这个示例中并未用到,但这对于涉及常量如 M_PIM_E 等的应用很有用。
  2. 数学函数调用
    • sqrt() 计算平方根。
    • fabs() 计算绝对值。
    • ceil() 计算向上取整。
    • floor() 计算向下取整。
    • fmod() 计算两个数的余数。
  3. 格式化输出
    • 使用 %.2f 来指定浮点数输出两位小数。

示例输出:

sqrt(16.00) = 4.00
fabs(-5.70) = 5.70
ceil(2.30) = 3.00
floor(2.70) = 2.00
fmod(5.50, 2.00) = 1.50

其他常见数学函数(可供参考):

  • sin(x): 返回 x 的正弦值(x 的单位是弧度)。
  • cos(x): 返回 x 的余弦值。
  • tan(x): 返回 x 的正切值。
  • exp(x): 返回 e^x 的值(e 是自然对数的底数)。
  • log(x): 返回 x 的自然对数(以 e 为底)。
  • pow(x, y): 返回 xy 次方。

这些数学函数可以帮助你进行各种数值计算,涵盖了从简单的四则运算到更复杂的三角函数、对数函数等。


226. pow 函数示例

在这段代码中,使用了 pow 函数来计算圆的面积。pow(x, y) 用于计算 xy 次方,返回 x^y 的结果。在这个例子中,pow(radius, 2) 用于计算圆的半径的平方。

代码分析:

  1. pow(x, y):
    • powmath.h 库中的一个数学函数,用于计算 xy 次方,即 x^y
    • 在此示例中,pow(radius, 2) 计算半径的平方,公式为 π×r2\pi \times r^2,用于求圆的面积。
  2. 圆的面积计算
    • 圆的面积公式:A=π×r2A = \pi \times r^2,其中 rr 是圆的半径,π\pi 是圆周率(通过 M_PI 获得)。
  3. scanf_s
    • scanf_sscanf 的安全版本,它能防止缓冲区溢出。在这里,它被用来从标准输入读取一个 double 类型的圆的半径。

完整代码:

#define _USE_MATH_DEFINES
#include <stdio.h>
#include <inttypes.h>
#include <math.h>

int main(void) {

    double radius = 0.0;
    double circle_area = 0.0;

    printf("请输入圆的半径:\n");

    // 读取用户输入的半径
    scanf_s("%lf", &radius);

    // 计算圆的面积,公式:area = π * r^2
    circle_area = M_PI * pow(radius, 2);

    // 输出圆的面积
    printf("圆的面积是:%.2f\n", circle_area);

    return 0;
}

代码说明:

  1. scanf_s("%lf", &radius)
    • 用于从标准输入读取一个 double 类型的值,表示圆的半径。%lf 是格式说明符,用于读取 double 类型的数值。
  2. circle_area = M_PI \* pow(radius, 2)
    • M_PImath.h 库中定义的圆周率常量(π),pow(radius, 2) 用于计算圆的半径的平方,最后将结果乘以 π 计算圆的面积。
  3. printf("圆的面积是:%.2f\n", circle_area)
    • 使用 printf 输出圆的面积,%.2f 格式说明符用于将浮点数输出为两位小数。

示例输出:

请输入圆的半径:
5
圆的面积是:78.54

解释:

  • 假设输入的圆的半径是 5,程序会计算出 A=π×52=3.14159×25=78.53975A = \pi \times 5^2 = 3.14159 \times 25 = 78.53975,并将结果格式化为两位小数,输出 78.54

其他常见 pow 函数应用:

  • 计算平方pow(x, 2) 用于计算一个数的平方。
  • 计算立方pow(x, 3) 用于计算一个数的立方。
  • 计算任意次方pow(x, y) 可以计算任意的次方数,比如计算 x 的 5 次方,pow(x, 5)

注意事项:

  • pow 函数通常用于需要浮点数结果的情况,返回值为 double 类型。
  • 在一些数学运算中,pow 可能会存在精度误差,尤其是在非常大的指数运算中。

231. time.h 与时间戳的使用

在这段代码中,使用了 time.h 库来获取当前的时间戳,并将其转换为本地时间和协调世界时(UTC)。代码通过 time_t 类型获取时间戳,然后使用 localtime_sgmtime_s 转换成结构体 tm,再使用 strftime 格式化输出时间。

代码分析:

  1. 获取当前时间戳
    • time_t now = time(NULL);
    • 这里 time(NULL) 获取当前的时间戳(即自 1970年1月1日以来的秒数)。time_t 是一个数据类型,通常用于表示时间戳。
  2. 转换为本地时间
    • struct tm local_time;
    • localtime_s(&local_time, &now);
    • localtime_s 函数将时间戳转换为本地时间。它返回一个 tm 结构体,包含年、月、日、时、分、秒等字段。
  3. 转换为 UTC 时间
    • struct tm utc_time;
    • gmtime_s(&utc_time, &now);
    • gmtime_s 函数将时间戳转换为协调世界时(UTC)。与 localtime_s 类似,gmtime_s 返回一个 tm 结构体,表示 UTC 时间。
  4. 时间格式化
    • strftime(local_time_str, sizeof(local_time_str), "%Y-%m-%d %H:%M:%S", &local_time);
    • strftime 函数将 tm 结构体转换为指定格式的字符串。"%Y-%m-%d %H:%M:%S" 格式表示年月日 时分秒(24小时制)。
    • 对本地时间和 UTC 时间分别进行格式化,并存储到 local_time_strutc_time_str 中。
  5. 打印结果
    • 使用 printf 输出当前的时间戳、本地时间和 UTC 时间。

完整代码:

#include <stdio.h>
#include <inttypes.h>
#include <time.h>

int main(void) {
    // 获得当前的时间戳
    time_t now = time(NULL);

    // 转换成本地时间
    struct tm local_time;
    localtime_s(&local_time, &now);

    // 转换为协调世界时(UTC)
    struct tm utc_time;
    gmtime_s(&utc_time, &now);

    char local_time_str[80];
    char utc_time_str[80];

    // 格式化时间
    strftime(local_time_str, sizeof(local_time_str), "%Y-%m-%d %H:%M:%S", &local_time);
    strftime(utc_time_str, sizeof(utc_time_str), "%Y-%m-%d %H:%M:%S", &utc_time);

    // 输出时间戳、本地时间和UTC时间
    printf("当前时间戳:%" PRIdMAX "\n", (intmax_t)now);
    printf("本地时间:%s\n", local_time_str);
    printf("UTC时间:%s\n", utc_time_str);

    return 0;
}

代码解释:

  1. 时间戳输出

    • printf("当前时间戳:%" PRIdMAX "\n", (intmax_t)now);
    • time_t 类型在不同的系统上可能具有不同的大小,因此使用 PRIdMAX 来适配平台,确保时间戳的正确输出。
  2. 时间格式化

    • strftime
      

      用于将

      tm
      

      结构体转换为自定义格式的时间字符串。格式字符串

      %Y-%m-%d %H:%M:%S
      

      表示:

      • %Y:四位年份
      • %m:两位月份
      • %d:两位日期
      • %H:24小时制的小时
      • %M:分钟
      • %S:秒数
  3. localtime_sgmtime_s

    • 这两个函数是线程安全的版本,分别用于获取本地时间和 UTC 时间。它们将转换后的时间存储在传入的 tm 结构体中。

示例输出:

当前时间戳:1640995200
本地时间:2022-01-01 00:00:00
UTC时间:2022-01-01 00:00:00

解释:

  • current_time 是当前的时间戳,表示自 1970年1月1日以来的秒数。
  • local_time_str 表示当前本地时间,例如 2022-01-01 00:00:00
  • utc_time_str 表示当前的 UTC 时间(也可以是 2022-01-01 00:00:00,如果本地时区与 UTC 相同)。

小结:

  • time.h 提供了获取时间戳的功能,以及将时间戳转换为本地时间和 UTC 时间的函数。
  • strftime 函数使得时间格式化更加灵活,能够按需要自定义输出的时间格式。

235. malloc 函数动态内存分配的使用与释放

在这段代码中,介绍了如何使用 malloc 动态分配内存,并且演示了如何使用 free 函数释放分配的堆内存。此代码展示了静态数组与动态数组之间的区别,特别是在内存分配、生命周期、作用域和释放方面。

代码分析:

  1. 静态数组的声明与初始化

    int static_arr[5] = { 1,2,3,4,5 };
    
    • static_arr 是一个静态数组,其大小和生命周期在编译时就已经确定。数组的元素会被分配在栈上,当函数执行完毕时,这些元素会被自动销毁。
  2. 动态数组的声明与初始化

    int* dynamic_arr = malloc(5 * sizeof(int));
    
    • malloc 用于在堆上分配指定大小的内存。这里,5 * sizeof(int) 表示为存储 5 个 int 类型数据所需的内存大小。malloc 返回的是一个 void* 类型的指针,指向这块已分配的内存。
    • 如果 malloc 分配内存失败,它会返回 NULL,因此我们需要检查返回值。
    • malloc 分配的内存不会自动初始化,因此需要手动填充数据。
  3. 动态数组的使用

    for (size_t i = 0; i < 5; i++) {
        dynamic_arr[i] = (i + 1) * 10;
    }
    
    • 在这段代码中,我们将动态数组 dynamic_arr 填充为一组数据:10, 20, 30, 40, 50
  4. 打印动态数组的内容

    for (size_t i = 0; i < 5; i++) {
        printf("%d ", dynamic_arr[i]);
    }
    
    • 使用 for 循环打印动态数组的内容。
  5. 释放动态内存

    free(dynamic_arr);
    
    • 动态分配的内存需要使用 free 显式释放,以避免内存泄漏。释放后,指针不再指向有效的内存区域,但该指针本身并未被置为 NULL,这需要开发者自己注意。
  6. 错误处理

    if (dynamic_arr == NULL) {
        perror("动态数组分配失败");
        exit(EXIT_FAILURE);
    }
    
    • malloc 如果分配失败,会返回 NULL。通过检查返回值,我们可以捕获这个错误并进行适当的错误处理,例如打印错误信息并退出程序。

完整代码:

#include <stdio.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

int main(void) {

    // 静态数组的声明和初始化
    // 编译时候就确定了,整个数组的大小和生命周期连同作用域,都一起决定了。
    // 分配到栈上
    int static_arr[5] = { 1,2,3,4,5 };
    printf("静态数组的内容\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", static_arr[i]);
    }
    printf("\n");

    // 动态内存分配               int arr[5]
    // 分配到堆上
    int* dynamic_arr = malloc(5 * sizeof(int));
    if (dynamic_arr == NULL) {
        perror("动态数组分配失败");
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < 5; i++) {
        dynamic_arr[i] = (i + 1) * 10;
    }

    puts("动态数组的内容:");
    for (size_t i = 0; i < 5; i++) {
        printf("%d ", dynamic_arr[i]);
    }
    
    // 堆内存要手动释放,因为不是简单的局部变量那么简单,局部变量会在函数执行完之后自动释放,而堆不会。
    free(dynamic_arr);

    return 0;
}

输出示例:

静态数组的内容
1 2 3 4 5 
动态数组的内容:
10 20 30 40 50

关键点总结:

  1. 静态数组
    • 在编译时就确定大小,内存分配在栈上,生命周期由作用域决定,函数结束时自动销毁。
  2. 动态数组
    • 使用 malloc 在堆上分配内存,大小在运行时决定。
    • 需要显式释放内存(使用 free),否则会导致内存泄漏。
  3. mallocfree
    • malloc 用于分配动态内存,free 用于释放动态内存。
    • 使用 malloc 时,必须确保分配成功,否则返回 NULL
  4. perror
    • perror 用于输出与 errno 相关的错误信息。如果 malloc 返回 NULL,我们使用 perror 来输出错误信息。

可能的问题与注意事项:

  • 使用 malloc 分配的内存必须手动释放,否则可能导致内存泄漏。
  • 在访问动态数组时,要确保内存已经分配成功。

244. Function Pointer(函数指针)的概念

在 C 语言中,函数指针是指向函数的指针。它允许你将函数作为参数传递、调用函数,或者动态地选择要执行的函数。函数指针可以用来实现回调机制、事件驱动编程等。

代码解析:

1. 函数指针声明
int (*myFunctionPointer)(int, int);
  • 这行代码声明了一个函数指针 myFunctionPointer,它指向返回类型为 int、参数类型为两个 int 的函数。

  • 语法解释:

    • int (*myFunctionPointer)(int, int);
      

      可以拆解为:

      • myFunctionPointer 是一个指针,指向一个接受两个 int 参数并返回 int 的函数。
2. 指针指向函数
myFunctionPointer = add;
  • myFunctionPointer 被赋值为函数 add 的地址。此时,myFunctionPointer 就指向了 add 函数。
3. 通过函数指针调用函数
int result = myFunctionPointer(2, 3);
  • 使用 myFunctionPointer 指向的函数调用语法,调用了 add(2, 3) 并将结果存储在 result 中。
  • 注意:这实际上等同于 int result = add(2, 3);,但是通过函数指针的方式调用。
4. 回调函数概念
  • 函数指针可以用于回调函数的实现。回调函数是一种机制,允许你将一个函数作为参数传递给另一个函数,然后在特定的事件或条件下被调用。
  • 在这个例子中,回调机制没有完全实现,但可以理解为 myFunctionPointer 代表一个可以在后续执行时调用的函数。

完整代码:

#include <stdio.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

// 函数声明
int add(int a, int b);

// 函数指针声明
int (*myFunctionPointer)(int, int);

int main(void) {

    // 将函数指针指向 add 函数
    myFunctionPointer = add;

    // 通过指针调用函数
    int result = myFunctionPointer(2, 3);
    printf("The result is %d\n", result);  // 输出结果:5

    // 这里可以实现回调函数的概念:
    // 回调函数用于事件驱动编程,可以通过传递不同的函数来实现不同的行为。

    return EXIT_SUCCESS;
}

// 函数定义
int add(int a, int b) {
    return a + b;
}

输出示例:

The result is 5

解释:

  1. myFunctionPointer 是一个指向函数的指针,它指向返回 int 类型、接受两个 int 参数的函数。
  2. 通过 myFunctionPointer = add;add 函数的地址赋值给 myFunctionPointer,从而使得 myFunctionPointer 成为 add 函数的别名。
  3. 使用 myFunctionPointer(2, 3) 调用 add 函数,返回结果为 5

函数指针的实际用途:

  1. 回调函数:在一些库或框架中,你可以通过回调函数来处理事件(例如 GUI 库、网络库等)。你将一个函数作为参数传递给其他函数,在需要的时候调用它。
  2. 动态选择函数:使用函数指针,你可以根据不同的条件选择执行不同的函数,这为灵活的代码实现提供了可能。
  3. 简化代码:通过函数指针,可以避免大量的 ifswitch 语句,提高代码的可读性和可扩展性。

小结:

  • 函数指针 是 C 语言的一种强大功能,可以动态地指向和调用函数。
  • 主要用途包括回调机制动态函数调用

254. 指针的作用域和生命周期

在这段代码中,我们展示了 指针的作用域生命周期 如何影响指针的使用。代码包含一个局部指针 local_ptr 和一个全局指针 global_ptr,它们的作用域和生命周期不同。

代码解析:

1. 全局指针 global_ptr
int* global_ptr;
  • global_ptr 是一个全局指针,在整个程序中都可以访问。它的生命周期是与程序的运行时间相同的,即程序开始时分配内存,直到程序结束时释放。
2. 局部指针 local_ptr
int* local_ptr = &local;
  • local_ptr 是一个局部指针,它的作用域仅限于函数 function 内部。当 function 函数执行结束时,local_ptr 将被销毁。
3. 动态内存分配
global_ptr = (int*)malloc(sizeof(int));
  • global_ptr 被分配了动态内存,指向 int 类型的内存空间。在 function 函数执行期间,global_ptr 仍然有效,并且它所指向的内存区域的生命周期由 malloc 分配控制,直到手动调用 free 释放。
4. 局部指针访问
printf("Inside function: local_ptr points to %d\n", *local_ptr);
  • 这行代码访问了 local_ptr 所指向的内存(即 local 变量)。虽然 local_ptr 的作用域仅限于函数内,但它在函数内部是有效的。
5. 全局指针在 main 函数中的使用
printf("Outside function: global_ptr points to %d\n", *global_ptr);
  • global_ptr 是一个全局指针,可以在 main 函数中访问并使用它所指向的内存(即动态分配的内存)。因此,尽管 global_ptrfunction 中被赋值,但它仍然可以在 main 中使用。
6. 释放动态内存
free(global_ptr);
  • free(global_ptr) 释放了通过 malloc 分配的内存。因为 global_ptr 是一个全局指针,所以它一直有效直到被 free 释放。

代码实现:

#include <stdio.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

// 全局指针声明
int* global_ptr;

void function() {
    int local = 5;  // 局部变量

    int* local_ptr = &local;  // 局部指针,指向局部变量

    // 动态分配内存,global_ptr 指向该内存
    global_ptr = (int*)malloc(sizeof(int));

    if (global_ptr != NULL) {
        *global_ptr = 10;  // 给分配的内存赋值
    }

    // 打印局部指针所指向的值
    printf("Inside function: local_ptr points to %d\n", *local_ptr);
}

int main(void) {
    // 调用 function
    function();

    // 打印 global_ptr 所指向的值
    printf("Outside function: global_ptr points to %d\n", *global_ptr);

    // 释放动态内存
    free(global_ptr);

    return EXIT_SUCCESS;
}

输出:

Inside function: local_ptr points to 5
Outside function: global_ptr points to 10

解释:

  • local_ptr 是指向局部变量 local 的指针,它的作用域仅限于 function 函数。因此,当 function 执行结束时,local_ptr 就会失效。
  • global_ptr 是一个全局指针,它在 main 函数中依然有效,指向动态分配的内存。在 function 中为其分配内存并赋值为 10 后,global_ptrmain 中依然可以访问。
  • 使用 malloc 动态分配内存时,分配的内存位于堆区,并且该内存会一直有效,直到通过 free 显式释放。

作用域与生命周期:

  • 作用域 决定了指针变量在哪个范围内可访问。局部指针的作用域仅限于函数内部,而全局指针在整个程序中都有效。
  • 生命周期 决定了指针所指向的内存或变量在内存中的存活时间。局部变量的生命周期通常与函数的执行时间相同,而全局变量的生命周期通常与程序的执行时间相同。动态分配的内存则由 mallocfree 控制其生命周期。

小结:

  1. 局部指针 的生命周期与它所在的函数相同,出函数后被销毁。
  2. 全局指针 的生命周期与程序运行的生命周期相同,直到程序结束或手动释放。
  3. 动态内存分配 使用 malloc,生命周期由程序员通过 free 来管理。

274. 函数传递数组

在这段代码中,展示了如何将数组传递给函数。在 C 语言中,数组的名称本质上是指向其第一个元素的指针。因此,当你将数组传递给函数时,实际上传递的是数组的地址。

关键点分析:

  1. 数组作为函数参数
    • void printArray(int arr[], int size) 中的 arr[] 其实是指向整数的指针。函数接收到的是数组的首地址,而不是整个数组。
    • sizeof(numbers) / sizeof(numbers[0]) 用来计算数组的大小,这样可以传递正确的数组长度。
  2. 传递数组到函数
    • 数组名(如 numbers)在传递给函数时会被隐式转换为指向数组首元素的指针。
    • 这意味着在 printArray 函数中,arr 就是一个指向整数的指针,可以像普通数组一样访问。
  3. 两种传递数组的方式
    • 传递整个数组的首地址:printArray(numbers, sizeof(numbers) / sizeof(numbers[0]))
    • 传递数组的首元素的地址(显式地使用地址运算符 &):printArray(&numbers[0], sizeof(numbers) / sizeof(numbers[0]))

代码解释:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <Windows.h>
#include <ctype.h>

// 函数声明
void printArray(int arr[], int size);

int main(void) {
    // 数组声明和初始化
    int numbers[] = { 1,2,3,4,5 };
    int numbers_2[] = { 2,3,4,5,6 };
    int numbers_3[] = { 32,3,4,5,6 };

    // 传递数组给 printArray 函数
    printArray(numbers, sizeof(numbers) / sizeof(numbers[0]));
    printArray(&numbers[0], sizeof(numbers) / sizeof(numbers[0]));
    printArray(numbers_2, sizeof(numbers_2) / sizeof(numbers_2[0]));
    printArray(numbers_3, sizeof(numbers_3) / sizeof(numbers_3[0]));
}

// 打印数组的函数定义
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);  // 打印数组的每个元素
    }
    printf("\n");
}

代码运行步骤:

  1. 数组声明与初始化

    int numbers[] = { 1,2,3,4,5 };
    int numbers_2[] = { 2,3,4,5,6 };
    int numbers_3[] = { 32,3,4,5,6 };
    
  2. 传递数组到 printArray 函数

    printArray(numbers, sizeof(numbers) / sizeof(numbers[0]));
    printArray(&numbers[0], sizeof(numbers) / sizeof(numbers[0]));
    
    • sizeof(numbers) / sizeof(numbers[0]) 用来计算数组的长度。这里的 sizeof(numbers) 返回整个数组的大小,sizeof(numbers[0]) 返回数组元素的大小,因此两者相除即可得到数组的元素数量。
    • 通过 numbers&numbers[0] 传递数组到 printArray 函数,实际上都传递了数组的首地址。
  3. printArray 函数

    • printArray 函数中,接收到的是指向数组的指针 arr[],然后通过遍历 arr[],打印每个元素。

输出:

1 2 3 4 5 
1 2 3 4 5 
2 3 4 5 6 
32 3 4 5 6 

总结:

  • 在 C 语言中,数组作为参数传递给函数时,实际上是传递了数组的首地址。你可以通过数组名或首元素的地址显式传递。
  • 无论是传递 numbers 还是 &numbers[0],都能正确地传递数组的地址到 printArray 函数,并且通过数组指针访问每个元素。
  • 数组的大小通过 sizeof(numbers) / sizeof(numbers[0]) 计算得到,确保在传递数组时能够正确获取数组的长度。

注意事项:

  • 如果数组是通过指针传递给函数的,必须确保在函数内部传递正确的数组大小,以便正确处理数组元素。
本系统采用Python编程语言中的Flask框架作为基础架构,实现了一个面向二手商品交易的网络平台。该平台具备完整的前端展示与后端管理功能,适合用作学术研究、课程作业或个人技术能力训练的实际案例。Flask作为一种简洁高效的Web开发框架,能够以模块化方式支持网站功能的快速搭建。在本系统中,Flask承担了核心服务端的角色,主要完成请求响应处理、数据运算及业务流程控制等任务。 开发工具选用PyCharm集成环境。这款由JetBrains推出的Python专用编辑器集成了智能代码提示、错误检测、程序调试与自动化测试等多种辅助功能,显著提升了软件编写与维护的效率。通过该环境,开发者可便捷地进行项目组织与问题排查。 数据存储部分采用MySQL关系型数据库管理系统,用于保存会员资料、产品信息及订单历史等内容。MySQL具备良好的稳定性和处理性能,常被各类网络服务所采用。在Flask体系内,一般会配合SQLAlchemy这一对象关系映射工具使用,使得开发者能够通过Python类对象直接管理数据实体,避免手动编写结构化查询语句。 缓存服务由Redis内存数据库提供支持。Redis是一种支持持久化存储的开放源代码内存键值存储系统,可作为高速缓存、临时数据库或消息代理使用。在本系统中,Redis可能用于暂存高频访问的商品内容、用户登录状态等动态信息,从而加快数据获取速度,降低主数据库的查询负载。 项目归档文件“Python_Flask_ershou-master”预计包含以下关键组成部分: 1. 应用主程序(app.py):包含Flask应用初始化代码及请求路径映射规则。 2. 数据模型定义(models.py):通过SQLAlchemy声明与数据库表对应的类结构。 3. 视图控制器(views.py):包含处理各类网络请求并生成回复的业务函数,涵盖账户管理、商品展示、订单处理等操作。 4. 页面模板目录(templates):存储用于动态生成网页的HTML模板文件。 5. 静态资源目录(static):存放层叠样式表、客户端脚本及图像等固定资源。 6. 依赖清单(requirements.txt):记录项目运行所需的所有第三方Python库及其版本号,便于环境重建。 7. 参数配置(config.py):集中设置数据库连接参数、缓存服务器地址等运行配置。 此外,项目还可能包含自动化测试用例、数据库结构迁移工具以及运行部署相关文档。通过构建此系统,开发者能够系统掌握Flask框架的实际运用,理解用户身份验证、访问控制、数据持久化、界面动态生成等网络应用关键技术,同时熟悉MySQL数据库运维与Redis缓存机制的应用方法。对于入门阶段的学习者而言,该系统可作为综合性的实践训练载体,有效促进Python网络编程技能的提升。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值