这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

小熊猫C++

欢迎访问小熊猫C++的文档!本站内容仍在建设和完善之中,欢迎国内用户加入QQ群并提出宝贵意见。

QQ群号:367538953

入群口令:devcpp

1 - 概述

小熊猫C++的历史和简要介绍

小熊猫C++的目标用户群和需求

小熊猫C++是一个面向编程入门和初级用户的C/C++集成开发环境(IDE)。其主要的目标用户主要有以下几种:

  1. 编程入门用户,包括正在学习C/C++语言编程的大中小学生,以及从事这方面教学工作的教师们;
  2. 准备参加信息学/算法编程竞赛的用户,或者从事这方面培训的教师们;
  3. 使用C/C++语言编写小型程序和项目的用户

作者在中学时期曾参加NOI竞赛并获省赛第一名、全国三等奖;大学毕业后从事多年程序开发工作,曾参与优酷网的早期开发;后进入大学教学,有多年C语言、Python和软件工程教学经验。在教学过程中,作者发现,市面上缺少一个完善、好用的,面向初学者的C/C++集成开发环境:

  • 已有的C/C++ IDE,要么体积庞大,需要长时间的下载和安装,如VS和Qt Creator;
  • 要么安装复杂,需要手工配置,如VS Code;
  • 要么需要较好的计算机配置才能流畅运行,如VS Code+clangd和Clion;
  • 要么功能简陋,界面过时,缺少实时代码补全提示、实时错误提示等现代IDE必备的基本功能,如Dev-C++

作者认为,一个面向初学者、竞赛和教学的现代C/C++ IDE,至少具备下面的特征

  • 安装和使用直观简便,初学者不至于在还没有开始正式编程前就被复杂的安装和配置过程打消学习的热情;
  • 运行时对计算机配置要求不高,让更多经济条件一般的用户也能流畅的使用和学习;
  • 实时语法错误提示和直观易用的调试,尽量减少初学者编程试错的成本

但除了这几点外,作为一位软件工程课程的教师,作者认为还有很重要的一点,就是要尽量让用户在一开始就能够培养良好的编程习惯,所以:

  • 必须提供实时补全功能,这样用户才不会为了输入方便而使用尽可能简单的变量名
  • 自动缩进和排版,尽量让用户在一开始就能写出排版良好的程序
  • 提供更多的重构功能,尽量减少用户改进和完善程序结构的成本

这些构成了小熊猫C++最基本的需求假设。

小熊猫Dev-C++与Dev-C++

小熊猫C++前身——小熊猫Dev-C++的开发最初是从修改和完善Orwell Dev-C++ 5.11版本开始的。

Dev-C++最初是由bloodshed.net基于Delphi开发的轻量级windows开源C/C++集成开发环境,2003年后停止开发。后来orwell在其基础上继续进行完善,称为Orwell Dev-C++,2012年发布5.11版后停止开发,这也是国内目前使用最多的Dev-C++版本。

如前一节所述,Dev-C++是一个轻量的C/C++ IDE,但是其存在不少使用上的不便之处。比如,如果打开了符号补全功能,在输入’(‘时它会自动在后面增加一个对应’)’。在输入完括号之中的内容后,必须按->键跳过这个括号,然后再去输入后面的内容,这是很别扭的。所以很多用户在安装完Dev-C++之后,第一件事就是关掉符号补全功能;再比如说,它需要按ctrl+enter来打开补全提示,对于使用中文输入法的用户来说,必须手动去配置里修改快捷键,才能使用这个功能;还有,它的调试功能和按钮设计和主流IDE相差甚多,等等。

从2020年下半年开始,作者根据自己的编程和教学经验,在Orwell Dev-C++ 5.11基础上开始,以大约一周一次新版本发布的速度开始开发新的版本,并取名为小熊猫Dev-C++。最初的几个版本只是对一些基本编辑功能如符号补全等进行完善,以及对调试等用户界面进行调整;后来逐步开始对代码分析等核心模块进行大的修改,实现了对STL常用类的支持,并开始加入实时代码补全提示、实时语法错误提示等新的功能。

到2021年8月发布的最后一个版本(6.7.5版),小熊猫Dev-C++已经有了这些主要的改进:

  • 优化改进代码补全提示功能:
    • 实时显示补全提示
    • 补全#预处理指令
    • 补全#include头文件名
    • 补全C/C++关键字
    • 补全时Insert用户代码模板等
    • 支持STL容器类
    • 支持C++11智能指针
  • 修正了代码分析器的一系列bug,更好的支持C++,能够正确的解析和补全提示mingw gcc 9.2, mingw-w64 gcc 10.2自带标准头文件
  • 代码分析器优化和速度提升。代码载入、编辑和显示代码提示时无明显卡顿或停滞。
  • 在换行、保存文件时自动检查语法错误,用波浪线标记错误
  • 用户编辑界面增强和改进:
    • 支持打开、编辑和编译UTF-8编码的源代码文件
    • 输入时自动覆盖匹配的’}’,’>’,’)’等符号
    • 暗色配色方案(包括面板和工具栏)
    • 使用不同颜色区分局部变量、全局变量、函数、类定义等;
    • 使用不同颜色突出显示字符串中的转义字符
    • 使用不同颜色区分嵌套括号
    • 高亮当前文件中所有选中的单词等
  • 改进搜索功能和界面:
    • 增加对正则表达式的支持
    • 在搜索结果界面中改用树形结构保存和展示搜索历史
  • 改进调试功能和界面:
    • 增加调试工具栏
    • 在调试时准确更新监视窗口中的信息(如不同函数中的同名局部变量等)
    • 改进gdb主控台,模拟gdb命令行界面
    • 隐藏/显示发送给gdb的指令
    • 增加局部变量列表
    • 增加调用栈列表
    • 增加断点列表和设置断点条件
  • 增加重构功能,包括:
    • 符号重命名
    • 提取宏定义
  • 改进结构浏览器:
    • 正确显示当前程序中的宏、类型、类、变量和函数定义
    • 按照类型或者字典序进行排序
    • 显示/隐藏继承成员
    • 提升内容加载速度。对于大文件如GL/glew.h,加载时间从大于20秒减少到不到0.1秒(6.4-beta1版本加入)。
  • 增加文件视图,可以直接在视图中浏览和打开文件

小熊猫C++的新改进

随着开发的不断深入,作者发现,由于Dev-C++所使用的Delphi 7版本太过于老旧,在其基础上进行改进和开发越来越显得事倍功半。比如,为了支持现在流行的暗色程序界面,作者花了约1周时间去覆写Delphi的一些基本控件,最终的实现效果也仅仅是不那么难看。而对于高分辨率显示器、大字体支持等一些新的要求,即使是最新版的Delphi也根本就没有提供现成的解决方案。同时,作者也希望将来如果某一天学校开始推行去windows教学的话,新版的IDE能够直接在Linux下使用。

因此,在综合考虑之后,笔者决定使用Qt开发一个全新的C/C++ IDE。为了和之前的小熊猫Dev-C++区分,这个版本被命名为小熊猫C++。

小熊猫C++不仅仅是使用Qt对小熊猫Dev-C++功能的完全复制,它还引入了大量新的功能:

  • 兼容Linux系统
  • Git版本管理
  • 试题集(使用预定义的输入/输出数据运行和自动测试程序是否正确)
  • 基于Competitive Companion的OJ网站支持
  • 调试改进
    • 支持调试协议gdb/mi,以及基于该协议的调试内容显示改进
    • 内存视图
    • 支持调试时输入重定向(仅windows下启用gdb server模式时)
  • 用户界面改进
    • 完善的多显示器、高DPI大字体支持(包括字体和图标)
    • 更加美观的暗色主题支持
    • 更多的编辑器配色设置选项
    • 英文和中文可以使用不同的字体
    • Fire Coda等字体的连字显示支持
    • 支持设置颜色透明度
  • 编辑功能改进:
    • 更准确的自动缩进计算
    • 更准确的代码折叠计算
    • “使用特定的字符集打开文件”支持更多的字符集
  • 代码补全提示改进:
    • 全新的表达式解析处理,可以对更复杂的表达式(如(pNode+1)->)进行代码补全提示
    • 支持中文标识符
    • 支持C++ 14的using 类型别名定义
    • 支持C风格的枚举变量定义
    • 支持带参数的宏定义
  • 新增TODO视图
  • 全新的“在文件中查找/替换”界面
  • 全新的书签界面
  • 新增GLSL语言编辑支持等

2 - 基本功能与快捷键

基本编辑功能和快捷键的使用介绍

基本文件操作

新建文件

通过"文件"菜单中的"新建"→“新建源代码文件”,或者直接点击工具栏上的"新建源代码文件"按钮,就可以在小熊猫C++ 的编辑区自动新建一个标题为"标题x"的文件编辑窗口。

缺省状态下,新建文件的快捷键是Ctrl+N

保存文件

通过"文件"菜单中的"保存",或者直接点击工具栏上的"保存"按钮,就可以保存当前正在被编辑的文件。如果要被保存的文件是新建的, 在保存前会弹出对话框,让用户设置要保存的文件名。

缺省状态下,保存文件的快捷键是Ctrl+S

文件另存为

通过"文件"菜单中的"另存为",或者直接点击工具栏上的"另存为"按钮,就可以使用新的名字保存当前正在被编辑的文件。保存前会弹出对话框,让用户设置要使用的新文件名。

关闭文件

通过"文件"菜单中的"关闭",就可以关闭当前正在被编辑的文件窗口。如果小熊猫C++认为被关闭的文件中存在尚未被保存的改动,则它会弹出对话框询问是否需要保存被关闭的文件。

缺省状态下,关闭文件的快捷键是Ctrl+W

打开文件

通过"文件"菜单中的"打开…",或者点击工具栏上的"打开…“按钮,就会显示"打开"对话框。在打开对话框中,选择一个或多个文件(在按住Shift或者Ctrl不放的同时,点击鼠标,可以选择多个文件)后, 点击"打开"按钮,小熊猫就会逐一打开选中的所有文件。如果某个文件之前已经被小熊猫C++打开了,则它会被忽略。

缺省状态下,打开文件的快捷键是Ctrl+O

基本编辑操作

只读模式

只读模式被用来防止用户不小心修改了重要的文件。下列文件在打开时会自动进入只读模式:

  • 当前编译器的C/C++包含文件夹(include文件夹)中的文件

文件以只读模式打开时,会在在编辑区的文件标题栏增加[只读]标记。只读模式无法取消或者改变。如果您确实需要用小熊猫C++修改某个被只读的文件,可以将它复制到别的位置,修改后再复制回原处。

光标

在处于编辑状态的文件窗口中,可以看到一条闪烁的线或者方块,它就是光标(caret)。光标所在的位置就是内容将会被输入的位置。

Insert状态与覆写状态

文件在编辑时,有两种状态:

  • Insert状态:这是文件新建或打开时缺省的状态,在此状态下,新输入的字符会添加到光标所在位置,光标后原有的内容会自动向后移动。
  • 覆写状态:在此状态下,新输入的字符会覆盖光标所在位置原有的内容。

按下Insert键,会自动从当前状态切换到另一种状态:如果当前是Insert状态,会变为覆写状态;如果当前是覆写状态,则会变为Insert状态。

小熊猫C++在状态栏的右下角用”Insert(中文)“或”覆写“显示编辑器当前的编辑状态。

基本键盘操作

按下Backspace键,删除所在位置的前一个字符并移动到被删除字符所在的位置;按下Delete键,就会删除光标所在位置的字符。

按下←、↑、→、↓键可以向左、上、右、下移动光标。

按住Ctrl键的同时按下←、↑、→、↓键,则窗口中的内容向左、上、右、下滚动,但是光标位置保持不变。

按下Home键,光标会移动到该行的第一个非空白字符处;如果光标已经位于第一个非空白字符处,则它会移动到该行的第一个字符处;

按下End键,光标会移动到该行的最后一个非空白字符处;如果光标已经位于最后一个非空白字符处,则它会移动到该行的最后一个字符处。

按下Ctrl键的同时按下Home键,光标会移动到文件的起始(第一行第一列);按下Ctrl键的同时按下End键,光标会移动到文件的末尾(最后一行最后一列)。

按下Page Up键,向前翻一页,同时光标移动到前一页对应的行和列;按下Page Down键,向后翻一页,同时光标移动到下一页对应的行和列。

按住Ctrl键的同时按下Page Up键,光标会移动到窗口中的第一行;按住Ctrl键的同时按下Page Down键,光标会移动到窗口中的最后一行。

在按住Shift键的同时使用上述键盘操作移动光标,则会自动选中操作前光标所在位置和操作后光标所在位置中间区域的内容。

常用编辑快捷键

快捷键 作用
Ctrl+C 将选中的内容复制到剪贴板
Ctrl+X 将选中的内容剪贴到剪贴板
Ctrl+V 将剪贴板中的内容复制到光标处
Ctrl+A 选中当前文件的全部内容
Ctrl+Z 撤销最近一次编辑操作
Ctrl+Y 恢复上一次撤销的操作
Ctrl+Alt+← 光标移动到前一次编辑开始位置
Ctrl+Alt+→ 光标移动到后一次编辑开始位置

特殊编辑快捷键

快捷键 作用
Ctrl+E 删除(Erase)光标所在的行
Ctrl+D 复制(Duplicate)并Insert光标所在的行
Ctrl+Shift+D 删除光标所在处的单词
Ctrl+Shift+B 从光标所在位置向前删除到单词开头(Begin)
Ctrl+Shift+E 从光标所在位置向后删除到单词结尾(End)
Ctrl+Enter 在光标所在行的下一行Insert新行

基本鼠标操作

双击任意单词可以选中该单词

在任意位置按下鼠标左键,光标会移动到鼠标箭头所在的位置。


滚动鼠标滚轮,窗口内容会跟着上下滚动(光标保持不变)。

按住Alt键的同时,滚动鼠标滚轮,窗口内容会跟着左右滚动(光标保持不变)。

按住Ctrl键的同时,滚动鼠标滚轮,编辑窗口中的字体大小会随之改变。

在按住Shift键的同时使用上述滚轮操作移动光标,则会自动选中操作前光标所在位置和操作后光标所在位置中间区域的内容。


在未选中内容的情况下,按下鼠标左键在编辑器中拖动,可以选中内容。

选中部分内容后按下鼠标左键,可以将选中的内容移动到指定位置;在拖动的同时按下Ctrl键,可以将选中的内容复制到指定位置。

右键菜单

在编辑器标题栏或者编辑区右键单击,会弹出右键菜单。根据用户鼠标右键点击的位置不同,小熊猫C++的编辑窗口会弹出两种不同的右键菜单:

  • 标题区域右键菜单
  • 编辑区域右键菜单

标题区右键菜单

右键单击被编辑文件的标题区域,会弹出标题区右键菜单。各菜单项的作用如下表所示。

菜单项 作用
关闭 关闭当前文件
全部关闭 关闭所有打开的文件
打开所在的文件夹 在Windows文件管理器中打开当前文件所在文件夹
打开命令行窗口 以文件所在的文件夹作为当前工作文件夹,打开Windows控制台
在文件视图中定位 将当前文件所在的文件夹设置为工作文件夹,打开小熊猫C++左侧的文件视图,并在视图的文件列表中选中和突出显示当前文件
移动到其他视图 将当前文件移动到另一个编辑视图中
文件属性… 在文件属性对话框中显示当前文件的属性信息

编辑区右键菜单

右键单击被编辑文件的正文编辑区域,会弹出编辑区右键菜单。部分菜单项的作用如下表所示。

菜单项 作用
编译运行 编译当前程序文件,然后运行编译得到的可执行文件
调试 编译当前程序文件,然后调试编译得到的可执行文件
跳转到声明处 跳转到光标所在处C/C++标识符的声明处。如果其所在的文件尚未打开,会自动打开该文件。
跳转到定义处 跳转到光标所在处C/C++标识符的定义处。如果其所在的文件尚未打开,会自动打开该文件。
查找符号的引用 在当前文件/项目中查找所有对光标所在处C/C++标识符的使用。查找结果会显示在小熊猫C++下方的查找面板中。
打开所在的文件夹 在Windows文件管理器中打开当前文件所在文件夹
打开命令行窗口 以文件所在的文件夹作为当前工作文件夹,打开Windows控制台
在文件视图中定位 将当前文件所在的文件夹设置为工作文件夹,打开小熊猫C++左侧的文件视图,并在视图的文件列表中选中和突出显示当前文件
对代码重新排版 使用自带的asytle程序对当前编辑的文件重新排版。可在"选项"对话框的"代码排版”→“通用"中设置排版使用的格式。
文件属性… 在文件属性对话框中显示当前文件的属性信息

