Linux基础支持以及C程序开发工具实验

实验名称:Linux基础支持以及C程序开发工具实验

实验类型:验证性、综合性、设计性

实验目的及要求:

1.熟悉Linux运行、开发环境。

2.掌握C语言编辑器的使用、gcc编译器的使用、gdb调试器的使用方法。

实验原理:1.Linux程序设计遵循的标准 2.C语言结构体 3递归调用

实验内容:

1.安装操作系统和开发环境

(1)安装Linux系统或虚拟机(建议Ubuntu 22.04 LTS)。

(2)写出你所装系统的发行版本和内核版本。

(3)安装编辑器(自选)、gcc编译器以及gdb调试工具。

2.编程

(1)编写一个C程序factorial.c。这个程序用于计算n的阶乘。程序可以接收输入的n,使用递归方法计算n的阶乘值fact并输出。使用gcc工具编译factorial.c程序使其可被gdb调试。调试中,设置断点观察fact的变化情况,使用gdb工具观察该程序递归调用过程,记录当fact>1000时的n值。

#include 

int factorial(int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

int main() {
    int n;
    printf("请输入一个整数 n:");
    scanf("%d", &n);
    
    int fact = factorial(n);
    printf("%d 的阶乘是 %d\n", n, fact);

    return 0;
}

使用 gcc 工具编译这个程序并使其可以被 gdb 调试

gcc -g factorial.c -o factorial

当 fact 的值大于 1000 时,你可以使用 gdb 的观察功能记录 n 的值。以下是一种方式:

1. 进入 gdb 调试模式:在命令行中输入 `gdb factorial`。
2. 设置断点:输入 `break factorial`。
3. 启动程序:输入 `run`。
4. 当程序停在断点处时,使用以下命令观察变量 n 的值:
   - 输入 `print n` 打印当前 n 的值。
   - 输入 `condition $1 > 1000` 设定观察条件,当 n 的值大于 1000 时触发。
   - 输入 `commands 1` 打开命令列表。
   - 输入 `silent` 关闭输出。
   - 输入 `continue` 继续执行程序。
   - 输入 `end` 结束命令列表。
5. 继续执行程序:输入 `continue`。
6. 当 n 的值大于 1000 时,gdb 将停在断点处。你可以使用 `print n` 命令观察 n 的值。
7. 若要继续执行程序,请输入 `continue`。
8. 当程序终止时,输入 `quit` 退出 gdb。

在观察变量 n 时,你可以记录下触发条件的 n 值。这样你就可以知道当 fact 大于 1000 时的 n 值是多少。请注意,由于递归的特性,调试过程中断点可能会多次触发,每次触发时的 n 值可能不同。

(2)在Linux环境下,使用C编程实现下面的要求。输入至少3棵银杏树的地径、胸径、冠幅,保存为结构体数组,将输入的信息写入文件保存。

#include 

#define MAX_TREES 3

typedef struct {
    float trunkDiameter;
    float chestDiameter;
    float crownWidth;
} GinkgoTree;

void saveTreesInfoToFile(const GinkgoTree trees[]) {
    FILE *file = fopen("trees_info.txt", "w");
    if (file == NULL) {
        printf("无法打开文件。\n");
        return;
    }

    for (int i = 0; i < MAX_TREES; i++) {
        fprintf(file, "地径: %.2f cm, 胸径: %.2f cm, 冠幅: %.2f cm\n",
                trees[i].trunkDiameter, trees[i].chestDiameter, trees[i].crownWidth);
    }

    fclose(file);
    printf("树木信息已成功保存到文件 trees_info.txt。\n");
}

int main() {
    GinkgoTree trees[MAX_TREES];

    printf("请输入至少 %d 棵银杏树的信息:\n", MAX_TREES);
    for (int i = 0; i < MAX_TREES; i++) {
        printf("第 %d 棵树:\n", i + 1);
        printf("地径(单位:cm):");
        scanf("%f", &trees[i].trunkDiameter);
        printf("胸径(单位:cm):");
        scanf("%f", &trees[i].chestDiameter);
        printf("冠幅(单位:cm):");
        scanf("%f", &trees[i].crownWidth);
    }

    saveTreesInfoToFile(trees);

    return 0;
}

定义了一个 GinkgoTree 的结构体,用于存储银杏树的地径、胸径和冠幅。在 main 函数中,使用循环依次输入至少 3 棵银杏树的信息,并将其保存在 trees 结构体数组中。然后,调用 saveTreesInfoToFile 函数将树木信息写入名为 trees_info.txt 的文件中。

请确保在编译和运行代码之前,已在当前目录下创建了可写入的 trees_info.txt 文件。完成后,树木的信息将被写入该文件中。

(3)使用man分析strerror函数和perror函数,尝试使用strerror函数实现perror函数的功能。

`strerror` 函数和 `perror` 函数是用于处理错误信息的函数,下面是对这两个函数的简要说明:

1. `strerror` 函数:
   - 函数定义:`char *strerror(int errnum);`
   - 功能:将给定的错误码 `errnum` 转换为对应的错误信息字符串。
   - 返回值:返回指向错误信息字符串的指针。

2. `perror` 函数:
   - 函数定义:`void perror(const char *s);`
   - 功能:根据全局的错误码 `errno` 打印对应的错误信息字符串,并在其前面加上字符串 `s`。
   - 返回值:无。

要使用 `strerror` 实现 `perror` 的功能,可以编写一个自定义函数,模拟 `perror` 的行为。下面是一个实现示例:

#include 
#include  // 包含 strerror 函数的头文件
#include   // 包含 errno 变量的头文件

void myPerror(const char *s) {
    // 使用 strerror 函数将 errno 转换为错误信息字符串
    const char *errorMsg = strerror(errno);

    // 根据需要,可以将错误信息字符串与自定义的字符串连接起来
    printf("%s: %s\n", s, errorMsg);
}

int main() {
    FILE *file = fopen("nonexistent.txt", "r");
    if (!file) {
        myPerror("打开文件失败");
    }

    return 0;
}

在上述示例中,我们定义了一个自定义函数 `myPerror`,类似于 `perror`。它接收一个字符串 `s` 作为参数,并使用 `strerror` 函数将全局的错误码 `errno` 转换为错误信息字符串。

在 `main` 函数中,我们尝试打开一个不存在的文件,并在失败时调用 `myPerror` 函数输出错误信息。

这样,通过使用 `strerror` 函数,我们可以实现类似 `perror` 的错误处理功能。

你可能感兴趣的:(linux,c语言,运维)