火龙信奥
  • 首页
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

2025/26 冬季学期 第 5 次实验作业

作者: 作者的头像   huolong , 时间:2025-11-23 17:57:35 , 所有人可见, 阅读  12

断点调试

针对习题 1 的逐题解答(基于上述代码) a) 在 int andereZahl = 8; 这一行设断点,然后逐步执行。当某行 x 被高亮时,哪些行已执行?调试器如何处理条件判断?

答:

当第 x 行被高亮(即将执行)时,第 x 行之前的所有语句都已执行完毕。 例如,当高亮到 printf("Zahlenvergleich\n"); 时,eineZahl(声明)、andereZahl = 8、text1 = new...、text2[20] 声明都已完成。 调试器遇到 if 条件时: 会先计算整个条件表达式的布尔值(如 eineZahl == andereZahl)。 然后根据结果跳转到对应的分支。 在“单步跳过”(Step Over)模式下,不会进入未被选中的分支,而是直接执行被选中分支的第一条语句或跳过整个 if-else 结构。 b) 在 printf("Zahlenvergleich\n"); 处设断点。此时各变量的值是多少?text2 数组元素是什么?是否稳定?

答:

eineZahl:未初始化,其值是随机垃圾值(例如可能是 -858993460 或其他任意整数)。 andereZahl:已初始化为 8,值稳定。 text1:是一个有效的指针(指向堆上 20 字节内存),但指向的内容未初始化,是垃圾数据。 text2:是一个栈上数组,全部 20 个元素都是未初始化的垃圾字节(例如可能是 0xCC, 0xFD, 或其他随机值)。 稳定性:eineZahl 和 text2 的值在多次运行中不稳定,每次运行都可能不同。 解释:这是因为 C/C++ 不会自动初始化局部变量。它们的初始值就是内存中原来的内容(“脏数据”)。这是常见的 Bug 源头,调试器能直观暴露这个问题。 c) 声明两个 char 变量:'q' 和 '&'。调试器能提供什么信息?

答: 在调试器的 Variables(变量)视图 中,你可以看到:

字符形式:'q' 和 '&' 十进制 ASCII 码:113 和 38 十六进制 ASCII 码:0x71 和 0x26 这揭示了字符在计算机内部是以整数编码(ASCII/Unicode)存储的。

d) 在 else if (andereZahl > eineZahl) 行设断点,运行到此处,将 andereZahl 改为 15,再继续运行。会发生什么?

答:

程序运行到该断点时,原始值为:eineZahl = 9, andereZahl = 8。 此时条件 andereZahl > eineZahl(即 8 > 9)为 false,正常情况下会进入 else 分支。 但你在调试器中将 andereZahl 手动改为 15 后: 条件变为 15 > 9 → true 因此,程序会执行这个 else if 分支,输出: text 编辑 Der kleinere Wert ist eineZahl: 9 结论:调试器允许动态修改变量,从而改变程序的执行路径,用于测试不同场景。

#include <cstdio>  // 或保留 stdio.h 也可以,但这是 C 风格

int main() {
    int eineZahl;           // 未初始化!
    int andereZahl = 8;     // 初始化为 8
    char* text1 = new char[20];  // 动态分配,但未初始化内容
    char text2[20];         // 栈上数组,未初始化!

    printf("Zahlenvergleich\n");  // ← 断点 b) 设在这里

    eineZahl = 9;  // 在此之后才赋值

    if (eineZahl == andereZahl) {
        printf("Beide Werte sind gleich gross: %d\n", eineZahl);
    }
    else if (andereZahl > eineZahl) {  // ← 断点 d) 设在这里
        printf("Der kleinere Wert ist eineZahl: %d\n", eineZahl);
    }
    else {
        printf("Der kleinere Wert ist andereZahl: %d\n", andereZahl); // 注意:原题这里打印错了,应为 andereZahl
    }

    delete[] text1;
    return 0;
}

解释:这是因为 C/C++ 不会自动初始化局部变量。它们的初始值就是内存中原来的内容(“脏数据”)。这是常见的 Bug 源头,调试器能直观暴露这个问题。

枚举类型,结构体的应用

习题 2:宝可梦输出 (7 分) 六只宝可梦的类型、名称和等级定义如下:

火系 = {(小火龙, 等级 7), (六尾, 等级 7)} 水系 = {(杰尼龟, 等级 3), (可达鸭, 等级 2)} 草系 = {(妙蛙种子, 等级 6), (蔓藤怪, 等级 3)} 请创建一个名为 Praktikum_5/Aufgabe_2 的新项目,并将提供的文件 pokemon.cpp 添加进去。

a) 在模板中定义必要的数据类型来表示一只宝可梦。为此,请定义一个名为 PokeType 的枚举类型 (enum),用于表示三种宝可梦类型(火、水、草)。接着,定义一个名为 Pokemon 的结构体 (struct),它包含一个名称(最多 20 个字符)、一个类型 (PokeType) 和一个等级 (int)。(2 分)