3 - 教程

小熊猫C++的相关教程

3.1 - 小熊猫C++入门教程

由用户anbangli撰写的入门教程

作者:anbangli@foxmail.com

格式调整:Alan-CRL@qq NaN@qq 瞿华(royqh1979@gmail.com)

1、安装与启动

**小熊猫C++**是一个开源、免费的 C/C++ 集成开发环境(Integrated Developing Environment,简称IDE),源于著名的Dev-C++。其前身小熊猫Dev-C++ 5.x和6.x是在Orwell Dev-C++停止更新后自行维护升级的分支版本。后来改用QT(一种适合于跨平台界面开发的C++开发框架)重新开发,曾用名小熊猫Dev-C++ 7,现更名为小熊猫C++。

建议读者从小熊猫C++中文官方主页下载最新版本。

点击主页中的“下载”,其中有几个下载链接(如下图),读者可以自行选择点击其中一个。

例如点击“蓝奏云网盘”并输入分享码之后,出现如下图网页,其中列出了多个操作系统的不同安装包。如果你不懂这些安装包的区别,那么就选择点击其中含有“Win64”和“安装版”字样的那一个(如下图所示)。点击之后就会开始下载。

下载到本机之后请开始安装。安装过程很简单,按照对话框的操作提示执行即可,在此略过不叙。

安装完毕之后,双击Windows桌面上的“小熊猫C++”图标,以启动这个软件。

第一次运行时会进行编译器配置,出现如下对话框:

请点击“Yes”按钮。

稍等片刻之后,自动配置完毕,出现软件主界面(下图),其中包括菜单栏、主工具栏、左侧工具面板、文件编辑区和底部工具面板。

小熊猫C++默认的界面主题是深色的,有些用户喜欢而另一些用户不喜欢。可以点击菜单“工具”下的“选项”,在弹出的对话框中点击“主题”下拉框,选择“default”并点击确定,于是整个界面都变成浅色了。为了方便起见,下文中的图片都是在浅色界面下截屏而得的。

工具栏是平时使用最多的,其中各个按钮会随着当前操作而处于 明亮可用状态 或 变灰不可用状态。几个主要按钮的功能如下图所示(请注意红色粗体标记的按钮):

2、编辑功能

  • 点击工具栏上的“新建源代码”按钮(或者按快捷键 Ctrl+N),就可以新建一个空白的源代码文件,并开始编写程序了。

  • 点击工具栏上的“打开”按钮(或按快捷键 Ctrl+O),就可以打开一个原有的源代码文件或工程文件,进行编辑。

  • 点击工具栏上的“保存”按钮(快捷键 Ctrl+S)或“全部保存”按钮,即可保存当前编辑的文件,默认文件扩展名为“.cpp”。

  • 点击文件选项卡上的“关闭”按钮,即可关闭当前编辑的文件。

在小熊猫C++中编辑文件时,基本操作与其它文本编辑器是完全相同的。值得指出的是,小熊猫C++具有强大的代码提示功能,当用户键入字符时,会自动根据前面已输入的几个字符而提示相似的词条。例如,当用户键入“#in”时,就会自动弹出“#include”、“#ifndef”等标识符(如下图所示)。如果按下回车键,则自动输入当前高亮的词条。

不仅如此,在编辑过程中,小熊猫C++会对已输入的源代码进行自动解析并提示(如下图所示):

(1)编辑区左边的行号区中显示了代码中的块状结构,可供用户看出代码中的复合语句层次(如图中的粉色框标记所示)。

(2)每次当用户按下回车键时,它会自动对当前行进行语法检查。如果有语法错误,就会在行号区标记出来(图中红色框所示,行号区的灰色圆圈表示警告信息),当鼠标悬浮于该行时就会显示语法检查信息(图中编辑区红色框所示)。

(3)当程序中定义了函数或类型时,它们会被自动解析出来,并显示在左侧工具窗口的“结构”页中显示出来(图中显示该程序中有新类型gg、函数“fun(int a)”和函数“main()”)。

还要说到的是,小熊猫C++集成了一个名为“AStyle”的自动格式整理工具,可以帮助用户整理源程序的排版格式。请点击工具栏上的“对代码重新排版”按钮,就会把当前正在编辑的源代码进行格式整理,使它变成规范的排版格式。——请读者记住并熟练使用这一工具。

3、编译与运行

当程序编写完成并已经保存时,就可以进行编译了。

小熊猫C++提供了多种编译配置方案可供用户选用。不过大部分用户直接使用默认的编译配置方案即可,不需额外设置。

程序编写完成之后,点击工具栏上的“编译”按钮,就可以开始编译,稍等片刻就会完成编译。这时底部信息面板会自动向上展开。如果编译出错,则底部信息面板会显示“编译信息”页,其中列出了编译时中的出错信息(如下图所示)。

我们在编写程序时经常会出错(包括语法错误和逻辑错误),程序编译时通常能检测出各种语法错误(上面图片中的示例程序就有语法错误和逻辑错误),这时我们需要根据出错信息,找出我们在编写程序时所犯的错误,并对程序进行修改,以改正这些错误。

根据上图中的编译信息“[错误] ‘k’ was not declared in this scope([错误] ‘k’ 未在此范围内声明)”,我们需要修改程序,在其中定义变量 k。

排除了所有语法错误之后,就可以编译成功。不会弹出编译信息。若有需要,可以点击底部信息面板的“编译日志”,从中看到详细的编译信息。

上图中的编译日志中显示,程序已经编译成功,生成了可执行文件“C:\Tools\test1.exe”。

编译完成之后,点击工具栏上的“运行”按钮,以便运行程序。如果程序未编译,或者编译之后有修改,小熊猫C++会自动重新编译程序。运行时会自动弹出控制台窗口,在其中显示有程序输出结果。

请注意,图中的输出结果是 4950 。根据我们的数学知识可知,从 1 累加到 100的结果应该是5050,所以这个答案是错误的,这说明上面的程序虽然可以运行并输出结果,但是其中存在着逻辑错误,需要进行调试,以排除错误。

在控制台窗口中按回车键,关闭该窗口。

4、小熊猫C++ 中的程序调试方法

编译时可以检查出源代码中的语法错误,但是检查不出源代码中的逻辑错误。有时候程序虽然能够编译并运行,但是运行结果却不是预想的结果,那就是因为源代码中存在有逻辑错误。

要想清除程序中的逻辑错误,就必须学会一些调试方法,通过观察变量的数值变化,加上自己的逻辑思考,从而找出程序中的错误所在并修改清除之。

一种常见的办法是在程序中添加输出语句,输出运行过程中的变量的中间值。例如上面示例程序中,可以在循环中添加语句,输出变量k 和 sum 在循环过程中的值(如下图所示)。

再次编译并运行程序,输出了一系列数据,如下图所示:

仔细查看输出的数据(需要用鼠标拖动窗口右侧的滚动条,以便看到完整的输出结果),可以发现,上面程序只是从1 累加到 99,所以累加结果是4950 。

要解决这个程序中的错误,就需要把 for 循环中的“k < 100”改为 “k <= 100”。重新编译并运行,就会发现,程序最终输出结果是 5050,这是从 1 累加到 100的正确结果。

上面程序通过输出运行过程中的变量的中间值可以找出问题并排除错误,但是有些程序的错误可能比较隐藏比较深,这时就需要更复杂一点的方法,也就是使用集成开发环境所提供的调试工具

小熊猫C++提供了强大的除错和调试工具。工具栏上与调试有关的按钮是“开始调试”、“单步跳过”、“单步进入”、“单步跳出”、“继续执行”、“停止执行”和“添加监视”(下图所示)。在调试过程中需要熟练使用这几个按钮。

1.开始调试(Debug)

我们以如下一个含有错误的程序为示例,讨论如何进行调试。

#include <stdio.h>

double average(int length, int array[]) {
	int k, sum;
	for (k = 0; k <= length + 1; k++)
		sum += array[k];
	return sum / k;
}

int main() {
	int a[] = {87, 74, 68, 86, 78, 82, 90};
	int len = sizeof(a) / sizeof(a[0]);
	printf("Total: %d\\n", 87 + 74 + 68 + 86 + 78 + 82 + 90);
	double avrg = average(len, a);
	printf("Length: %d, Average: %f\\n", len, avrg);
	return 0;
}

该程序中含有一个名为“average”的函数,用于求出长度为 length 的整型数组 array[]的平均值。在主函数中提供了一个示例数组 a ,并调用 average 函数求平均值。

把这个程序保存到本机,编译并运行。手工简单计算可知,数组 a中现有的数据的平均值大约是 80.7,但是程序输出结果不正确,说明程序中存在严重的错误,而且无法直接找出错误所在。

点击工具栏上的“!开始调试”按钮(快捷键F5),或点击菜单“运行”下的“调试 F5”即可开始调试。

2. 调试过程中的操作

如下图所示,启动调试之后,工具栏上的“单步跳过”、“单步进入”、“单步跳出”、“继续执行”和“停止执行”都变亮可用了,左侧管理器面板会自动切换到“监视”窗格。底部信息面板也自动展开并显示到“调试”页。

在上图中我们可以看到,启动调试后,“调试”面板的右边部分显示了“局部变量”标签页,其中显示局部数组变量a 、局部变量 len 和局部变量 avrg的值,而且是一些奇怪的莫名其妙的数字。这是因为刚进入函数时,所有局部变量都只是被分配了存储空间,还没有被赋值。所以查询其值就得到一个毫无意义的数字。需要在程序中赋值之后,它们才具有我们所需的值。读者不要为此感到惊奇。

然后需要熟练使用工具栏上的“单步跳过”按钮(快捷键F7)和“单步进入”按钮(快捷键 F8)。在简单的只含有一个 main函数的程序中,这两个按钮的功能是相同的,没有区别。而在含有多个自定义函数的程序中,这两个功能有较大的区别:“单步跳过”是指把当前语句作为一步执行完毕,而“单步进入”是指如果当前语句中含有函数调用则追踪进入到函数中去执行

如果调用函数是标准函数或你认为无误的函数,就用“单步跳过”执行(以免追踪进入到函数中),对于怀疑有问题的函数才用“单步进入”去追踪。如果一不小心进入了标准函数(例如printf 函数或“cout << endl;”输出),则点击“单步跳出”以返回。

在启动了调试之后,读者可以使用“单步跳过”按钮和“单步进入”按钮,慢慢地在调试状态下执行程序中的语句,并随时观察下方“局部变量”标签页中所显示的值,并且不断地思考程序中的语句是否正确,然后进行相应操作。

对于上面程序,应该在第15句时使用“单步进入”,追踪到 average函数中去。仔细观察可以发现,该函数中的局部变量 sum 没有赋初值!

这时请点击工具栏上的“停止”按钮(快捷键 F6 ),返回到编辑状态,把局部变量 sum赋初值为 0(例如写成“int k, sum = 0;”,然后点击“编译”按钮重新进行编译,再点击“运行”按钮运行程序,或点击“调试”按钮启动调试。(以后在调试过程中可以随时点击“停止”按钮返回编辑状态,对源代码进行修改之后需要重新编译,再运行程序或启动调试)

运行程序会发现结果仍然不正确,所以需要重新启动调试。分析可知,这时需要检查 for循环中的情况。检查时会逐渐注意到,虽然下方“局部变量”标签页中随时会显示 k 和 sum的值,但是重要的是需要观察 array[k]才行!然而底部的“局部变量”标签页中并没有显示这个数组元素的值。

这时需要使用“监视变量”的功能。

在默认情况下,如果用鼠标悬浮在当前运行的代码中的变量上方(例如上面程序中的 length ),则会自动出现一个小悬浮窗口,显示出该变量当前的值。

如果想更快速地看到变量的值,可以在编辑器中选中待查看的变量名(例如,选中“array[k]”),点击工具栏上的“添加监视”按钮并确认,左边的“监视”窗格中就会显示该变量当前的值。

在上面程序中添加了查看变量 array[k]之后,用“单步进入”逐句执行该程序,并随时观察变量 k 和数组元素 array[k]的值,最后会观察到,当 k 的值为 8 和 9时仍然进入了循环!这是一个数组下标越界错误(主函数中的数组 a 只有 8个变量,下标为 0 - 7。数组长度值 len 传递给函数 average 的参数 length,循环变量 k 最大只能取值为 7)。应该把 “k <= length + 1”修改为 “k <length”,这样才能避免下标越界,求得正确的 sum 值。

在上面的调试过程中,每次都使用“单步跳过”按钮(F7)和“单步进入”按钮(F8)进行操作时比较慢。还可以在程序中设置断点,加快调试操作速度。

在事先对程序的运行出错现象进行思考之后,可以推断出程序出错的可能原因在于源代码中的哪些语句。无论是在编辑状态还是在调试过程中,可以用鼠标点击想要暂停执行的那一行左边的装订区位置中的行号(或者把光标移动到想要那一行并按F4键),该行在装订区的行号处就显示有一个带勾的红圈,表示该行已被设置为一个断点。再次操作则取消该行为断点。

可以直接在“sum +=array[k];”那一行设置一个断点,也可以在自己怀疑有问题的程序片段前后设置多个断点,以便进行调试。

在程序中设置了断点之后,启动调试时会直接运行到第一个断点处(而不是第一条可执行语句)暂停。这时仍然可以用“单步跳过”按钮(F7)和“单步进入”按钮(F8)进行操作。如果认为程序中某一部分无误,则点击“继续执行”按钮,就会继续运行到下一个断点处暂停,无断点则运行到程序末尾结束。

对上面的示例程序继续调试,可以发现语句“return sum / k;”含有错误:整数相除得到整数,丢失了小数部分。一种修改办法是改成“return 1.0 *sum / k;”。

这样,通过启动 小熊猫C++中的调试功能,使用“单步跳过”(F7)和“单步进入”(F8)慢慢地执行程序,在此过程中随时查看变量的值,并在头脑中进行分析思考,从而判断程序中是否存在逻辑错误,从而修改程序、排除程序中的错误。

最后,总结一下小熊猫C++ 使用过程中调试过程中经常用到的功能及其快捷键:

  • 切换断点 F4
  • 启动调试 F5
  • 停止执行 F6
  • 单步跳过 F7
  • 单步进入 F8
  • 编译 F9
  • 运行 F10
  • 编译运行 F11

熟记这些快捷键有利于加快操作速度。

当前小熊猫C++中文作者主页:https://royqh1979.gitee.io/redpandacpp/

旧版本(使用Delphi编写,与原版Dev-C++相似):https://royqh.net/devcpp/

软件作者的知乎专栏“小熊猫C++”:https://www.zhihu.com/column/c_1440014168041054208

4 - 起步

如何下载、安装和运行小熊猫C++

系统需求

小熊猫C++基于Qt 5.12开发

  • windows:需要windows 7或以上操作系统,1GHz CPU和4G内存;
  • Linux:要求Debian 10、深度2020.4或者Ubuntu20.04LTS;其他版本的Linux也可能支持,但作者未进行测试。

4.1 - Windows

Windows系统下的下载、编译和安装

下载

小熊猫C++网站的下载页中提供了多个下载站点供用户选择。用户可以根据自己的网络情况,选择合适的站点下载。

不同发行版的区别

为了满足不同用户的需求,小熊猫提供了多个不同的Windows发行版本。

文件名 适用操作系统位数 GCC版本 安装类型
win32 MinGW-w64.i686.GCC 绿色版 32位 32位 GCC 10.3 绿色版
win32 MinGW-w64.i686.GCC Setup 32位 32位 GCC 10.3 安装版
win32 无编译器 绿色版 32位 绿色版
win32 无编译器 Setup 32位 安装版
win64 MinGW-w64.x86_64.GCC 绿色版 64位 32位 GCC 10.3 绿色版
win64 MinGW-w64.x86_64.GCC Setup 64位 32位 GCC 10.3 安装版
win64 无编译器 绿色版 64位 绿色版
win64 无编译器 Setup 64位 安装版

对于大多数普通用户,应该下载和使用64位带gcc 10.3编译器的版本

绿色版与安装版

文件名中含有“绿色版”或者“Portable”,以.7z后缀结尾的版本是绿色版。绿色版的特点是无需安装,使用7-zip或其他支持7z格式的解压软件解压后,直接运行其中的RedPandaIDE.exe即可开始使用小熊猫C++;同时,所有的程序参数设置都保存在RedPandaIDE.exe所在文件夹的config子文件夹中。这个版本适合需要同时在多台电脑上运行小熊猫C++、或者无法在电脑上安装程序的用户使用。

文件名中含有“Setup”,以.exe后缀结尾的版本是安装版。安装版本身是一个安装程序,下载之后会将小熊猫C++程序安装到电脑中。

32位与64位

64位(win64)版本的小熊猫C++只能在64位windows操作系统下运行。如果您的电脑是32位系统,应使用32位(win32)版本的小熊猫C++。

无编译器版本

小熊猫C++需要GCC编译器套件(包括gcc、gdb等程序),来编译和调试程序。 为了方便用户安装和使用,小熊猫C++直接提供了集成GCC的版本,供用户下载和使用。

但也有部分高级用户不需要使用小熊猫C++自带的GCC,因此,小熊猫C++也提供了无编译器的版本,供这些用户使用。

windows xp用户

小熊猫C++不支持windows xp。仍在使用windows xp的用户,可以考虑使用(旧版)小熊猫Dev-C++ 6.7.5。

安装

安装版(以Setup.exe)结尾下载后,运行下载的程序,既可开始安装。如无特殊需求,直接按照安装程序提供的缺省设置进行安装即可。

首次运行时配置

在小熊猫C++第一次运行时,会自动生成缺省的配置文件,并进行下列自动设置:

  1. 在主程序RedPandaIDE.exe所在文件夹的MinGW32/bin和MinGW64/bin中寻找gcc编译器,并建立对应的编译器配置集
  2. 在系统环境变量PATH中所列的文件夹中寻找gcc编译器,并建立对应的编译器配置集
  3. 在系统环境变量PATH中所列的文件夹中寻找git程序

接下来,小熊猫C++会显示下面的界面,提示用户选择将要使用的界面主题:

完成主题选择之后,即进入小熊猫C++的主界面:

编译

作者本人在windows下使用msys2编译小熊猫C++。其主要步骤如下:

  1. 下载安装msys2
  2. 进入msys2 shell后,使用pacman程序安装gcc qt5等程序
pacman -S  mingw-w64-x86_64-gcc  mingw-w64-x86_64-qt5 mingw-w64-x86_64-qt5-tools  mingw-w64-x86_64-make
  1. 将msys2安装文件夹下的mingw64\bin加入系统PATH环境变量
  2. 从gitee或者github下载小熊猫C++源码
  3. 打开windows控制台,进入小熊猫C++源码所在目录,进行源码(假设编译到D:\RedPanda-Cpp下)
qmake PREFIX="D:\RedPanda-Cpp" -o Makefile Red_Panda_Cpp.pro -r -spec win32-g++ 
mingw32-make -j16
mingw32-make install

4.1.1 - 预览版

Windows系统下预览版的下载、安装

作者:Alan-CRL(alan-crl@foxmail.com)

下载

您可以前往Alan-CRL维护的下载站下载小熊猫C++预览版,或加入小熊猫C++用户Q群获取。

注意事项

小熊猫C++预览版仅支持Windows 7及以上系统。

安装

首先必须先安装小熊猫C++正式版。(如果您已经安装,此次操作可以称为升级)

下载完成后,打开小熊猫C++的安装目录(绿色版解压目录),并关闭小熊猫C++。

  • PS:如果您不知道小熊猫C++的安装目录在哪里,请右键小熊猫C++桌面快捷方式,选择 “打开文件所在位置” 。

将下载的文件(RedPandaIDE.exe),复制到小熊猫C++的安装目录。并覆盖同名文件,可能需要管理员权限。

完成

再次打开小熊猫C++即可,此刻已经升级为小熊猫C++预览版本了。

问题解答

问题 回答
如果升级成预览版,原先数据会丢失吗? 不会。
正式版与预览版的区别? 预览版可以有限体验最新功能,但可能会有不足。
我想退回正式版本增么办? 将正式版中的 RedPandaIDE.exe 覆盖当前安装目录的同名文件就行。
我在预览版发现了问题,将如何反馈? 加入小熊猫C++用户Q群与大家交流或@开发者。

4.2 - Linux

Linux系统下的编译和安装

下载

小熊猫C++网站的下载页中直接提供了下列Linux系统的二进制包,下载后直接使用包管理器安装,就可以使用了:

  • debian 11
  • ubuntu 20.04
  • deepin 20.4 (深度操作系统)

编译

以debian为例,编译的主要步骤如下:

  1. 安装g++、make
  2. 安装qt5开发库(包括qt5svg5开发库和qmake工具)
  3. 使用qmake建立make文件
sudo qmake PREFIX="\usr\local" -o Makefile Red_Panda_Cpp.pro -r -spec win32-g++ 
  1. 编译安装
make -j16
make install

5.安装小熊猫C++使用时依赖的其他软件:gdb、gdb-server、qterminal

首次运行时配置

在小熊猫C++第一次运行时,会自动生成缺省的配置文件,并进行下列自动设置:

  1. 在系统环境变量PATH中所列的文件夹中寻找gcc编译器,并建立对应的编译器配置集
  2. 在系统环境变量PATH中所列的文件夹中寻找git程序

接下来,小熊猫C++会显示下面的界面,提示用户选择将要使用的界面主题:

完成主题选择之后,即进入小熊猫C++的主界面:

4.3 - MacOS

MacOS系统下的安装

下载

小熊猫C++网站的下载页中提供了由QQ群友cyano.CN,RigoLigo,Bowen404,Johnny等提供的二进制dmg包。

由于未购买苹果开发账号,dmg包均未进行数字签名,需要在终端里使用下面的命令修改权限后才能安装:

xattr -rc dmg文件的文件路径

相关说明

  • 用户需自行安装clang或者gcc编译器后才能编译程序
  • 用户需自行安装gdb调试器,才能使用小熊猫C++的调试功能调试程序。

首次运行时配置

在小熊猫C++第一次运行时,会自动生成缺省的配置文件,并进行下列自动设置:

  1. 在系统环境变量PATH中所列的文件夹中寻找gcc编译器,并建立对应的编译器配置集
  2. 在系统环境变量PATH中所列的文件夹中寻找git程序

接下来,小熊猫C++会显示下面的界面,提示用户选择将要使用的界面主题:

完成主题选择之后,即进入小熊猫C++的主界面:

5 - 使用方法

小熊猫C++的详细功能和使用介绍

5.1 - 外观

调整小熊猫C++的字体、图标、颜色等外观元素

5.1.1 - 整体外观

调整小熊猫C++主窗口的整体外观

对于每一个人来说,视力都是需要认真去保护的。无论你使用何种工具编程, 在开始敲代码前都首先应该将其外观调整到眼睛看起来最舒服的状态。

通过“工具”→“选项”对话框中的“外观”页,可以调整小熊猫C++的整体外观。

主题

主题决定着小熊猫C++主窗口中除编辑器外其他部分显示时的使用颜色。

小熊猫C++自带三种主题,用户可以根据自己的习惯选择:

  • 深色:深色背景,浅色文字
  • 浅色:浅色背景,深色文字
  • 高对比度:黑色背景,白色文字

字体

“外观”页中的字体和大小选项控制着小熊猫C++主窗口中除编辑器外其他部分显示时所用的字体。

图标

图标集

“图标集”是当前显示时所用的图标集合。深色主题默认使用“高对比度”图标集;浅色主题默认使用“新外观”图标集。

图标缩放

小熊猫C++使用SVG格式的图标,其显示时的大小通过下列公式计算得到:

图标大小=外观字体实际大小*缩放比例

通过“图标缩放”选项,可以改变图标的缩放比例。

5.1.2 - 编辑器外观

调整编辑器的字体、配色和图标等视觉元素

对于每一个人来说,视力都是需要认真去保护的。无论你使用何种工具编程, 在开始敲代码前都首先应该将其外观调整到眼睛看起来最舒服的状态。

配色

通过配色设置,可以调整小熊猫C++的编辑器在显示不同内容时所用的颜色和字体样式。

通过菜单"工具"→“选项”,用户可以打开选项对话框。 在选项对话框左侧选中"编辑器"→“配色”,即可打开相应的设置页。

小熊猫C++预置了多套配色方案。用户可以根据自己的喜好,通过配色设置页顶部的下拉框选择合适的配色方案。

配色方案管理

点击配色方案下拉框旁边的"…“按钮,即可弹出配色方案管理菜单。通过其中的菜单项可以对配色方案进行管理。

菜单项 作用
复制 生成一个当前配色方案的副本
导出 将当前配置方案导出保存到指定的文件
导入 从指定的文件导入配色方案
删除自定义修改 丢弃对当前预置配色方案的修改
重命名 修改当前配色方案的名称(预置方案无此选项)
删除 删除当前配色方案(预置方案无此选项)

修改配色方案

如果对预置的配色方案不是完全满意,可以对其进行修改。

类别 项目 说明
编辑器 活动断点 在调试时,程序暂停所在的行
当前行 光标所在的行
断点 被设置了断点的行
当前高亮单词 启用"高亮光标所在的单词"时,光标所在的单词
编辑器缺省 编辑器的缺省前景和背景色
代码折叠线 代码折叠线的颜色
侧边栏 编辑器左侧边栏(行号和断点标记所在的栏)
当前行侧边栏 光标所在行的侧边栏
选中文字 被用户选中的文字内容

字体

通过菜单"工具”→“选项”,用户可以打开选项对话框。 在选项对话框左侧选中"编辑器"→“字体”,即可打开相应的设置页。

用户可以对小熊猫C++的编辑器的下列字体设置进行修改:

  • 英文字体
  • 非英文字体
  • 字体大小
  • 启用合字显示支持

英文字体

小熊猫C++使用该字体来显示编码介于0x00-0xFF之间的Unicode字符。

非英文字体

小熊猫C++使用该字体来显示所有编码大于0xFF的Unicode字符。

快速调整字体大小

在编辑器打开的状态下,按住Ctrl键的同时转动鼠标的滚轮按钮,就可以调整编辑器的字体大小。

显示合字

部分字体,如Fira Code,可以将多个字符 作为一个整体来显示,如->显示成→,<=显示成≤,等等。这种特性被称为合字(ligatures)。

在启用该选项后,就可以启用字体的合字显示特性。该选项仅对英文字体生效

下面的两张图展示了同一段代码使用Fira Code字体,不启用合字和启用合字后的显示效果。

不启用合字:

启用合字:

高亮显示

小熊猫C++提供了一系列高亮(突出)显示功能,来帮助用户在编辑时聚焦到重要的内容上。

语法高亮

小熊猫C++在显示C/C++等支持类型的文件内容时,会用不同的颜色区分显示文件中的关键字、标识符、运算符、字符串和注释等不同语法元素。

用户可以在"选项"对话框的"编辑器"→“配色"页中设置每一种语法元素显示所用的颜色。

语法高亮增强

在"代码补全"功能被启用的情况下,小熊猫C++会进一步用不同的颜色区分显示变量、函数和类等不同的标识符。

符号匹配高亮

当光标移动到括号或引号等符号上时,小熊猫C++会高亮显示和它配对的另一个括号或者引用。

选中词高亮

当光标移动到单词(标识符)上时,小熊猫C++会高亮显示文件中所有该单词出现的位置。

彩虹括号

小熊猫C++会用不同的颜色区分显示嵌套的括号。

用户可以在"选项"对话框的"编辑器”→“配色"页中设置不同嵌套层次括号所用的颜色;也可以通过勾选"彩虹括号"选项来启用/禁用彩虹括号显示功能。

5.2 - 代码编辑

小熊猫C++的各项编辑功能

5.2.1 - 基本功能与快捷键

基本编辑功能和快捷键的使用介绍

基本文件操作

新建文件

通过"文件"菜单中的"新建"→“新建源代码文件”,或者直接点击工具栏上的"新建源代码文件"按钮,就可以在小熊猫C++ 的编辑区自动新建一个标题为"无标题+数字"的文件编辑窗口。

缺省状态下,新建文件的快捷键是Ctrl+N

保存文件

通过"文件"菜单中的"保存",或者直接点击工具栏上的"保存"按钮,就可以保存当前正在被编辑的文件。如果要被保存的文件是新建的, 在保存前会弹出对话框,让用户设置要保存的文件名。

缺省状态下,保存文件的快捷键是Ctrl+S

文件另存为

通过"文件"菜单中的"另存为",或者直接点击工具栏上的"另存为"按钮,就可以使用新的名字保存当前正在被编辑的文件。保存前会弹出对话框,让用户设置要使用的新文件名。

关闭文件

通过"文件"菜单中的"关闭",就可以关闭当前正在被编辑的文件窗口。如果小熊猫C++认为被关闭的文件中存在尚未被保存的改动,则它会弹出对话框询问是否需要保存被关闭的文件。

缺省状态下,关闭文件的快捷键是Ctrl+W

打开文件

通过"文件"菜单中的"打开…",或者点击工具栏上的"打开…“按钮,就会显示"打开"对话框。在打开对话框中,选择一个或多个文件(在按住Shift或者Ctrl不放的同时,点击鼠标,可以选择多个文件)后, 点击"打开"按钮,小熊猫就会逐一打开选中的所有文件。如果某个文件之前已经被小熊猫C++打开了,则它会被忽略。

缺省状态下,打开文件的快捷键是Ctrl+O

基本编辑操作

只读模式

只读模式被用来避免用户不小心修改重要的文件。下列文件在打开时会自动进入只读模式:

  • 当前编译器的C/C++包含文件夹(include文件夹)中的文件

文件以只读模式打开时,会在在编辑区的文件标题栏增加[只读]标记。只读模式无法取消或者改变。如果您确实需要用小熊猫C++修改某个被只读的文件,可以将它复制到别的位置,修改后再复制回原处。

光标

在处于编辑状态的文件窗口中,可以看到一条闪烁的线或者方块,它就是光标(caret)。光标所在的位置就是内容将会被输入的位置。

Insert状态与覆写状态

文件在编辑时,有两种状态:

  • Insert状态:这是文件新建或打开时缺省的状态,在此状态下,新输入的字符会添加到光标所在位置,光标后原有的内容会自动向后移动。
  • 覆写状态:在此状态下,新输入的字符会复写光标所在位置原有的内容。

按下Insert键,会自动从当前状态切换到另一种状态:如果当前是Insert状态,会变为覆写状态;如果当前是覆写状态,则会变为Insert状态。

小熊猫C++在状态栏的右下角用”Insert(中文)“或”覆写“显示编辑器当前的编辑状态。

基本键盘操作

按下Backspace键,删除所在位置的前一个字符并移动到被删除字符所在的位置;按下Delete键,就会删除光标所在位置的字符。

按下←、↑、→、↓键可以向左、上、右、下移动光标。

按住Ctrl键的同时按下←、↑、→、↓键,则窗口中的内容向左、上、右、下滚动,但是光标位置保持不变。

按下Home键,光标会移动到该行的第一个非空白字符处;如果光标已经位于第一个非空白字符处,则它会移动到该行的第一个字符处;

按下End键,光标会移动到该行的最后一个非空白字符处;如果光标已经位于最后一个非空白字符处,则它会移动到该行的最后一个字符处。

按下Ctrl键的同时按下Home键,光标会移动到文件的起始(第一行第一列);按下Ctrl键的同时按下End键,光标会移动到文件的末尾(最后一行最后一列)。

按下Page Up键,向前翻一页,同时光标移动到前一页对应的行和列;按下Page Down键,向后翻一页,同时光标移动到下一页对应的行和列。

按住Ctrl键的同时按下Page Up键,光标会移动到窗口中的第一行;按住Ctrl键的同时按下Page Down键,光标会移动到窗口中的最后一行。

在按住Shift键的同时使用上述键盘操作移动光标,则会自动选中操作前光标所在位置和操作后光标所在位置中间区域的内容。

常用编辑快捷键

快捷键 作用
Ctrl+C 将选中的内容复制到剪贴板
Ctrl+X 将选中的内容剪贴到剪贴板
Ctrl+V 将剪贴板中的内容复制到光标处
Ctrl+A 选中当前文件的全部内容
Ctrl+Z 撤销最近一次编辑操作
Ctrl+Y 恢复上一次撤销的操作
Ctrl+Alt+← 光标移动到前一次编辑开始位置
Ctrl+Alt+→ 光标移动到后一次编辑开始位置

特殊编辑快捷键

快捷键 作用
Ctrl+E 删除(Erase)光标所在的行
Ctrl+D 复制(Duplicate)并Insert光标所在的行
Ctrl+Shift+D 删除光标所在处的单词
Ctrl+Shift+B 从光标所在位置向前删除到单词开头(Begin)
Ctrl+Shift+E 从光标所在位置向后删除到单词结尾(End)
Ctrl+Enter 在光标所在行的下一行Insert新行

基本鼠标操作

双击任意单词可以选中该单词

在任意位置按下鼠标左键,光标会移动到鼠标箭头所在的位置。


滚动鼠标滚轮,窗口内容会跟着上下滚动(光标保持不变)。

按住Alt键的同时,滚动鼠标滚轮,窗口内容会跟着左右滚动(光标保持不变)。

按住Ctrl键的同时,滚动鼠标滚轮,编辑窗口中的字体大小会随之改变。

在按住Shift键的同时使用上述滚轮操作移动光标,则会自动选中操作前光标所在位置和操作后光标所在位置中间区域的内容。


在未选中内容的情况下,按下鼠标左键在编辑器中拖动,可以选中内容。

选中部分内容后按下鼠标左键,可以将选中的内容拖动到指定位置;在拖动的同时按下Ctrl键,可以将选中的内容复制到指定位置。

右键菜单

在编辑器标题栏或者编辑区右键单击,会弹出右键菜单。根据用户鼠标右键点击的位置不同,小熊猫C++的编辑窗口会弹出两种不同的右键菜单:

  • 标题区域右键菜单
  • 编辑区域右键菜单

标题区右键菜单

右键单击被编辑文件的标题区域,会弹出标题区右键菜单。各菜单项的作用如下表所示。

菜单项 作用
关闭 关闭当前文件
全部关闭 关闭所有打开的文件
打开所在的文件夹 在Windows文件管理器中打开当前文件所在文件夹
打开命令行窗口 以文件所在的文件夹作为当前工作文件夹,打开Windows控制台
在文件视图中定位 将当前文件所在的文件夹设置为工作文件夹,打开小熊猫C++左侧的文件视图,并在视图的文件列表中选中和突出显示当前文件
移动到其他视图 将当前文件移动到另一个编辑视图中
文件属性… 在文件属性对话框中显示当前文件的属性信息

编辑区右键菜单

右键单击被编辑文件的正文编辑区域,会弹出编辑区右键菜单。部分菜单项的作用如下表所示。

菜单项 作用
编译运行 编译当前程序文件,然后运行编译得到的可执行文件
调试 编译当前程序文件,然后调试编译得到的可执行文件
跳转到声明处 跳转到光标所在处C/C++标识符的声明处。如果其所在的文件尚未打开,会自动打开该文件。
跳转到定义处 跳转到光标所在处C/C++标识符的定义处。如果其所在的文件尚未打开,会自动打开该文件。
查找符号的引用 在当前文件/项目中查找所有对光标所在处C/C++标识符的使用。查找结果会显示在小熊猫C++下方的查找面板中。
打开所在的文件夹 在Windows文件管理器中打开当前文件所在文件夹
打开命令行窗口 以文件所在的文件夹作为当前工作文件夹,打开Windows控制台
在文件视图中定位 将当前文件所在的文件夹设置为工作文件夹,打开小熊猫C++左侧的文件视图,并在视图的文件列表中选中和突出显示当前文件
对代码重新排版 使用自带的asytle程序对当前编辑的文件重新排版。可在"选项"对话框的"代码排版”→“通用"中设置排版使用的格式。
文件属性… 在文件属性对话框中显示当前文件的属性信息

5.2.2 - 高级编辑功能

介绍自动缩进、注释切换、代码折叠和重新排版等高级编辑功能

自动缩进

保持良好和统计的缩进,是提升代码代码可读性的重要手段之一。为了帮助用户编写缩进良好的代码,小熊猫C++提供并缺省启用了编辑器的自动缩进功能。

在开启该功能的情况下,用户在输入C/C++代码时,每次换行时,小熊猫C++会自动计算并在新一行的行首Insert合适数量的空格或者制表符,以形成合适的缩进。

如果希望自己输入缩进,可以通过"工具"菜单→“选项"打开选项对话框,在"编辑器”→“通用"页中找到并取消勾选"自动计算缩进"选项。

注释切换

在编程和调试时,经常需要暂时禁用程序中的一段代码。要实现这一点,最简单的方法就是使用小熊猫C++的注释切换功能。

选中你希望暂时禁用的代码,然后通过菜单"编辑”→“切换注释”(或者直接通过快捷键ctrl+/),即可将这段代码变为注释;当需要启用这段代码时,再次选中它然后"切换注释",就可以将其重新变为普通代码。

代码折叠

在调试和维护逻辑较为复杂的代码时,可以通过代码折叠功能来把整段复合语句显示成一行。

直接点击编辑器左侧边栏的代码折叠按钮即可:

匹配当前括号

当光标位于括号前时,匹配当前括号功能可以让光标直接移动到此左(右)括号对应的右(左)括号处。

通过菜单"代码"→“匹配当前括号"或者快捷键Ctrl+[即可使用这一功能。

重新排版

如果代码本身的缩进格式较为散乱,可以通过"代码"菜单→“对代码重新排版”,或者点击工具栏上的"对代码重新排版"按钮来对代码文件重新进行排版。

5.2.3 - 代码补全与符号补全

使用代码补全和符号补全功能,提升开发效率

代码补全

如下面的动画所示,小熊猫C++可以根据用户当前已经输入的内容,推测用户可能要输入的标识符,并以弹出下拉列表(以下称为代码补全列表)的形式展现给用户。

当代码补全列表弹出时,用户可以继续输入,也可以通过键盘上的下列按键进行操作:

按键 作用
选中列表中的上一个标识符
选中列表中的上一个标识符
Page Up 列表翻到上一页
Page Down 列表翻到下一页
Esc 关闭列表
Tab 使用列表中当前选中的标识符替换用户当前的输入,并关闭列表
Enter 和Tab键作用相同

代码补全可以显著的减少用户输入时的拼写错误,也可以帮助用户在使用不熟悉的库时,快速找到自己想要的API函数或者其他符号,因此可以显著的提升代码输入的效率。

有部分教师认为代码补全会影响学生对重要函数和关键字的记忆,对此我个人的看法是:

  1. 编程教育的核心应该是让学生掌握编程的基本思维范式和问题解决模式,语法并不是最核心的内容。(因为大部分学生将来不一定会使用课程上教授的语言来进行实际的编程工作)

  2. 以笔者个人这些年最终结课考试的实际结果来看,让学生使用带代码补全功能的IDE,并不会影响学生最终书面考试编程的分数;笔者未发现有学生在考试中程序整体思路和步骤正确,但是关键字写错的情况。

因此,笔者认为,并不应该以锻炼学生的基本功为理由,而不让学生使用代码补全功能。

如果需要关闭代码补全功能,可以通过"工具"菜单→“选项"打开"选项"对话框,在"编辑器”→“代码补全"页中取消勾选"启用代码补全”:

符号补全

符号补全是指用户在输入括号、引号等成对出现的符号时,小熊猫C++自动进行的编辑处理。小熊猫C++提供的符号补全功能可以分为三类:

  • 成对符号补全
  • 已成对符号跳过
  • 符号成对删除

成对符号补全

用户在输入左括号(包括圆括号、方括号、花括号)和单双引号时,小熊猫C++会自动Insert和其匹配的右括号或者引号;

此功能可以显著的减少在输入复杂公式时由于忘记输入括号而产生的括号不匹配错误。

符号成对删除

用户在删除左括号(包括圆括号、方括号、花括号)和单双引号时,如果和它匹配的右括号或者引号与它之间没有内容,则小熊猫C++会自动将两个符号一起删除:

已成对符号跳过

用户在输入右括号(包括圆括号、方括号、花括号)和单双引号时,如果当前光标位置上存在要输入的符号,且该符号之前存在和其匹配的左括号或者单双引号,那么此次输入会自动以覆写模式进行。

此功能的主要作用是减少成对符号补全自动引入的符号对于输入流畅性的干扰。

如果需要关闭符号补全功能,可以通过"工具"菜单→“选项"打开"选项"对话框,在"编辑器”→“代码补全"页中取消勾选"启用代码补全”:

5.2.4 - 代码导航

介绍结构浏览器和书签等代码导航功能

结构浏览器

点击小熊猫C++左侧面板的"结构"页,即可打开结构浏览器。该浏览器以树形列表的形式显示了当前文件中的全局变量、函数、宏和类定义等全局定义的标识符。

在结构浏览器中双击某个标识符,可以将光标跳转到该标识符声明所在的行。

右键单击某个标识符,然后在右键菜单中选择"跳转到定义处",就可以将光标跳转到该标识符定义所在的行。

代码跳转

在编辑器中,按住Ctrl键的同时用鼠标点击某个标识符,就会将光标跳转到该标识符声明所在的行。如果当前行就是该标识符的声明,则光标会跳转到该标识符定义所在的行(如果定义和声明不在一行的话)。

也可以通过在编辑器中右键点击某个标识符,然后在右键菜单中选择"跳转到定义处"/“跳转到声明处"进行跳转。

查找符号引用

在在编辑器中右键点击某个标识符,然后在右键菜单中选择"查找对符号的引用”,小熊猫C++就会在当前文件/项目中查找所用使用了该标识符的地方,并在"查找"面板中显示查找结果。

该功能和"在文件中查找"的区别在于,“在文件中查找"在查找时只比较两个单词是否相同;而"查找对符号的引用"会考虑作用域。在不同作用域里定义的重名标识符,会被"查找对符号的应用"当作不同标识符进行处理。

书签

小熊猫C++中的"书签"就是指定文件的某一行。在书签面板中可以浏览和管理小熊猫C++当前的所有书签。

通过"代码"菜单或编辑器右键菜单,可以设置和管理文件中的书签。

5.2.5 - 编码

使用不同的编码打开和编辑文件

不同的用户可能需要用不同的文件编码编写程序。虽然未来编程的大趋势是统一使用UTF-8编码编写程序,但由于windows下gcc对UTF-8编码支持还不够完善,会导致诸如中文文件夹中的C/C++程序里面的__FILE__宏出错等奇怪的bug,所以目前还是建议普通用户使用操作系统的缺省编码来编写程序。

默认文件编码

通过"工具"菜单→“选项"打开"选项对话框”,在"编辑器"→“杂项"页中可以选择小熊猫C++在新建和保存文件时使用的默认文件编码。当"自动识别文件编码"未启用时,该编码也被用作打开文件时的默认编码。

自动识别编码

当该选项被启用时,小熊猫C++会自动判断被打开的文件内容是以UTF-8还是系统默认字符集编码。在简体中文环境下,如果用UTF-8或者系统默认字符集打开失败,还会尝试以gbk和gb18030打开文件。

由于作者本人对于其他语言所使用的字符集了解有限,所以暂时未实现其他语言环境下的非UTF-8及系统默认字符集自动识别支持。欢迎有兴趣的用户提供相关的信息或者实现。

强制使用指定的编码打开文件

如果小熊猫C++打开文件时所使用的编码不正确,用户可以在"编辑"菜单→“文件编码"子菜单中强制指定使用特定的编码来重新打开文件。该操作不会改变磁盘上的文件内容。

转换文件编码

用户可以在"编辑"菜单→“文件编码"子菜单中将文件转换为指定的编码。

注意:该操作会改写磁盘上的文件的内容,所以用户在操作前最好先做好文件的备份。

建议文件编码和实际文件编码

小熊猫C++打开的每个文件编辑器都有两个参数,(建议)编码和实际编码。文件打开保存时会根据文件内容和(建议)编码来计算实际编码:

  • 当文件中不包含非ascii字符时,文件的实际编码是ASCII;
  • 否则,文件的实际编码与编码一致。

小熊猫C++在编译程序时,会根据文件的实际编码来生成相应的gcc编译参数。

5.2.6 - 代码模板

快速生成文件内容

小熊猫C++提供了两种不同的代码模板来帮助用户快速生成代码:

  • 新文件模板 在新建文件时,小熊猫C++会用模板中的内容创建新文件。
  • 代码段模板 在输入内容时,可以快速插入指定代码模板的内容。也可通过“代码”→“插入代码段”插入指定的代码段。

使用代码段模板输入

编辑插入的代码

使用代码模板插入代码段后,即进入代码段编辑模式,光标会停在第一个可编辑区域中。

在代码段编辑模式下:

  • 按TAB键跳转到下一个可编辑区域。
  • 按ENTER键退出代码段编辑模式。

编辑模板

在“选项”对话框→编辑器→代码模板 可以编辑代码模板。

代码段模板属性说明:

  • 代码补全前缀 代码模板在代码补全提示中显示的名称。为空的代码模板则不会显示在补全提示中。
  • 菜单节 代码模板在“代码”→“插入代码段”子菜单中的位置。为-1的代码模板不会出现菜单中。

特殊代码

在代码模板中,可以使用下列特殊代码:

代码 作用
%REPL_BEGIN% 可编辑区域开始
%REPL_END% 可编辑区域结束
%INSERT% 空可编辑区域
<SOURCENAME> 源文件名
<DATE> 当前日期
<DATETIME> 当前时间日期

5.2.7 - 自动保存

使用自动保存功能备份代码

通过"工具"菜单→“选项"打开"选项对话框”,在"编辑器"→“自动保存"页中勾选“启动自动保存"项,即可启用自动保存功能。

该功能会在指定的时间间隔经过后,自动保存指定的文件内容。

用户不管用什么IDE或者编辑软件来编写程序或书写文档,都应该养成编辑后及时存盘(保存)的习惯。因此,作者本人不建议一般用户依赖该功能来保存自己的工作。

5.3 - 查找与替换

使用查找与替换功能提升代码编辑和开发效率

小熊猫C++提供了两种查找和替换功能:

  • 查找/替换 在当前文件的指定区域中查找/替换指定的内容。查找结果直接以选中的形式显示在编辑窗口中。
  • 在文件中查找/替换 在当前文件/项目中查找/替换指定的内容。查找结果以树形列表形式显示在查找面板中。

在大多数情况下,被查找/替换的内容会在文件中多处出现,使用"在文件中查找/替换"要比"查找/替换"更加方便。下图展示了"在文件中查找"的结果:

在文件中查找

通过"查找"菜单→“在文件中查找…",即可直接打开"查找"对话框的"在文件中查找"页。

查找面板

在查找面板中,可以看到"在文件中查找"的结果。如果进行了多次查找,可以在查找面板左上方"历史:“下拉框选择查看每一次查找的结果:

查找的结果在面板中以树形列表显示,包括存在被查找关键字的文件路径,关键字在其中出现的次数,以及文件中每一个关键字出现的位置。当被查找的关键字在不止一个文件中出现时,用户可以很方便的查看查找结果。

双击树形列表中的某一行,就可以在编辑器中跳转到该行对应的位置。

在文件中替换

再"在文件中查找"对话框中,点击到"替换"按钮,即可使用批量"在文件中替换"功能。

注意:此操作无法撤销,在替换前请做好文件的备份!

在文件中替换操作由三个步骤组成:

  1. 在文件中查找
  2. 在查找面板中勾选要替换的行
  3. 完成替换

查找与替换

最后简单说一下查找与替换。在完成了一次查找之后,通过快捷键F3,或者"查找"菜单→“查找下一个”,可以查找关键词在文件中的下一个出现的位置;通过快捷键Shift+F3,或者"查找"菜单→“查找前一个”,可以查找关键词在文件中的前一次出现的位置。

5.4 - 编译与执行

(以单文件方式)编译和执行程序代码

在小熊猫C++中,可以直接将一个包含main函数的程序文件编译链接成可执行文件,然后执行或者调试。

5.4.1 - 编译器配置

通过使用合适的"编译器配置",来编译符合需要的可执行文件

小熊猫C++通过调用外部的gcc编译器来编译和链接程序。通过不同的参数设置,gcc可以将同样的源程序编译成不同的可执行文件。因此,为了方便用户的使用,小熊猫C++与其他大多数的IDE一样,以"编译器配置"的形式来管理编译器的设置。

每个"编译器配置"都是一套gcc相关的编译参数设置,包括:

  • gcc和其他相关程序的路径
  • gcc在编译时用的相关文件夹位置
  • gcc编译参数
  • gcc链接参数等等

通过工具栏上的编译器设置下拉框,用户可以切换当前使用的编译器配置(见下图)。

小熊猫C++在第一次运行时,会自动寻找自带的和系统PATH中的gcc程序,并生成相应的编译器配置。

在之后每次运行时,会自动检查当前编译器配置中的gcc程序是否存在;如果不存在,会自动提示用户重新寻找gcc编译器。

Release和Debug

小熊猫C++为每个自动找到的gcc创建两个编译器配置:Release配置和Debug配置。

在缺省情况下,小熊猫C++会将Debug配置设置为当前编译器配置。

配置类型 作用
Release 生成优化、静态链接的可执行文件。其执行速度最快(-O2优化),可以脱离gcc环境独立运行
Debug 生成调试用的可执行文件;其中包含了调试信息和符号,运行速度相对较慢(-Og优化);脱离gcc环境运行时会提示缺少dll文件

管理编译器配置

用户可以通过"选项"对话框中的"编译器"→“编译器配置集"来创建、编辑和管理编译器配置。

自动搜索编译器

当用户需要恢复缺省的编译器设置,或者在系统PATH中加入了新的gcc兼容编译器时,可以通过"编译器配置集"页上部工具栏的"自动搜索编译器"按钮(见下图)来重新搜索和生成编译器配置。

注意:自动搜索编译器会自动删除原有的全部编译器配置!

在指定文件夹中搜索编译器

通过"编译器配置集"页上部工具栏的"在指定文件夹中搜索编译器"按钮(见下图),可以为指定的文件夹中的gcc兼容编译器建立相应的编译器配置。

添加空白编译器设置

通过"编译器配置集"页上部工具栏的"添加空白编译器设置"按钮,可以创建空白的编译器设置。用户需要自行填写设置中的相关参数。

编译器配置参数

编码转换

对于使用printf或者std::cout输出的程序,如果要输出的字符串常量(字面量)中包含非ascii字符,且程序文件本身的编码和操作系统控制台的编码(中文windows缺省为gbk)不一致,就会导致程序运行时输出的内容显示为乱码。

另外,gcc内部使用UTF-8来分析和处理程序。如果程序文件编码不是UTF-8,并且在标识符里使用了非ascii字符,那么编译就会失败。

因此,当程序中包含非ascii字符时,就需要在gcc编译程序时,对字符串进行转码,包括两个转码操作:

  1. 编译前,将程序文件内容转换为gcc内部处理使用的UTF-8编码;
  2. 链接时,将gcc生成的机器代码中的字符串内容转换为主控台所用的编码,最终得到可执行文件。

在缺省情况下,小熊猫C++生成的编译器配置中会自动勾选”将可执行文件中的字符串转码为"选项,在编译时自动添加相关的转码参数。

静态链接

C/C++的库文件(实现的机器代码)通常有两种提供方式:

  • 静态库。程序直接将库里面的机器代码整合到可执行文件中。
  • 动态库。机器代码位于.dll(或者.so)文件中,库里面只包含调用.dll的相关信息。可执行文件在执行时需要载入.dll文件调用相应的代码。

链接时使用动态库的好处在于,多个程序可以共用同一个动态库.dll文件,减少程序本身可执行文件的大小、启动速度和内存占用。但这也要求程序在启动时能够找到相应的.dll文件。

windows系统在安装时自带了众多的.dll文件,使用这些.dll开发的程序不需要特殊的配置就可以直接在windows下正常运行。而使用gcc开发环境(mingw-w64)编译和动态链接的程序,就必须要进行相关的设置,否则在运行时就会因为找不到.dll文件而出错。

如果在编译器配置中勾选了"静态链接所有库”,小熊猫C++就会在编译时尝试使用静态链接的方式链接所有用到的库。这样得到的程序可以脱离小熊猫C++环境直接运行。

缺省情况下,小熊猫C++生成的Release配置中自动勾选了"静态链接所有库";其他配置都没有勾选该选项。

5.4.2 - 编译和运行

使用编译和运行的相关功能

通过"运行"菜单,或者工具栏上的相关按钮,即可编译和运行当前打开的程序文件。

5.4.3 - 自动链接

根据程序中包含的头文件,自动生成对应的库文件链接参数

大多数C/C++库使用声明和实现分离的形式发行,把相关函数等的声明放在.h头文件中,而把实现编译成.a或者.lib库文件。我们的程序在使用这些库时,除了需要使用#include语句包含相关的头文件外,还需要通过编译参数告诉gcc需要链接的库文件。

Visual C++通过引入#pragma语法,可以在头文件中直接指明对应的库文件;而gcc编译器尚不支持该语法,这就导致用户在使用gcc编译程序时,必须通过自定义链接参数来指定要链接的库,否则就会编译链接失败。如果用户需要在不同的程序中链接不同的库,反复修改自定义链接参数就成了一件很繁琐的事情。

针对这个问题,小熊猫C++提供了一个解决方法:自动链接。在编译单文件程序时,小熊猫C++会根据程序中直接或者间接包含的头文件信息,在自动链接表中查找对应的链接参数。其在"选项"对话框中的配置页如下图所示:

注意:自动链接仅对单文件程序编译生效

小熊猫C++缺省提供了ege、海龟作图、raylib、freeglut等的自动连接配置。因此,用户在小熊猫C++中使用这些库时,不需要手工设置自定义链接参数,非常方便。

5.4.4 - 输入重定向

利用输入重定向功能在运行时自动输入数据,减少测试运行时的工作量

我们为学习C/C++语言和算法编写的练习程序,经常需要在运行时输入一些数据。例如下题(来自洛谷):

在运行时需要输入:

4 3
3 7 12 19

在解决这个题目的过程中,必然需要反复输入这些数据。即使是通过复制粘贴来输入,这也是一件繁琐的事情。小熊猫的输入重定向功能可以帮助我们自动在运行程序时输入数据。

首先,我们用记事本软件,把要输入的数据保存在一个文本文件中(这里假设它的路径是f:/data.txt)。接下来我们会让程序在运行时自动从这个文件中读入内容。

启用输入重定向

通过"运行"菜单→“运行参数…",或者工具栏上的对应按钮,可以直接打开"选项"对话框的"程序运行”→“通用"选项页(以下简称"程序运行选项"页)。

在"程序运行选项"页中勾选"将程序的标准输入重定向到下面的文件”,并填写文件所在的路径,即可启用输入重定向功能。

启用后,程序中的scanf或者cin语句就会从f:/data.txt中读入数据。

5.5 - 调试

使用调试功能定位和解决程序中的缺陷

5.5.1 - 基础知识和准备

介绍调试的基础知识和使用调试功能前需要的准备工作

在为刚开始学习编程的同学们具体介绍小熊猫C++的调试功能之前,让我们先来看一下调试的基本方法(了解调试的同学可以直接转下一节):

1 调试的基本方法

调试就是找出并修正程序中的缺陷(bug)的过程。其实,即使没有学习过编程,我们也早就做过很多次的“调试”了,只不过调试的对象不是程序,而是数学、物理试题的解题步骤罢了。是的,我们调试程序的过程,和我们检查一道数学或者物理题的解题过程是否正确其实是类似的。

我们在解数学或者物理计算题时,从已知条件出发,每一步会进行一项处理或者计算从而得到一个(中间)结果,后面的步骤在前面的步骤的计算结果上继续进行计算,最后得到结果。所以,检查的过程主要就是看:

每一步计算的逻辑是否正确(根据已经计算出来的结果,是不是该用这个定理来进行下一步计算)? 计算的结果有没有错? 想一想你就会发现,我们在用C或者C++这类命令式编程语言编写的程序其实也是如此。除了输入(cin或者scanf)和输出(printf或者cout)外,程序中的每一条语句要么就是在做计算并保存计算结果(赋值),要么就是在根据某个变量的值来决定下一步该干啥(if、while、for等)。所以,我们在调试程序时主要关注的就是:

计算的逻辑是否正确(if、while、for等语句的条件表达式写的对吗)? 计算的对吗,是否使用了正确中间结果(计算的表达式写错了没有,变量名是否写错了)? 所以,我们调试时最基本的操作就是:

对于if/while/for语句:检查程序在执行这条语句之前,条件表达式的计算结果 对于其他语句:检查程序在执行这条语句前后,相关变量或者内存中的值(或者值的变化) 显然,我们可以直接在相关的语句前后使用printf或者cout等语句输出想要检查的内容,从而进行调试。

但调试工具给了我们更多(很多时候也更加方便)的选择。

2 小熊猫的调试功能

小熊猫C++的调试功能主要可以分为两类:

  • 控制程序的执行:包括断点、单步执行系列工具等,通过“运行”菜单或者调试工具栏来访问
  • 查看程序和内存的状态:包括局部变量面板、内存面板、监视面板、调用栈面板、CPU信息窗口(对话框)等
运行菜单中的调试命令

运行菜单中的调试命令

调试工具栏

调试工具栏

监视面板

监视面板

调试面板

调试面板

3 调试前的准备

在后面的系列文章中,我们将以下面这个程序为例,介绍小熊猫的调试功能。(此程序是正确的,我们只是用它来演示调试功能的使用)

/**
 * 找出整数n的所有质因数
 */
#include <stdio.h>
#include <stdbool.h>

//判断n是否为质数
bool isPrime(int n) {
	if (n<2)
		return false;
	for (int i=2;i<n;i++) {
		if (n%i==0)
			return false;
	}
	return true;
}

int main() {
	int n;
	scanf("%d",&n);
	for (int i=2;i<n;i++) {
		if (n%i==0) { //如果i能整除n
			if (isPrime(i)) { //并且i是质数
				printf("%d\n",i);
			}
		}
	}
	return 0;
} 

绝大多数的调试工具都需要程序在编译时嵌入必要的调试信息,才能够正常工作。小熊猫C++内部所使用的gdb工具也是如此。因此,如果想让程序能被正常调试,必须要使用Debug类型的编译器配置集来编译程序,如下图所示:

选择Debug编译

选择Debug编译

注意:改变编译器配置集后,必须使用“运行”菜单中的“全部重编译”功能强制使用新编译器配置重新编译一遍程序,小熊猫C++目前不会在程序内容本身没有改动过的情况下自动重新编译程序。

5.5.2 - 控制程序执行

在调试时控制程序的执行

要查看程序执行到特定位置时的状态,最好当然是能够让它执行到那个位置的时候暂停下来。我们想看什么,就可以看什么。为此,小熊猫C++提供了一系列控制程序执行的功能。

1 启动调试

通过“运行”菜单或者调试工具栏,点击“调试”,就可以让当前程序以调试模式启动运行。当前程序中如果没有断点,则程序启动后会自动停在main()函数的第一条语句处(变量声明除外),如下图所示(注意当前暂停位置所在行左侧的小箭头):

调试按钮

调试按钮

启动调试后,程序暂停在main函数入口处

启动调试后,程序暂停在main函数入口处

2 退出调试

在程序调试过程中,通过“运行”菜单或者调试工具栏,点击“停止执行”按钮,即可停止调试。

停止按钮

停止按钮

3 断点

断点(Breakpoint)就是程序中预设的暂停点。程序在调试运行到断点位置时,就会暂停。

在小熊猫C++中,单击编辑器左侧边栏区域即可设置/取消断点:

点击编辑器左侧栏设置、取消断点

点击编辑器左侧栏设置、取消断点

设置断点后点击”调试“按钮启动调试,程序就会在断点所在的第22行暂停。注意:程序在运行第20行的scanf语句时,会等待用户输入一个整数,这是scanf语句本身的行为特性,和调试没有任何关系

程序暂停在第23行断点处

程序暂停在第23行断点处

4 单步执行

顾名思义,单步执行就是让程序执行一步后暂停。问题在于,到底多少程序算”一步“?在小熊猫C++的运行菜单中,有这么几种单步执行:

  • 单步跳过(Step Over):一行程序算一步。执行完当前行后暂停。
  • 单步进入(Step Into):如果当前行不包含函数调用,则一行程序算一步;如果这行程序中包含对函数的调用,会在进入函数后暂停;如果找不到该函数的符号信息,则在执行完该函数后暂停。
  • 单步跳出(Step Out):退出当前函数后暂停。
单步跳过、单步进入和单步跳出按钮

单步跳过、单步进入和单步跳出按钮

4.1 单步跳过

在上一节中,程序在我们输入300后,暂停在了第23行断点处。注意这一行中包含了对函数isPrime()的调用。并且注意此时变量i的值为2(2是质数)

如果此时(程序暂停在23行时)点击”单步跳过“,程序会在执行完23行后,停在第24行

单步跳过

单步跳过

4.2 单步进入

让我们退出再重新开始调试,输入300后程序再次暂停在了23行断点处。如果此时(程序暂停在23行时)点击”单步进入“,程序会停在第9行isPrime()函数的入口处:

单步进入

单步进入

4.3 单步跳出

我们现在暂停在了函数isPrime()中。现在点击”单步跳出“按钮,程序会返回第23行(isPrime(i)函数执行完了,但是if判断还没执行)

单步跳出

单步跳出

在小熊猫C++的CPU窗口中,还有两个单步执行按钮:”单步执行一条机器指令“和”单步进入一条机器“指令。有兴趣的同学可以猜一猜,然后自己试试它们的作用是什么?

5 继续执行

程序暂停后,通过”运行“菜单或者调试工具栏选择”继续执行”,程序就会继续以调试方式运行,直到遇到下一个断点,或者程序运行结束为止。

接上一节的例子,点击“继续执行”,程序又会停在第23行断点处。但注意此时i的值已经变成了3

继续运行后再次暂停

继续运行后再次暂停

6 GDB Server调试模式

为了支持在Linux下使用终端调试程序,从0.12.5版本开始,小熊猫C++中新增了gdb server调试模式(在Linux下自动缺省启用,目前在Windows下缺省关闭)。可以通过工具菜单的“选项”菜单项打开选项对话框,然后在选项对话框的“调试器”“通用"页中设置是否启用gdb server调试。

使用gdb server调试选项

使用gdb server调试选项

7 中断(仅gdb server模式下支持)

在gdb server模式下,运行菜单和调试工具栏中会多出一个“中断”按钮。此按钮可以暂停运行中的程序。但是由于此时程序可能正在执行某个运行库中的指令(比如,输出内容到控制台窗口),所以小熊猫C++无法在编辑器窗口中获取和显示程序当前暂停的位置。

在Linux操作系统下可以通过调用栈视图了解程序当前的状态。但是Windows下小熊猫C++后台使用的gdb程序尚无法在中断后获取完整的调用栈信息。

Linux系统下程序中断(暂停)时的状态显示

Linux系统下程序中断(暂停)时的状态显示

5.5.3 - 查看程序状态

在程序暂停时查看程序的状态

通过小熊猫C++的控制程序执行功能,可以帮我们准确将程序暂停到指定的位置。然后,我们就需要去查看程序的状态了。小熊猫C++提供了一系列工具来帮助我们查看程序的状态

1 局部变量视图

在调试时,调试面板的局部变量视图会自动显示当前函数作用域中的所有局部变量(包括函数参数)。

局部变量视图

局部变量视图

2 监视和监视面板

局部变量视图可以自动显示局部变量的状态,这很好。但是如果某个函数里面的局部变量太多,找我想看的变量很麻烦;或者我想看某个全局变量的状态;或者我想看某个表达式的值,怎么办呢?这时就需要使用监视功能了。

2.1 添加监视

比如,我们想在调试过程中监视&n的值(n的地址)。可以在调试工具栏中点击“添加监视”按钮

添加监视按钮

添加监视按钮

然后在对话框中输入我们要监视的表达式:

添加监视按钮

添加监视按钮

在左侧的监视面板中就可以看到我们要监视的表达式了。因为此时我们没有开始调试程序,所以&n的值中显示“执行以求值”。

gdb(小熊猫C++使用的调试器)支持监视任何C、C++表达式。但请保证在表达式中不会出现无穷递归、无限循环等错误,否则gdb调试器会卡死无法正常使用

2.2 查看监视

在程序调试的过程中,小熊猫C++会在程序暂停时自动更新监视的值。请注意示例程序在main函数中暂停,和在isPrime函数中暂停时,&n的变化(main和isPrime中的n虽然同名,但是是两个作用域不同的变量,在内存中的地址不同)

程序在main函数中暂停

程序在main函数中暂停

程序在isPrime函数中暂停

程序在isPrime函数中暂停

3 调用栈视图

我们按照自顶向下或者模块化的思路设计程序时,会以函数为单位来组织和实现的程序的功能。在调试程序时,我们经常需要知道,函数现在正被谁调用?调用者的状态是怎样的?

调试面板中的调用栈视图为我们提供了程序调用栈(Call Stack)的信息。从下图中我们可以看出,当前程序执行到isPrime函数中,它是在main函数的第30行被调用的。

调用栈信息

调用栈信息

在调用栈视图中双击某一行,小熊猫C++就会自动跳转到对应的程序位置。

点击调用栈视图第二行,跳转到isPrime函数被调用的位置

点击调用栈视图第二行,跳转到isPrime函数被调用的位置

4 内存视图

调试面板的内存视图允许我们在调试时,查看程序进程指定内存位置的值。在地址表达式栏中输入任意返回内存地址的表达式,就可以查看指定位置的内容。例如,下面是我们输入“&n"后的显示结果

5 求值工具

除了监视和局部变量之外,我们还可以使用求值工具来快速计算某个表达式。

注意,求值工具可以执行任意C/C++表达式,包括赋值表达式!其效果和在程序中执行该表达式的作用是相同的。例如,我们在求值输入框中输入n=500,就可以将变量n的值改为500。

6 CPU窗口

CPU窗口让我们可以查看程序对应的机器和汇编指令,以及CPU中各寄存器的状态。通过”运行“菜单的”打开CPU窗口“菜单项即可打开CPU窗口。对于学生和初中级用户而言,这个窗口中的信息可以帮助他们更深入的理解C语言程序的实际工作机理。

5.5.4 - 修改变量或内存

在调试时修改变量或内存中的内容

从小熊猫C++ 0.13.2版本开始,我们可以在调试程序时直接修改变量的值或者内存中的数据。初学者可以使用这个功能,更好的理解C语言的变量、数据类型和字符串机制等知识。

1 直接执行表达式

在调试面板的求值框中,我们可以输入任意表达式,包括赋值表达式。通过这一点我们可以对任意变量或者内存地址进行赋值,从而改变它们的值。

在下例中,我们直接在求值框中输入n=10后回车

输入n=10

输入n=10

n的值被修改了

n的值被修改了

2 改变监视变量

在监视面板中,双击要修改的值,就可以对其进行修改。

双击要修改的值

双击要修改的值

进入修改状态

进入修改状态

修改完成

修改完成

可以看到,修改完成后,局部变量视图也同步进行了更新。

3 改变内存的值

和监视面板类似,我们在调试面板的内存视图中,双击要修改的内容,即可直接对其进行修改:

双击要修改的值

双击要修改的值

进入修改状态

进入修改状态

完成修改,注意监视面板中的信息更新

完成修改,注意监视面板中的信息更新

5.6 - 项目管理

使用项目管理、编辑和构建包含多个代码文件的程序

我们在编写复杂的C/C++程序时,会将代码拆分到多个源文件中。这么做有很多好处:

  1. 便于组织和管理代码;
  2. 便于在不同的程序(项目)之间共用代码和利用已有的代码
  3. 减少程序修改后编译的工作量,提高编译速度

小熊猫C++提供了项目功能,可以对多文件程序进行管理、编译运行和调试。

5.6.1 - 多文件程序构建基础

介绍C/C++语言构建可执行文件的基本原理和术语

编译(构建)过程

计算机并不能直接执行C或者C++语言指令,因此C/C++程序必须被翻译(translate)成计算机(CPU)认识的指令(机器语言指令),并按照特定的格式保存在可执行文件(Executable)中之后,才能被计算机载入执行。在C++11(ISO/IEC 14882:2011)标准中,将从C/C++源程序文件到可执行文件的过程称为"translation"。在很多C/C++教材中,也将这个过程称为**“Compilation”(编译)**。

由于compilation/compile在不同的情境下有不同的含义,为了便于的区分,很多工具软件将这个过程称为build(构建)

下图展示了C/C++编译(构建)程序的一般过程:

graph TD
  subgraph 构建
  Source1{{源文件}} -- 预处理 --> TranslationUnit1[编译单元]
  Header1[[头文件]] -.-> TranslationUnit1[编译单元]
  Source2{{源文件}} -- 预处理 --> TranslationUnit2[编译单元]
  Header2[[头文件]] -.-> TranslationUnit2[编译单元]
  Source3{{源文件}} -- 预处理 --> TranslationUnit3[编译单元]
  Header3[[头文件]] -.-> TranslationUnit3[编译单元]
  TranslationUnit1 -- 编译 --> TranslatedUnit1([目标文件])
  TranslationUnit2 -- 编译 --> TranslatedUnit2([目标文件])
  TranslationUnit3 -- 编译 --> TranslatedUnit3([目标文件])
  end
  subgraph 链接
  TranslatedUnit1 & TranslatedUnit2 & TranslatedUnit3 -- 链接 --> Executable[/可执行文件/]
  end

预处理和编译单元

编译的第一步是对源文件(source file)进行预处理(preprocess)。预处理包括转码、标记切分(tokenize)、宏替换等很多工作,但其中最重要的工作是把源文件中#include语句包含的头文件(header)的内容和源文件合并在一起成为一个整体,也就是所谓的"编译单元"(translation unit)。

每一个源文件经过预处理后都会得到一个"编译单元"。

在gcc编译时加入"-E"参数,就可以将源文件预处理后得到的编译单元保存到指定的文件中。

编译和目标文件

编译过程的下一步是将编译单元转换为机器代码,这个步骤一般叫做"编译"(compilation),编译得到的机器代码被称为"translated unit"(“被编译单元”)。 当被编译单元保存到文件中时,我们会将该文件称为"目标文件"(object file),通常以.o或者.obj作为目标文件的后缀名。

因为"被翻译单元"这个说法在中文中比较别扭,所以我们一般用"目标文件"来代替它,即使"目标文件"并没有被实际存到文件里。

说明:很不幸,编译这个词被在不同的地方表示了不同的含义。不过根据上下文,我们一般都能够理解"编译"到底是指从源文件到目标文件,还是从编译单元到目标文件。

链接

链接是整个编译过程中的最后一步,将一个或者多个目标文件整合成一个可执行文件。这是多文件编译时最容易出问题的步骤。

下图是一个典型的链接错误提示(首先,错误提示显示的文件名是个目标文件"xxxx.o";其次,ld(gcc的链接程序)程序错误退出"ld returned 1 exit status"):

常见的错误问题有:

  • 多个目标文件中存在同名的标识符。(在多个源文件中定义了同一个全局变量或者函数)
  • 找不到某个函数的定义。(某个源文件中调用了某个函数,但是在所有的目标文件中都找不到这个函数的定义)

库文件

在链接时我们可能会需要用到.a或者.lib结尾的库文件(library file),这些文件实际上是由多个预先生成的目标文件组成的包。链接某个库文件实际上就是链接包里面的目标文件。

在gcc编译时,指定-lxxx参数,实际是让gcc链接libxxx.a库文件。

使用gcc工具集里的ar命令可以管理和查看.a文件中的内容。下图显示了libstdc++.a库文件中包含的目标文件:

在编译C/C++程序时,缺省gcc会自动链接标准库的库文件。因此,我们不需要告诉gcc怎么找到printf等标准库函数的定义,gcc就能够正确编译和链接普通的程序。

Make与Makefile

gcc一次运行只能进行单个文件的编译,单个文件的编译链接,或者多个文件的链接;无法完成多个文件的编译和链接。因此,需要按照一定的顺序多次运行gcc,才能完成一次完整的多文件编译链接。

此外,我们在维护和修改维护软件时,往往需要在只更新了一两个源文件的情况下重新生成可执行文件。显然,此时只需要对那些修改过的源文件重新编译得到更新的目标文件;没有修改过的源文件没有必要重新编译一遍。

为了方便这个过程,大家使用make工具来管理和执行这个过程。它的核心功能就是检查相关的源文件和头文件和对应的目标文件相比是否有更新,重新编译那些受到变化影响的源文件得到更新的目标文件,然后重新链接所有的目标文件最终得到新的可执行文件。

一般我们会用一个配置文件用来告诉make工具,生成可执行性文件需要哪些目标文件,每个目标文件又对应哪个源文件以及涉及哪些头文件,应该如何编译等等信息。这个配置文件被称为makefile,一般使用Makefile或者Makefile.win作为它的文件名。

小熊猫C++在编译单文件时,会直接调用gcc;在多文件编译(编译项目)时,会根据项目信息,自动生成makefile,然后调用make程序来完成编译。

下面是小熊猫C++自动生成的一个项目makefile:

# Project: 项目23
# Makefile created by Red Panda C++ 1.0.0

CPP      = g++.exe
CC       = gcc.exe
WINDRES  = windres.exe
RES      = 项目23_private.res
OBJ      = main.o glmatrix.o $(RES)
LINKOBJ  = main.o glmatrix.o $(RES)
CLEANOBJ  =  main.o glmatrix.o $(RES)
LIBS     =  -lwinmm -mwindows -lm -lfreeglut.dll -lopengl32 -lwinmm -lgdi32  
INCS     =  
CXXINCS  =  
BIN      = 项目23.exe
CXXFLAGS = $(CXXINCS)  -Wall -Wextra -g3 -pipe -D__DEBUG__
CFLAGS   = $(INCS)  -Wall -Wextra -g3 -pipe -D__DEBUG__
RM       = del /q /f

.PHONY: all all-before all-after clean clean-custom

all: all-before $(BIN) all-after

clean: clean-custom
	${RM} $(CLEANOBJ) $(BIN) > NUL 2>&1

$(BIN): $(OBJ)
	$(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)

main.o: main.c glmatrix.h
	$(CPP) -c C:/Users/royqh/Documents/projects/项目23/main.c -o main.o $(CXXFLAGS) 

glmatrix.o: glmatrix.c glmatrix.h
	$(CPP) -c C:/Users/royqh/Documents/projects/项目23/glmatrix.c -o glmatrix.o $(CXXFLAGS) 

项目23_private.res: 项目23_private.rc 
	$(WINDRES) -i 项目23_private.rc --input-format=rc -o 项目23_private.res -O coff 

从中我们可以看到,"$(BIN)"(也就是"项目23.exe")依赖于"$(OBJ)"(main.o、glmatrix.o等目标文件);而main.o依赖于main.c和glmatrix.h。make程序会根据这些信息来自动判断应该执行哪些操作来生成项目23.exe文件。

5.6.2 - 项目及其使用

使用小熊猫C++的项目功能

创建项目

通过"文件"菜单→“新建”→“新建项目…",可以打开新建项目对话框。

项目视图

新建项目文件

加入项目文件

新建类

5.6.3 - 自定义Makefile

通过自定义Makefile来实现包含复杂步骤的编译过程

5.7 - 试题集

使用试题集快速测试程序的正确性

5.7.1 - 试题和案例

使用试题集快速测试程序的正确性

小熊猫C++使用“试题”(Problem)来实现对使用标准输入输出的程序的自动测试。

  • 试题集是由试题组成的集合。
  • 每个试题就是一道竞赛或者练习题目,包括题目和试题内容,以及多个试题案例
  • 每个试题案例对应一组测试数据,由输入数据期望输出数据组成。
  • 运行当前案例就是将当前案例的输入数据作为标准输入运行当前程序,并将程序的输出保存到输出框中。程序运行结束后,自动比较实际输出和案例的期望输出是否一致。
  • 运行所有案例就是将当前试题的所有案例逐一作为当前案例执行“运行当前案例

通过小熊猫C++主窗口左侧的试题集视图可以管理当前试题集中的试题。通过下方的试题视图可以管理和运行当前试题的案例。

5.7.2 - 从OJ网站下载试题

使用CompetitiveCompanion浏览器插件下载OJ试题

作者:超能少年飞 (2310646553@qq.com)

1. 安装插件

在使用这个可以节约时间的功能之前,请确定你有安装以下的东西:

  1. 小熊猫C++(废话)
  2. 一个名为Competitive Companion 的插件

你不知道第二个是什么?
Competitive Companion 简单来讲就是将你所在的浏览器页面(如果是OJ)上的所有测试点都扒下来。 而这个牛逼的插件是和浏览器绑定的。所以说,不同的浏览器有不同的解决方法:

Google Chrome

由于Chrome的应用商店被一股神奇的力量封锁在了中国大陆之外~~(应该不会有人用梯子吧)~~,所以说,我们要安装的是.crx格式的文件。这个文件可以在神奇的Bing或是百度以 Competitive Companion下载 的关键词搜到。用Google Chrome下载完之后,他会告诉你,这玩意可能危险。此时请不要点放弃!那样就前功尽弃了! 在你点下“保留”之后,它就会保存在你的电脑里了。
现在,请点右上角的三个点,选择“更多工具——扩展程序”,然后将刚刚下载的文件拖到页面里,再确认一下,就OK了!

Microsoft Edge

Edge的应用商店可以访问,但是并没有这款插件。由于Edge的插件与Chrome的插件相通,所以安装步骤与Chrome同理。

Mozila Firefox

FireFox的扩展商店可以访问,且有这款插件。所以可以直接搜索扩展商店,然后安装插件。

其它浏览器

换一个浏览器吧 绝大多数基于Chrome的核心开发,所以和Chrome浏览器有异曲同工之处。

2. 实际使用

可以使用Competitive Companion的情况下

此处以Mozila Firefox为例。
我想要复习一下dfs,于是打开了这道远古题目:NOIP远古老题
然后将数据导入到小熊猫C++里:我们要先点击下图中被红框框起来的图标
然后很快啊,小熊猫就会“咻”的一下蹦出来,然后下面会出现一些神奇的玩意儿:
下面绿框圈起来的,可以分成三个部分来讲解:

  1. 左上角的那个部分,是这道题的名字,应该很好理解吧
  2. 左边那个部分,上面五个按钮从左到右分别是:添加试题案例,删除试题样例,打开答案源代码文件,运行试题集,设置试题集。全部都是字面意思,在此不做说明。
  3. 右边那占了一大半的部分,字面意思,就是从OJ上爬下来的输入输出样例,还有你程序实际输出的答案。

然后经过一番操作,我们把代码写了出来,接下来就要运行了:
点击下面五个按键中的“运行试题集”,然后可能会跳出 “文件未保存” “源代码未编译” “程序文件比执行文件新” 等等提示。与平常编译文件同理,你只要都选 “保存”和“编译”就可以了。
经过万人瞩目的运行时刻,你可能会发现下面那不起眼的“试题样例1”之类的玩意,前面戴上了一个√或是×。这就代表着你的程序是否通过这些测试样例了。如果有些没过,不好意思,请继续去调代码!

在不能使用Competitive Companion的情况下

但是!Competitive Companion这个插件不是万能的!在部分没有被开发者纳入支持名单的OJ(比如本校OJ),你运行Competitive Companion是不会有效果的!
所以说,这种情况下该怎么办呢?这种情况下,请点击下图中的那个被红框圈起来的加号按钮,那是“添加试题集”的意思 然后,就会出现一个全新的试题集,等着你赐予它测试样例。这个时候,你要点“添加试题样例”这个按键,然后一个空白的试题样例就出现了!
现在这个测试样例还是一个空壳子,我们要从OJ上复制下来输入样例和输出样例,让它变成一个有灵魂的测试样例!
Ctrl-C和Ctrl-V应该不用讲吧 将你复制下来的输入和输出分别粘贴到“输入”和“期望输出”里。
然后重复以上两步,就可以达到直接使用Competitive Companion的效果了!

注意:每个测试点要单独增加一个试题样例。

这就是小熊猫C++的试题集功能的简单玩耍方法了。

5.8 - 文件视图

通过文件视图管理和组织代码文件

5.9 - 重构

使用重构功能优化和改善代码

重命名符号

在“重构”或者编辑器的右键菜单中,可以找到“重命名符号”菜单项。其作用是在程序中将指定的符号所有出现的地方全部统一改为新的名称。该功能会自动区分不同作用域的重名符号。

例如,程序中分别存在全局变量text和函数process()中的局部变量text。将局部变量text重命名为text1后,全局变量text仍然保持不变。

该功能可以解除用户修改变量、函数等符号名称时的顾虑,帮助用户编写可读性强的程序。

5.10 - 汇编语言支持

编辑、编译、运行和调试GNU汇编语言程序。

小熊猫C++支持编辑、编译、运行和调试GNU汇编语言程序。

  • 支持GNU汇编语言程序的 语法高亮 显示。
  • 在使用x86 CPU的系统中,支持 常用指令和寄存器名的补全提示
  • 在使用x86 CPU的系统中,光标停留在指令上时,显示该指令的作用
  • 光标停留在立即数上时,显示该数的十六进制和十进制值。
  • 和C/C++语言程序一样,小熊猫C++可以直接编译、运行和调试汇编语言程序。
  • 对于C/C++程序,可通过 “运行”菜单→“生成汇编” 生成对应的汇编程序文件。

5.11 - SDCC支持

编辑和使用SDCC编译器编译单片机程序

从2.24版本开始,小熊猫C++支持编辑SDCC C语言语法的单片机程序,以及使用SDCC编译器生成二进制文件。

  • 在选项对话框→“编译器”→“编译器配置集”页中,点击左上角第二个按钮,选择SDCC编译器所在的文件夹即可添加SDCC编译器配置。
  • 当前编译器配置为SDCC时,代码编辑器支持SDCC程序文件的语法高亮和补全提示。
  • 当前编译器配置为SDCC时,可使用“编译”和“全部重编译”功能生成二进制文件。
  • 在选项对话框→“编译器”→“编译器配置集”页的输出页中,可选择生成的二进制文件类型。

5.12 - 版本管理

使用内置的Git功能对代码文件进行版本管理

从2.24版开始,小熊猫C++发行版中不再提供git版本管理相关功能。强烈推荐windows用户使用tortoisegit进行程序的版本管理。

6 - 相关库

小熊猫C++发行版集成的部分C/C++库使用说明

本章是小熊猫C++发行版中集成的部分C/C++库的教程和使用介绍。

小熊猫C++在发行版所带的编译器中集成了若干教学中常用的库以方便学生使用,包括:

6.1 - EGE

兼容BGI的简易作图库

EGE(Easy Graphics Engine),是windows下的简易绘图库,是一个类似BGI(graphics.h)的面向C/C++语言新手的图形库,它的目标也是为了替代TC的BGI库而存在。

它的使用方法与TC中的graphics.h相当接近,对新手来说,简单,友好,容易上手,免费开源,而且接口意义直观,即使是完全没有接触过图形编程的,也能迅速学会基本的绘图。

编译使用ege库的程序

单文件方式

如果直接使用单文件方式编写ege程序(不创建项目),直接在程序中包含ege.h,编译即可。小熊猫C++的自动链接功能会自动在编译时链接相关的库。

如需修改编译时的链接参数,可通过“工具”菜单→“选项”打开“选项”对话框,在“编译器”→“自动链接”页中找到ege.h,修改相关的链接参数。

项目方式

如果要在项目中使用ege库,请使用新建项目向导中的“多媒体”→“EGE绘图”模板创建项目,即可正常编译。

小熊猫C++ 2.22或更早的版本,请使用新建项目向导中的“多媒体”→“Graphics.h”模板创建项目。

如需修改编译时的链接参数,可以通过“项目”菜单→“项目属性”打开“项目选项”对话框,修改自定义选项。

控制台显示

为了方便调试,缺省编译得到的可执行文件在运行时会显示控制台窗口。如果不想显示它,可以:

  • 单文件方式开发:在自动链接参数中增加-mwindows参数。
  • 项目方式开发:在“项目选项”对话框的“通用”页中,将程序类型改为“Win32图形界面程序”。

6.2 - raylib

简单并且易于使用的游戏编程库

raylib是一个以简单易用为目标的跨平台游戏绘图库,它的特点包括:

  • 免费开源(基于类似于BSD的zlib授权协议)
  • 跨平台支持:Windows, Linux, MacOS, RPI, Android, HTML5等
  • 全部用C语言实现
  • 简单易用
  • 使用OpenGL硬件加速(1.1, 2.1, 3.3, 4.3 or ES 2.0)
  • 支持多种字体(XNA SpriteFonts, BMfonts, TTF, SDF)
  • 支持多种材质格式,包括压缩材质(DXT, ETC, ASTC)
  • 全面支持3D,包括Shapes,Models,Billboards, Heightmaps等
  • 材质系统支持包括经典贴图和PBR贴图
  • 支持动画3d模型(Animated 3d models)
  • 支持多种着色器,包括模型着色器(Model shaders)和后处理着色器(Postprocessing shaders)
  • 提供数学模块,支持矢量、矩阵和四元数(Quaternion)运算
  • 支持多种音乐格式的载入和流媒体播放(WAV, OGG, MP3, FLAC, XM, MOD)
  • 提供50多种编程语言的绑定

教程

raylib和rdrawing中文使用教程

示例程序

下面这个程序绘制了一个旋转的立方体(其实是摄像机在围绕立方体旋转):

#include <raylib.h>
#include <math.h>

int main(void)
{
	// 初始化
	const int screenWidth = 640;
	const int screenHeight = 480;
	
	//启用反锯齿
	SetConfigFlags(FLAG_MSAA_4X_HINT);
	
	//初始化窗口
	InitWindow(screenWidth, screenHeight, "Sample");
	
	// 初始化摄像机
	Camera3D camera = { 0 };
	camera.position = (Vector3){ 40.0f, 20.0f, 0.0f }; //相机所在位置{x,y,z}
	camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; //相机朝向位置{x,y,z}
	camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; //相机正上方朝向矢量
	camera.fovy = 70.0f; //相机视野宽度
	camera.projection = CAMERA_PERSPECTIVE; //采用透视投影
	
	//设置动画帧率(刷新率,fps)为30帧/秒
	SetTargetFPS(30);
	//--------------------------------------------------------------------------------------
	int angle=0; //多边形旋转角度

	// 主游戏循环
	while (!WindowShouldClose())    //关闭窗口或者按ESC键时返回true
	{
		
		double time = GetTime(); 
		// 每次循环更新一帧
		// 摄像机围绕y轴转动
		double cameraTime = time*0.3;
		camera.position.x = (float)cos(cameraTime)*40.0f;
		camera.position.z = (float)sin(cameraTime)*40.0f;
		
		BeginDrawing();
		
		ClearBackground(WHITE);
			//以摄像机视角绘制3d内容
			BeginMode3D(camera);
				DrawCube(Vector3{0,0,0},10,10,10,VIOLET);
				DrawCubeWires(Vector3{0,0,0},10,10,10,BLACK);
			EndMode3D();
		EndDrawing();
	}
	
	//关闭窗口
	CloseWindow();
	
	return 0;
}

对于初学者来说,只要了解了OpenGL的3维坐标系,以及摄像机投影的各项基本参数,很快就可以用raylib编写动画程序啦。

6.3 - rdrawing

基于raylib的2维绘图库

rdrawing是raylib的扩展库raylib-drawing中的一个子库,提供了诸如绘制指定线宽的线段、填充圆形、填充任意形状多边形等raylib缺少的2d绘图功能。

教程

raylib和rdrawing中文使用教程

示例

#include <raylib.h>
#include <rdrawing.h>
#include <time.h>

#define SHRINK_FRAMES 2

Image genBodyImage();

int main() {
	InitWindow(800,600,"Doraemon");
	SetTraceLogLevel(LOG_WARNING);
	SetTargetFPS(30);
	
	Image img=genBodyImage();
	
	Texture texture = LoadTextureFromImage(img);
	
	while(!WindowShouldClose()) {
		BeginDrawing();
		ClearBackground(WHITE);
		DrawTexture(texture,0,0,WHITE);
		EndDrawing();
	}
	
	//Clean up
	UnloadTexture(texture);
	UnloadImage(img);
	CloseWindow();
}

Image genBodyImage(){
	Image img=GenImageColor(800,600,WHITE);
	// 画头
	Color fillColor = (Color){7,190,234,255};
	Color color=BLACK;
	ImageFillRoundRectEx(&img,265, 94, 270, 260, 124, 124,fillColor);
	ImageDrawRoundRectEx(&img,265, 94, 270, 260, 124, 124,1,color);
	
	fillColor = WHITE;								// 脸
	ImageFillEllipseEx(&img, 400, 256, 115, 95, fillColor);
	
	ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);			// 右眼
	ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color);			
	ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);			// 左眼
	ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color);	
	
	fillColor = BLACK;
	ImageFillCircleEx(&img,384,184,6, fillColor);							// 右眼球
	ImageFillCircleEx(&img,416,184,6, fillColor);							// 左眼球
	
	fillColor = (Color){201, 62, 0, 255};						// 鼻子
	ImageFillCircleEx(&img, 400, 208, 15, fillColor);
	
	ImageDrawLineEx(&img,400,223,400,296,1,color);		// 人中
	ImageDrawArcEx(&img,400, 192, 108, 108, PI * 5 / 4, PI * 7 / 4,1,color);	// 嘴
	
	ImageDrawLineEx(&img,358, 227, 310, 209,1,color);							// 胡子
	ImageDrawLineEx(&img,442, 227, 490, 209,1,color);
	ImageDrawLineEx(&img,359, 235, 308, 235,1,color);
	ImageDrawLineEx(&img,441, 235, 492, 235,1,color);
	ImageDrawLineEx(&img,358, 243, 310, 261,1,color);
	ImageDrawLineEx(&img,442, 243, 490, 261,1,color);	
	
	// 画身体
	ImageDrawLineEx(&img, 319, 332, 262, 372,1,color);					// 手臂(上)
	ImageDrawLineEx(&img, 481, 332, 538, 372,1,color);
	ImageDrawLineEx(&img, 304, 396, 284, 410,1,color);					// 手臂(下)
	ImageDrawLineEx(&img, 496, 396, 516, 410,1,color);
	
	ImageDrawLineEx(&img, 304, 385, 304, 478,1,color);					// 腿外侧
	ImageDrawLineEx(&img, 496, 385, 496, 478,1,color);
	ImageDrawArcEx(&img, 400, 479, 15,11,0,PI,1,color);				// 腿内侧
	
	fillColor=WHITE;						// 手
	ImageFillCircleEx(&img, 260,399,27, fillColor);
	ImageDrawCircleEx(&img, 260,399,27, 1, color);
	ImageFillCircleEx(&img, 540,399,27, fillColor);
	ImageDrawCircleEx(&img, 540,399,27, 1, color);
	ImageFillRoundRectEx(&img,288,478,110,27,12,12,fillColor);			// 脚
	ImageDrawRoundRectEx(&img,288,478,110,27,12,12,1,color);			
	ImageFillRoundRectEx(&img,402,478,110,27,12,12,fillColor);
	ImageDrawRoundRectEx(&img,402,478,110,27,12,12,1,color);			
	
	fillColor=(Color){7,190,234,255};							// 身体填充蓝色
	ImageFloodFill(&img,400,400,BLACK,fillColor);
	
	fillColor=WHITE;						// 肚皮
	ImageFillCircleEx(&img,400,381,75,fillColor);
	ImageFillRectangleEx(&img,340,304,120,20,fillColor); // 用白色矩形擦掉多余的肚皮
	
	ImageDrawSectorEx(&img,400,381,58, 58,PI,2*PI,1,color); // 口袋 
	
	// 画铃铛
	fillColor=(Color){169, 38, 0,255};				// 绳子
	ImageFillRoundRectEx(&img,300,323,200,19,12,12,fillColor);
	
	fillColor=(Color){245, 237, 38,255};			// 铃铛外形
	ImageFillCircleEx(&img,400,349,19,fillColor);
	
	fillColor=BLACK;						// 铃铛上的洞
	ImageFillEllipseEx(&img,400,354,4,4,fillColor);
	ImageDrawLineEx(&img,400,357,400,368,3,color);	
	
	ImageDrawLineEx(&img,384,340,416,340,1,color);					// 铃铛上的纹路
	ImageDrawLineEx(&img,384,344,418,344,1,color);
	return img;
}