b) 将上述六只宝可梦全部以 Pokemon 结构体的形式存储在一个名为 minipokedex 的数组中。然后编写一个辅助函数 void printpokemon(struct Pokemon poke),该函数以如下格式在控制台上输出单只宝可梦: 名称 (等级 N, 类型 PokeType) 在 main 函数中,使用此函数输出所有宝可梦。(1 分)

c) 使用一个辅助函数 void kampf(struct Pokemon pokeA, struct Pokemon pokeB) 来模拟两只宝可梦之间的对战。通过根据战斗力进行条件判断来确定对战的胜者(或平局)。战斗力的计算公式如下: 战斗力 = 等级 * 效果

效果规则如下:

火系攻击对草系的效果为 2 倍。 水系攻击对火系的效果为 3 倍。 草系攻击对水系的效果为 2 倍。 所有其他攻击(同类型或反向克制)的效果为 1 倍。 该函数应在控制台上始终输出包含两只参战宝可梦的对战结果。输出示例如下: 小火龙 (等级 7, 类型 火) 战胜了 妙蛙种子 (等级 6, 类型 草) 或者 对战以平局告终,因为 小火龙 (等级 7) 和 六尾 (等级 7) 的实力相同。

在 main 函数中读取两个索引,并模拟对应宝可梦之间的对战。(4 分)


/*
 * Speichern und Ausgeben von Pokémon
 */
#include <iostream>
using namespace std;

//============================================
// a1) Hier bitte den Aufz?hlungstyp "PokeType" für verschiedene Pokémon-Typen definieren
enum PokeType {
    Feuer,
    Wasser,
    Pflanze
};

// a2) Hier bitte die "Pokemon"-Struktur definieren, welche den Namen (nur bis zu 20 Zeichen lang) und Typen (PokeType) eines Pokémon beinhaltet
struct Pokemon {
    char name[21]; // 20 Zeichen + '\0'
    PokeType type;
    int level;
};

//============================================

//--------------------------------------------
// b1) Hier bitte ein Feld namens "minipokedex" mit den genannten Pokemon definieren
struct Pokemon minipokedex[6] = {
    {"Glumanda", Feuer, 7},
    {"Vulpix", Feuer, 7},
    {"Schiggy", Wasser, 3}, // Note: Corrected spelling from "Schiggym" to "Schiggy"
    {"Enton", Wasser, 2},
    {"Bisasam", Pflanze, 6},
    {"Tangela", Pflanze, 3}
};

// Hilfsfunktion zur Typumwandlung für die Ausgabe
const char* getTypeString(PokeType t) {
    switch (t) {
        case Feuer:   return "Feuer";
        case Wasser:  return "Wasser";
        case Pflanze: return "Pflanze";
        default:      return "Unbekannt";
    }
}

// b2) Hier bitte die Funktion printpokemon definieren
void printpokemon(struct Pokemon poke) {
    cout << poke.name << " (Level " << poke.level << ", Typ " << getTypeString(poke.type) << ")";
}

//--------------------------------------------


//............................................
// c1) Kampfausgang berechnen
void kampf(struct Pokemon pokeA, struct Pokemon pokeB) {
    // Effektivit?t von A gegen B berechnen
    double effA = 1.0;
    if (pokeA.type == Feuer && pokeB.type == Pflanze) {
        effA = 2.0;
    } else if (pokeA.type == Wasser && pokeB.type == Feuer) {
        effA = 3.0;
    } else if (pokeA.type == Pflanze && pokeB.type == Wasser) {
        effA = 2.0;
    }

    // Effektivit?t von B gegen A berechnen
    double effB = 1.0;
    if (pokeB.type == Feuer && pokeA.type == Pflanze) {
        effB = 2.0;
    } else if (pokeB.type == Wasser && pokeA.type == Feuer) {
        effB = 3.0;
    } else if (pokeB.type == Pflanze && pokeA.type == Wasser) {
        effB = 2.0;
    }

    double kraftA = pokeA.level * effA;
    double kraftB = pokeB.level * effB;

    if (kraftA > kraftB) {
        printpokemon(pokeA);
        cout << " gewinnt gegen ";
        printpokemon(pokeB);
        cout << endl;
    } else if (kraftB > kraftA) {
        printpokemon(pokeB);
        cout << " gewinnt gegen ";
        printpokemon(pokeA);
        cout << endl;
    } else {
        cout << "Der Kampf endet unentschieden, weil ";
        printpokemon(pokeA);
        cout << " und ";
        printpokemon(pokeB);
        cout << " gleich stark sind." << endl;
    }
}

//............................................

int main()
{
    //--------------------------------------------
    // b3) Bitte geben sie alle Pokémon im minipokedex aus
    for (int i = 0; i < 6; i++) {
        printpokemon(minipokedex[i]);
        cout << endl;
    }

    //--------------------------------------------

    //............................................
    // c2) Pokemon w?hlen und Kampf simulieren
    int idx1, idx2;
    cin >> idx1 >> idx2;
    kampf(minipokedex[idx1], minipokedex[idx2]);

    //............................................

    return 0;
}

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

©2026加盟我们 | 关于我们 | ACM课程 | 常见问题 | 成果墙 | 评测记录 | 浙ICP备2021013995号
在线画图 | OI WIki | 打字练习
火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码