Image genShrinkImage0() {
	Image img = GenImageColor(800,600, BLANK);
	Color fillColor=WHITE;
	Color color=BLACK;
	ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);			// 右眼
	ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);			// 左眼
	ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color);			
	ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color);	
	
	fillColor = BLACK;
	ImageFillCircleEx(&img,384,184,6, fillColor);							// 右眼球
	ImageFillCircleEx(&img,416,184,6, fillColor);							// 左眼球
	fillColor = (Color){201, 62, 0, 255};						// 鼻子
	ImageFillCircleEx(&img, 400, 208, 15, fillColor);
	return img;
}

Image genShrinkImage1() {
	Image img = GenImageColor(800,600, BLANK);
	Color fillColor=WHITE;
	Color color=BLACK;
	ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);			// 右眼
	ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);			// 左眼
	ImageDrawRoundRectEx(&img,337, 150, 63, 37, 28, 28, 1, color);
	ImageDrawRoundRectEx(&img,400, 150, 63, 37, 28, 28, 1, color);
	
	ImageFillRectangleEx(&img,337,168,63,19,fillColor);
	ImageFillRectangleEx(&img,400,168,63,19,fillColor);
	
	ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color);			
	ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color);	
	
	fillColor = BLACK;
	ImageFillCircleEx(&img,384,184,6, fillColor);							// 右眼球
	ImageFillCircleEx(&img,416,184,6, fillColor);							// 左眼球
	fillColor = (Color){201, 62, 0, 255};						// 鼻子
	ImageFillCircleEx(&img, 400, 208, 15, fillColor);
	return img;
}

Image genShrinkImage2() {
	Image img=GenImageColor(800,600,BLANK);
	Color fillColor=WHITE;
	Color color=BLACK;
	ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);			// 右眼
	ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);			// 左眼
	
	ImageDrawLineEx(&img,337,168,399,168,1,color);
	ImageDrawLineEx(&img,400,168,462,168,1,color);
	
	ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color);			
	ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color);
	fillColor = (Color){201, 62, 0, 255};						// 鼻子
	ImageFillCircleEx(&img, 400, 208, 15, fillColor);
	return img;
}

Image genShrinkImage3(){
	Image img=GenImageColor(800,600,BLANK);
	Color fillColor=WHITE;
	Color color=BLACK;
	ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);			// 右眼
	ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);			// 左眼
	ImageDrawRoundRectEx(&img,337, 150, 63, 37, 28, 28, 1, color);
	ImageDrawRoundRectEx(&img,400, 150, 63, 37, 28, 28, 1, color);
	
	ImageFillRectangleEx(&img,337,150,63,19,fillColor);
	ImageFillRectangleEx(&img,400,150,63,19,fillColor);
	
	ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color);			
	ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color);
	fillColor = (Color){201, 62, 0, 255};						// 鼻子
	ImageFillCircleEx(&img, 400, 208, 15, fillColor);
	return img;
}

Image genShrinkImage4() {
	Image img=GenImageColor(800,600,BLANK);
	Color fillColor=WHITE;
	Color color=BLACK;
	ImageFillRoundRectEx(&img,337, 131, 63, 74, 28, 28, fillColor);			// 右眼
	ImageFillRoundRectEx(&img,400, 131, 63, 74, 28, 28, fillColor);			// 左眼
	
	ImageDrawRoundRectEx(&img,337, 131, 63, 74, 28, 28,1, color);			
	ImageDrawRoundRectEx(&img,400, 131, 63, 74, 28, 28,1, color);	
	fillColor = (Color){201, 62, 0, 255};						// 鼻子
	ImageFillCircleEx(&img, 400, 208, 15, fillColor);
	return img;
}

函数列表

函数名 功能
ImageDrawPointEx 使用指定的大小,在Image对象中画一个点
ImageDrawArcEx 使用指定的线宽和颜色,在Image对象中画一段椭圆弧
ImageDrawCubicBezierEx 使用指定的线宽和颜色,绘制三次贝塞尔曲线
ImageDrawLineEx 使用指定的线宽和颜色,在Image对象中画一条线段
ImageDrawPolylineEx 使用指定的线宽和颜色,在Image对象中画一条多义线(polyline)
ImageDrawRectangleEx 使用指定的线宽和颜色,在Image对象中画一个矩形(仅轮廓线)
ImageDrawRoundRectEx 使用指定的线宽和颜色,在Image对象中画一个圆角矩形(仅轮廓线)
ImageDrawCircleEx 使用指定的线宽和颜色,在Image对象中画一个圆(仅轮廓线)
ImageDrawEllipseEx 使用指定的线宽和颜色,在Image对象中画一个椭圆(仅轮廓线)
ImageDrawPolygonEx 使用指定的线宽和颜色,在Image对象中画一个多边形(仅轮廓线)
ImageDrawSectorEx 使用指定的线宽和颜色,在Image对象中画一个扇形(仅轮廓线)
ImageFillCircleEx 使用指定的颜色,绘制一个填充的圆
ImageFillEllipseEx 使用指定的颜色,绘制一个填充的椭圆
ImageFillTriangleEx 使用指定的颜色,绘制一个填充的三角形
ImageFillRectangleEx 使用指定的颜色,绘制一个填充的矩形
ImageFillRoundRectEx 使用指定的颜色,绘制一个填充的圆角矩形
ImageFillPolygonEx 使用指定的颜色,绘制一个填充的多边形
ImageFillSectorEx 使用指定的颜色,绘制一个填充的扇形
ImageFloodFill 泛洪填充(当遇到颜色为border color的像素时停止)

6.4 - 海龟作图(rturtle)

基于raylib和rdrawing的海龟作图库

rturtle教程

6.5 - {fmt}

{fmt}是一个开源的格式化库,用于替代C的stdio和C++的iostream。

特色:

  • 简便的格式化API,提供本地化用的位置参数。
  • 实现C++ 20 std::format
  • 和python的format类似的格式化字符串语法
  • 使用Dragonbox算法提供快速IEEE 754浮点数格式化和舍入,
  • 可移植的Unicode支持
  • 安全的printf实现,包括POSIX位置参数扩展。
  • 可扩展:支持用户自定义类型
  • 高效:比默认的标准库实现中的(s)printf、iostream、to_string和to_chars更快
  • 源代码和编译后代码尺寸小
  • 可靠:拥有广泛的测试并持续改进
  • 容易使用:无外部依赖,MIT许可
  • 可移植性:在不同平台上提供一致的输出结果,支持旧编译器
  • 代码整洁,不会产生编译警告
  • 默认与本地化环境(Locale)无关
  • 通过FMT_HEADR_ONLY宏,可以作为header-only库使用

代码示例

打印到标准输出

#include <fmt/core.h>

int main() {
  fmt::print("Hello, world!\n");
}

格式化字符串

std::string s = fmt::format("The answer is {}.", 42);
// s == "The answer is 42."
Format a string using positional arguments (run)

std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
// s == "I'd rather be happy than right."

打印chrono时长

#include <fmt/chrono.h>

int main() {
  using namespace std::literals::chrono_literals;
  fmt::print("Default format: {} {}\n", 42s, 100ms);
  fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
}

输出:

Default format: 42s 100ms
strftime-like format: 03:15:30

打印容器

#include <vector>
#include <fmt/ranges.h>

int main() {
  std::vector<int> v = {1, 2, 3};
  fmt::print("{}\n", v);
}

输出:

[1, 2, 3]

在编译期检查格式化字符串

下面的代码在C++20中产生编译器错误,因为对字符串参数来说d是非法的格式符

std::string s = fmt::format("{:d}", "I am not a number");

输出到文件

#include <fmt/os.h>

int main() {
  auto out = fmt::output_file("guide.txt");
  out.print("Don't {}", "Panic");
}

运行速度是fprintf的5到9倍。

7 - 贡献指南

如何帮助完善小熊猫C++和本文档

7.1 - 文档

如何帮助编写和完善小熊猫C++的官方网站和文档

小熊猫C++网站简介

小熊猫C++网站使用Markdown语言来撰写内容,使用hugo工具来对内容排版并生成静态网页。

hugo使用主题来对内容进行排版。由于hugo不支持同时使用多个主题,为了达到更好的视觉效果,作者将小熊猫C++网站分成了两个部分,每个部分由一个hugo网站组成,分别使用不同的主题:

  • 首页和日志,位于sources/main子文件夹中,使用hugo-universal-theme主题生成最终网页
  • 文档,位于sources/docs子文件夹中,使用docsy主题生成最终网页

下载和安装相关工具

hugo

hugo网站上可以下载最新版的hugo-exteneded程序。下载后可以把解压的hugo.exe所在文件夹加入到系统的PATH环境变量中,以方便使用。

node.js

docsy主题需要使用node.js来辅助生成一些需要的内容,因此还需要安装node.js。直接从官网下载安装即可。

获取小熊猫C++网站源码

请按下列步骤获取小熊猫C++的网站源码:

  1. 登录gitee网站。(如果没有账号请注册一个)
  2. 打开小熊猫C++网站项目仓库,点击网页右上方的fork按钮,fork一个仓库到自己的账号中。
  1. 打开fork得到的位于自己账号下的仓库,点击网页的克隆/下载,复制仓库的网址。
  2. 使用git或者支持git的其他工具将仓库clone到本机文件夹中。
  3. 进入sources/docs文件夹,在控制台或者shell下执行下列指令:
npm install -D autoprefixer
npm install -D postcss-cli
npm install -D postcss

说明:由于国内访问npm官方仓库速度较慢,建议用户预先将npm的仓库设为taobao等国内镜像。

在本地查看修改效果

网站首页和日志

进入sources/main文件夹,执行:

hugo server

成功执行后,按照hugo运行后的提示信息,在浏览器中打开对应的本地网址,即可查看网站首页和日志排版后的效果

文档

进入sources/docs文件夹,执行:

hugo server

成功执行后,按照hugo运行后的提示信息,在浏览器中打开对应的本地网址,即可查看文档排版后的效果。

提交修改后的网站源码

完成内容的修改后,提交(commit)修改,并将其推送(push)到gitee仓库中。

然后在gitee仓库的网页中找到**"+Pull Request"**按钮,进行提交即可。

7.2 - 图标集

如何为小熊猫C++制作图标集

图标是程序外观的重要构成要素。不同的图标可以赋予程序不同的观感,如下面两幅图所示:

新外观图标集

新外观图标集

蓝天图标集

蓝天图标集

小熊猫C++使用图标集来组织和管理图标。本文介绍如何使用小熊猫C++的自定义图标集功能自行制作和更换图标集。

启用自定义图标集

通过"工具"菜单→“选项"打开"选项"对话框,在它的"环境”→“外观"页中勾选"使用自定义图标”,点击"确定"后就启用了小熊猫C++的自定义图标集功能。

再次打开"选项"对话框,在它的"环境"→“文件夹"页中,可以看到自定义图标集所在的文件夹,点击右边的按钮即可打开该文件夹。

从上图中可见,小熊猫C++已经将内置的三个图标集复制到了自定义图标文件夹中 。

用户可以从中选择一个图标集作为蓝本制作副本,然后在此基础上制作自己的图标集。

info.json文件

在每个图标集的文件夹下都包含一个info.json文件,里面定义了关于该图标集的基本信息。在制作新图标集时,首先应修改info.json中的信息。以新外观(newlook)图标集为例,其info.json的内容如下:

{
    "name":"New Look",
    "name_zh_CN": "新外观",
    "version": "1.0",
    "author": "Roy Qu (royqh1979@gmail.com)"
}

图标文件

为了能够在不同分辨率下都能清晰的显示图标,小熊猫C++的图标集仅支持使用SVG矢量格式的图形文件,每个文件对应一个图标。

作者推荐使用inkscape来创建和编辑SVG文件。

贡献图标集

向小熊猫C++贡献图标的推荐方式是使用github或者gitee的PR(Pull Request)功能。把新的图标集放入小熊猫C++源码的RedPandaIDE/resources/iconsets子文件夹下,提交PR即可。

不会使用PR功能的用户,也可以通过小熊猫C++的QQ群与作者直接联系。

7.3 - 主题

如何为小熊猫C++制作主题(调色板)

主题(调色板)规定了小熊猫C++在绘制界面时所使用的各种颜色。本文介绍如何使用小熊猫C++的自定义主题功能来更改程序的外观。

启用自定义主题

通过"工具"菜单→“选项"打开"选项"对话框,在它的"环境”→“外观"页中勾选"使用自定义主题”,点击"确定"后就启用了小熊猫C++的自定义主题功能。

再次打开"选项"对话框,在它的"环境"→“文件夹"页中,可以看到自定义主题所在的文件夹,点击右边的按钮即可打开该文件夹。

从上图中可见,小熊猫C++已经将内置的三个主题复制到了自定义主题文件夹中 。

主题文件

自定义主题文件夹中每个文件名以.json结尾的文件定义了一个主题。例如,高对比度主题的contrast.json文件内容如下:

{
    "name":"contrast",
    "name_zh_CN": "高对比度主题",
    "isDark": true,
    "default scheme": "Twilight",
    "default iconset": "contrast",	
    "palette": {
        "PaletteWindow":"#000000",
        "PaletteWindowText":"#FFFFFF",
        "PaletteBase":"#0A0A0A",
        "PaletteAlternateBase":"#0F0F0F",
        "PaletteButton": "#141414",
        "PaletteButtonDisabled": "#000000",
        "PaletteBrightText": "#ff0000",
        "PaletteText":"#FFFFFF",
        "PaletteButtonText":"#FFFFFF",
        "PaletteButtonTextDisabled":"#9DA9B5",
        "PaletteHighlight":"#aa1f75cc",
        "PaletteDark":"#ff232323",
        "PaletteHighlightedText":"#ffe7e7e7",
        "PaletteToolTipBase":"#66000000",
        "PaletteToolTipText":"#ffe7e7e7",
        "PaletteLink":"#ff007af4",
        "PaletteLinkVisited":"#ffa57aff",
        "PaletteWindowDisabled":"#FFFFFF",
        "PaletteWindowTextDisabled":"#FFFFFF",
        "PaletteHighlightDisabled":"#FFFFFF",
        "PaletteHighlightedTextDisabled":"#FFFFFF",
        "PaletteBaseDisabled":"#0A0A0A",
        "PaletteTextDisabled":"#9DA9B5",
        "PaletteMid": "#FFFFFF",
        "PaletteLight": "#505050",
        "PaletteMidLight": "#00ff00"
    }
}

主题文件中重要的属性及其作用见下表:

属性名 作用
name 主题英文名
name_zh_CN 主题中文名
isDark 是否是深色主题*(背景颜色深,文字颜色浅)。true表示是深色主题,false表示不是。
default scheme 缺省使用的编辑器配色方案
default iconset 缺省使用的图标集
palette 调色板颜色定义

关于深色主题:小熊猫C++使用不同的算法为深色和浅色主题计算边框、阴影和过渡。所以请将isDark属性设为正确的值。

贡献主题

向小熊猫C++贡献主题的推荐方式是使用github或者gitee的PR(Pull Request)功能。把新的主题文件放入小熊猫C++源码的RedPandaIDE/themes子文件夹下,提交PR即可。

不会使用PR功能的用户,也可以通过小熊猫C++的QQ群与作者直接联系。

7.4 - 配色方案

如何为小熊猫C++制作编辑器的配色方案

与旧版的Dev-C++相同,小熊猫C++使用配色方案(scheme)来管理如何在编辑器中显示不同内容。

导出配色方案

在"选项"对话框中的"编辑器"→“配色"页中,选择"导出…“即可导出配色文件,如下图所示:

贡献配色方案

向小熊猫C++贡献配色方案的推荐方式是使用github或者gitee的PR(Pull Request)功能。把配色访问文件(.scheme文件)放入小熊猫C++源码的RedPandaIDE/colorschemes子文件夹下,提交PR即可。

不会使用PR功能的用户,也可以通过小熊猫C++的QQ群与作者直接联系。

8 - 常见问题

小熊猫C++使用中的常见问题及其解答

编译器相关

小熊猫C++中每个编译器有Debug和Release两个配置集,有何区别?

配置类型 作用
Release 生成优化、静态链接的可执行文件。其执行速度最快,可以脱离gcc环境独立运行
Debug 生成调试用的可执行文件;其中包含了调试信息和符号,运行速度相对较慢;脱离gcc环境运行时会提示缺少dll文件

MinGW-w64官方的版本只有8.1,为什么小熊猫C++自带的MinGW-w64 GCC版本是11.2 / 13.1?

首先必须需要说明,MinGW-w64和GCC是两回事:GCC是一个C/C++编译器,而MinGW / MinGW-w64是windows系统下的C/C++基本运行函数库。

截止2022年5月,GCC的官方网站上发布的GCC最新版本已经是12.1; MinGW-w64官方日志中发布的MinGW-w64的最新版本是10.0.0。

小熊猫C++ 1.0.6带的gcc编译器版本是基于MinGW-w64库的GCC 11.2。

网上流传比较广的MinGW-w64 gcc 8.1实际的版本号是gcc 8.1和MinGW-w64 6.0,它来源于MingW-W64-builds网站,该网站提供了mingw-w64库的最新版本,但并未提供最新的基于MinGW-w64的GCC编译器。如果想在windows下使用最新的mingw-w64库和gcc编译器,可以考虑安装MSYS2

小熊猫C++自带的MinGW-w64 GCC是哪儿来的?为什么不使用MSYS2版本?

2.22版前小熊猫C++自带的MinGW-w64 GCC(包括32位和64位)均来自于Qt wiki

2.23版之后小熊猫C++自带的MinGW-w64 GCC 13.1来自于mingw builds,并做了如下改动:

之所以不使用MSYS2版本的MinGW-w64 GCC编译器,是因为它的gdb编译器存在bug,当所在文件夹的完整路径中包含非ascii字符时,会无法启动。这会导致小熊猫C++无法调试程序。而qt版本的gcc编译不存在这个问题。

小熊猫C++自带的Clang编译器是哪儿来的?

由于clang只支持gbk编码,在中文windows下处理中文输入非常麻烦,不利于初学者和教学使用,所以从小熊猫C++ 1.1.2版本开始不再自带clang编译器。有兴趣的用户可以自行从LLVM MinGW下载最新版的clang编译器。

小熊猫C++自带的Clang编译器来自于MSYS2。是的,这个版本的gdb同样存在当所在文件夹的完整路径中包含非ascii字符时,无法启动的bug。但这已经是目前为止作者在网上能找到的最好的可独立使用的Clang编译器发行版了。

Clang编译器和GCC编译器有啥区别?如何选择?

GCC是一个久经考验的开源C/C++编译器,大多数编程竞赛和OJ(网上判题)网站都在后台使用这个编译器。和Clang相比,它的优点是:

  • 支持文件的字符编码转码操作。在小熊猫C++中用它编译的程序里可以直接用printf或者cout输出中文字符串,而基本不用担心乱码问题。
  • 遇到问题时在网上比较容易找到相关的解答。

Clang是相对较新的开源C/C++编译器。它的优点是:

  • 提供比gcc更直观友好的错误提示信息
  • 支持-fsanitize=address参数,编译出的程序在检测到内存/数组访问越界行为时会自动提示并退出。

缺点是:

  • 不支持文件的字符编码转码操作。容易遇到中文乱码问题

所以,对于自学C/C++,或者不太容易获得教师答疑的用户来说,建议使用GCC编译器

项目相关

windows下,项目全部重新编译时显示“clean Error 127 (ignored)”

请检查系统环境变量PATH里的文件夹中是否存在sh.exe文件。将其改名或者移除即可。

错误原因: 小熊猫C++构建项目使用的mingw32-make会优先运行PATH中的sh.exe,然后再查找del程序。而del是windows系统控制台程序cmd.exe自带的命令,sh无法找到它,因此会出现Error 127找不到命令错误。

Clang相关

如何让用Clang编译的程序正确显示中文

使用wchar_t字符串代替char字符串。参考下面的c程序(在cpp程序中应使用wcout代替cout)

**注意:由于MinGW-w64中stdlib的bug,该程序使用gcc编译时运行结果乱码

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
	wchar_t msg[200];
	wchar_t name[100];
    // 将程序的Locale设为简体中文,这一步很重要
	setlocale(LC_ALL,"zh_CN");

	wprintf(L"你叫什么?");
	wscanf(L"%ls",name);
	wcscpy(msg,L"你好,");
	wcscat(msg,name);
	wprintf(L"%ls\n",msg);
	return 0;
}

如何让用Clang编译的ege程序正确显示中文

使用wchar_t字符串代替char字符串。参考下面的c程序

#include <graphics.h>
#include <wtypes.h>
#include <locale.h>

#define BUF_SIZE 4096

int main() {
	wchar_t buf[BUF_SIZE+1];
	initgraph(640,480);	
	inputbox_getline(L"名字",L"名字",buf,BUF_SIZE);	
	xyprintf(200,200,L"你好!%ls",buf);
	getch();
	return 0;
}