C++ 程序文档生成器介绍(doxygen)

2023-11-07


http://ly4cn.cnblogs.com/archive/2005/11/23/282637.html

 

程序文档,曾经是程序员的一个头痛问题。写一个程序文档,比较花时间,但不是很难;麻烦的是当程序修改后,程序文档也要跟着同步更新,否则文档和程序就要脱节,文档也就变成没用的东西了。

好在有许多好用的文档生成器来解决这个问题。目前比较流行的C++文档生成器是doxygen。
本文就简单的介绍一下doxygen的文档注释方法,以供初学者参考:

C++ 程序文档生成器介绍(doxygen)     沐枫网志

1. 模块定义(单独显示一页)
/*
 * @defgroup 模块名 模块的说明文字
 * @{
 */
 
 ... 定义的内容 ...
 
/** @} */ // 模块结尾
 
2. 分组定义(在一页内分组显示)
/*
 * @name 分组说明文字
 * @{
 */
 
 ... 定义的内容 ...
 
/** @} */
 
3. 变量、宏定义、类型定义简要说明
/** 简要说明文字 */
#define FLOAT float
 
/** @brief 简要说明文字(在前面加 @brief 是标准格式) */
#define MIN_UINT 0
 
/*
 * 分行的简要说明 /n
 *  这是第二行的简要说明
 */
int b;
 
4. 函数说明
/*
 * 简要的函数说明文字 
 *  @param [in] param1 参数1说明
 *  @param [out] param2 参数2说明
 *  @return 返回值说明
 */
int func(int param1, int param2);
 
/*
 * 打开文件 /n
 *  文件打开成功后,必须使用 ::CloseFile 函数关闭。
 *  @param[in] file_name 文件名字符串
 *  @param[in] file_mode 文件打开模式字符串,可以由以下几个模块组合而成:
 *  - r 读取
 *  - w 可写
 *  - a 添加
 *  - t 文本模式(不能与 b 联用)
 *  - b 二进制模式(不能与 t 联用)
 *  @return 返回文件编号
 *  - -1 表示打开文件失败
 
 *  @note 文件打开成功后,必须使用 ::CloseFile 函数关闭
 *  @par 示例:
 *  @code
    // 用文本只读方式打开文件
    int f = OpenFile("d://test.txt", "rt");
 *  @endcode
 
 *  @see ::ReadFile ::WriteFile ::CloseFile
 *  @deprecated 由于特殊的原因,这个函数可能会在将来的版本中取消。
 */
int OpenFile(const char* file_name, const char* file_mode);
 
5. 枚举类型定义
/** 枚举常量 */
typedef enum TDayOfWeek
{
SUN = 0,  /**<  星期天(注意,要以 “<” 小于号开头) */
MON = 1,  /**<  星期一 */
TUE = 2,  /**<  星期二 */
WED = 3,  /**<  星期三 */
THU = 4,  /**<  星期四 */
FRI = 5,  /**<  星期五 */
SAT = 6   /**<  星期六 */
}
/** 定义类型 TEnumDayOfWeek */
TEnumDayOfWeek;  
  
6. 项目符号标记
  /* 
   *  A list of events:
   *    - mouse events
   *         -# mouse move event
   *         -# mouse click event/n
   *            More info about the click event.
   *         -# mouse double click event
   *    - keyboard events
   *         -# key down event
   *         -# key up event
   *
   *  More text here.
   */
 

结果为:

A list of events:

  • mouse events
    1. mouse move event
    2. mouse click event
      More info about the click event.
    3. mouse double click event
  • keyboard events
    1. key down event
    2. key up event

More text here.

代码示范:
/**/ /*
 * @defgroup EXAMPLES 自动注释文档范例
 * @author  沐枫
 * @version 1.0
 * @date    2004-2005
 * @{
 
*/



/**/ /*
 * @name 文件名常量
 * @{
 
*/


/**/ /** 日志文件名 */
#define  LOG_FILENAME "d://log//debug.log"
/**/ /** 数据文件名 */
#define  DATA_FILENAME "d://data//detail.dat"
/**/ /** 存档文件名 */
#define  BAK_FILENAME "d://data//backup.dat"

/**/ /** @}*/   //  文件名常量

/**/ /*
 * @name 系统状态常量
 *  @{
 
*/

 
/**/ /** 正常状态 */
#define  SYS_NORMAL 0
/**/ /** 故障状态 */
#define  SYS_FAULT 1
/**/ /** 警告状态 */
#define  SYS_WARNNING 2

/**/ /** @}*/   //  系统状态常量



/**/ /** 枚举常量 */
typedef 
enum  TDayOfWeek
{
        SUN 
= 0/**//**< 星期天 */
        MON 
= 1/**//**< 星期一 */
        TUE 
= 2/**//**< 星期二 */
        WED 
= 3/**//**< 星期三 */
        THU 
= 4/**//**< 星期四 */
        FRI 
= 5/**//**< 星期五 */
        SAT 
= 6  /**//**< 星期六 */
}

/**/ /** 定义类型 TEnumDayOfWeek */
TEnumDayOfWeek;  
/**/ /** 定义类型 PEnumDayOfWeek */
typedef TEnumDayOfWeek
*  PEnumDayOfWeek; 

/**/ /** 定义枚举变量 enum1 */
TEnumDayOfWeek enum1;        
/**/ /** 定义枚举指针变量 enum2 */
PEnumDayOfWeek p_enum2; 



/**/ /*
 * @defgroup FileUtils 文件操作函数
 * @{
 
*/


/**/ /*
 * 打开文件 /n
 *  文件打开成功后,必须使用 ::CloseFile 函数关闭。
 *  @param[in] file_name 文件名字符串
 *  @param[in] file_mode 文件打开模式字符串,可以由以下几个模块组合而成:
 *  - r 读取
 *  - w 可写
 *  - a 添加
 *  - t 文本模式(不能与 b 联用)
 *  - b 二进制模式(不能与 t 联用)
 *  @return 返回文件编号
 *  - -1 表示打开文件失败
 
 *  @note 文件打开成功后,必须使用 ::CloseFile 函数关闭
 *  @par 示例:
 *  @code
    // 用文本只读方式打开文件
    int f = OpenFile("d://test.txt", "rt");
 *  @endcode
 
 *  @see ::ReadFile ::WriteFile ::CloseFile
 *  @deprecated 由于特殊的原因,这个函数可能会在将来的版本中取消。
 
*/

int  OpenFile( const   char *  file_name,  const   char *  file_mode);

/**/ /*
 * 读取文件 
 *  @param[in] file 文件编号,参见:::OpenFile
 *  @param[out] buffer 用于存放读取的文件内容
 *  @param[in] len 需要读取的文件长度
 *  @return 返回读取文件的长度
 *  - -1 表示读取文件失败
 
 *  @pre /e file 变量必须使用 ::OpenFile 返回值
 *  @pre /e buffer 不能为 NULL
 *  @see ::OpenFile ::WriteFile ::CloseFile
 
*/

int  ReadFile( int  file,  char *  buffer,  int  len);

/**/ /*
 * 写入文件 
 *  @param[in] file 文件编号,参见:::OpenFile
 *  @param[in] buffer 用于存放将要写入的文件内容
 *  @param[in] len 需要写入的文件长度
 *  @return 返回写入的长度
 *  - -1 表示写入文件失败
 
 *  @pre /e file 变量必须使用 ::OpenFile 返回值
 *  @see ::OpenFile ::ReadFile ::CloseFile
 
*/

int  WriteFile( int  file,  const   char *  buffer,  int  len);

/**/ /*
 * 关闭文件 
 *  @param file 文件编号,参见:::OpenFile
 *  @retval 0  为成功
 *  @retval -1 表示失败
 
 *  @see ::OpenFile ::WriteFile ::ReadFile
 *  @deprecated 由于特殊的原因,这个函数可能会在将来的版本中取消。
 
*/

int  CloseFile( int  file);

/**/ /** @}*/   //  文件操作函数

/**/ /** @}*/   //  自动注释文档范例


生成的chm文档截图:



范例下载:
/Files/ly4cn/doxygen_example.rar
 
 

Doxygen 源代码文档自动生成器的使用笔记

 

google 上搜了很久的关于 Doxygen 使用方法的咚咚,只不过都是英文,而且都很多的规则。实际上大家只需要告诉基本的规则就可以。下面是我对 Doxygen 的摸索

 

首先熟知 Doxygen 产生的文件的基本结构 ( Html 1.4.6 为例 )

Header (头部)

MainPage  Files  Classes

 

那么我们首先建立两个类吧,以典型的 Shape 它的继承类 Rectangle 为例

(为了表示那些是我的解释约定 ~ 为解释符号 其他的头文件和源文件的具体内容)

// shape.h

 

~ 在这个头文件中首先要有一些关于本文件的一些信息或者公司的 copyright 信息

~ 至于你想写什么,发挥你的创意把。

 

/** /file  

 * <pre><b>Richard Zeng Shape Class File Source</b></pre>

   ~ <pre></pre> 为居中显示

*  <pre><b>Copyright and Use</b></pre>

 

* /author Richard Zeng

* /date 2006-3-23

 

~ /author /date Doxygen 的两个关键字

/author 为作者标题

  /date 为日期标题

 

* <pre>zengyongjoy@gmail.com</pre>

  <b>All rights reserved.</b>

*/

 

 

/** class shape define

 * this is the base class for all Shape

 */

 

~ Shape 类定义的前面请加上解释,否则这个类就不会产生很重要的

 

class Shape{

public :

       Shape();

       ~Shape();

 

       virtual void Draw(CDC* pDC);

};

 

 

// shape.cpp

 

/** /file

* <pre><b>Richard Zeng Shape Class File Source</b></pre>

 

*  <pre><b>Copyright and Use</b></pre>

 

* /author Richard Zeng

* /date 2006-3-23

 

* <pre>zengyongjoy@gmail.com</pre>

<b>All rights reserved.</b>

*/

 

~ 上面的就不用说了吧

#include "shape.h"

 

~ 解释,随便你写什么都可以的

~ 这里我们可以看出在 CPP 中加注释比较好

~ 每个函数的实现都必须加上注释否则就没有这个函数拉

 

/** default constructor*/

Shape ::Shape()

{

 

}

 

/** destructor */

Shape ::~Shape()

{

 

}

 

 

/** Draw funtion for this shape

 * /param CDC* pointer to MFC CDC

 */

 

~ /param Doxygen 的关键字 用于定义参数

~ /return 为返回关键字

void Shape::Draw(CDC* pDC)

{

 

}

 

//Rectangle.h

/** /file __FILE__

* <pre><b>Richard Zeng Shape Class File Source</b></pre>

 

*  <pre><b>Copyright and Use</b></pre>

 

* /author Richard Zeng

* /date 2006-3-23

 

* <pre>zengyongjoy@gmail.com</pre>

<b>All rights reserved.</b>

*/

 

 

#include "shape.h"

 

 

/** Rectangle class define

*/

class Rectangle:publicShape{

public :

       Rectangle();

       ~Rectangle();

 

       void Draw(CDC*pDC);

 

private :

       int width,height;

};

 

 

//Rectangle.cpp

 

/** /file __FILE__

* <pre><b>Richard Zeng Shape Class File Source</b></pre>

 

*  <pre><b>Copyright and Use</b></pre>

 

* /author Richard Zeng

* /date 2006-3-23

 

* <pre>zengyongjoy@gmail.com</pre>

<b>All rights reserved.</b>

*/

 

 

/** default constructor */

Rectangle ::Rectangle()

{

 

}

 

/** destructor */

Rectangle ::~Rectangle()

{

 

}

 

 

/** Draw function

 * /param CDC* pointer to MFC CDC Class

 */

void Rectangle::Draw(CDC* pDC)

{

 

}


o_1.PNG  

 

下面是 Doxygen 的主要操作步骤

首先我们在 MainPage 中看到 ProjectName ProjectVersion (在 Doxygen Wizhard Step1

中输入就可以啦 )

     

 

  o_2.PNG

 

 

 

 

 

 

 

 

 

 

 

 

然后在 Step2

中选择保存文件的位置

 

Step3 选择工作目录

Step4 点击 Start 按钮, ok 完成。

打开输出文件的位置。 Html 文件就生成拉。


http://www.codeproject.com/KB/tips/doxysetup.aspx

Welcome!

Doxygen is a free1) tool that extracts specific source code comments and analyzes the declarations of your code, to create a comprehensive online documentation, similar to the Tools/Build Comment web pages command in Visual Studio.NET. If you want the same for VC++6, or maybe some more flexibility and options, this article is for you.

Once setup, Doxygen can generate create a HTML documentation of your code at one click. It's still you who has to write the documentation, and if you want quality, it's still your job. However, an automated system can do a lot of vanilla tasks, and setting up the one-click documentation process is the first step to take: if you see the results of your effort immediately, it will soon feel natural to add the right type of comments.

1) Doxygen is written by Dimitri van Heesch, and released under the GNU public license (GPL). The documentation created by doxygen is not affected by the GPL. See the Doxygen Homepage for more information.

What do I have for you today?

  1. Setting it up - a quick step-by-step guide to setting up and integrating doxygen with VC++ 6
  2. Documenting Basics - hot to make doxygen understand your comments.
  3. Rationale - why to use doxygen? (skip if you are already convinced)
  4. Working with Doxygen - discusses the sample setup from 1), and provides an introduction to the most important doxygen features.
  5. Additional Resources (not much right now)

So let's jump right in!

Setting it up

This will show you how to integrate doxygen in VC++ 6, and set it up for one of your projects. I assume you already have a project you want to try doxygen on (if not, any C++ file will do). The whole process will take about 5 minutes (depends on your download speed).

Note: this setup does not work very well if you have a workspace with multiple projects in sub folders. See below for more.

doxygen binaries [^] 1. Download the Win32 binaries and install them I'll assume in the following you installed doxygen in c:/program files/doxygen.
doxygen tools 2. Download and extract my doxygen tools and keep them safe and warm in a folder of your choice. They contain all the individual files mentioned in this article
Add VC++ Tool:
"doxygen"
Add a new custom tool, called "DoxyGen", with the following parameters:
  • Command: c:/program files/doxygen/bin/doxygen.exe (or where you installed it)
  • Arguments: "$(WkspDir)/default.doxygen" (the config file - include the quotes!)
  • Initial Directory: "$(WkspDir)"
  • Check the "Use output directory" box
Add VC++ Tool:
"view results"
add another tool, to view the results new "View DoxyDoc" tool, to view the results:
  • Command your favorite browser, e.g. c:/program files/internet explorer/iexplore.exe
  • Arguments: "$(WkspDir)/doxydoc/index.html"
  • Initial Directory: leave empty
Add to project
  • open the project you want to add the file to
  • copy the default.doxygen file into your project folder (this file contains doxygen configuration options)
  • open it for editing in VC++
  • change the ***PROJECT NAME*** to the name of your project
  • right click the file, and choose "Insert File into Project / <project name>". If you use VSS, I'd also add it to SourceSafe
You're done! Try! choose Tools/doxygen from the menu, and watch the magic happen (doxygen will log it's progress and complaints to the output window).
Choose Tools/View results to explore the documentation.

The "Main Page" is probably rather boring. Click on "Data Structures" in the top line to browse your classes etc.

Documenting Basics

Unless you already use some comment style that doxygen understands, the documentation is pretty much meaningless. So what can you do?

1. Add a comment block before classes and structures, using ///

Just use /// for the comment block:

/// SNAPINFO holds the data for calculating a modified window rect. Since it
/// only works on coordinate rects, it can be used without any actual Windows.
struct SNAPINFO
{
   // ...
}

2. Add a brief comment to to class member declarations

Use /// if you put a single line before the member. Use ///< if you put the comment behind the member

struct SNAPINFO
{
    /// Init, using a pre-change and a post-change rectangle
    void Init(RECT const & oldRect, RECT const & newRect, DWORD snapwidth); 

    void SnapHLine(int y); ///< Snap to a horizontal line
}

3. Add a detailed description to the method implementation

as with classes, use a /// - comment block

/// Initializes the structure with an old an a new rectangle.
/// use this method if the window is about to be moved or resized (e.g. in
/// WM_SIZING or WM_MOVING handler)
void Init(RECT const & oldRect, RECT const & newRect, DWORD snapwidth)
{
  // ...
}

I prepared an example for a small class of another article, which had virtually no documentable comments.

original code [^] documentation [^]
brief comments added [^] documentation [^] 13 new lines
2 with comment style modified
method desciptions added [^] documentation [^] 14 additional lines (with ehavy copy&paste)
without EXTRACT_ALL option documentation [^]

Note: as soon as you have added a basic doxy-comment to the important classes, you should turn off the EXTRACT_ALL option (as done in default2.doxygen). Undocumented classes are excluded, This will very much reduce the clutter in the detailed documentaiton section.

Rationale

When working with VS.NET I noticed that the Tools/Build comment web pages is a great motivaiton for me to add useful function and class comments to my sources. Having a large VC6 code base to maintain, which, for a huge part, already has the comments, but no tool to extract, I was pointed to doxygen, and got it running in relatively short time. So, maybe you're not convinced, so here are three questions for you, with some (suggestive) answers.

First Question: Do You need a software documentation?

Reasons are many:

  • your company requires some documentation
  • you're not convinced you understand all of your code after not looking at it for half a year
  • your co-workers pester you with ""how do I do this" questions about your tool library.
  • you plan to retire or move on, and don't want your precious code to end up in the garbage, pillaged and rewritten by someone you don't even know, just because he doesn't take the time for it.
  • you feel better

Of course you can live without for an amazinghly long time, especially when you work on your own, or in a very small team. However, once a project grows beyond a certain size, you'll start to want some formal documentation. And the earlier you start, the better it is. Having set up a tool ready to be used, waiting for you tears down the biggest obstacle - getting started.

Second Question: Why use an automated system?

  • Documentation is up-to-date
    You are much more likely to change a comment atop of the function you fiddle with, than fire up MS Word, look for the function documentation, and change it there.
  • Reuse of your own comments
    Assuming you already discovered the virtue of commenting your own code, the market value of your comments just doubled.
  • automatic formatting, and crosslinking
    with a few simple markups, you get documentation that looks professional and consistent, and creates links to the description of all important entities. Forget about struggling with MS Word.
  • In-code comments carry important meta information
    Not all important information is available from the actual "raw" source code. Interface contracts, pre- and post-conditions, side effects, meaning of special parameters, etc. need to be known to anyone who is to maintain the code - be it yourself or someone else. A formal style for these comments, in conjucntion with a parser (like doxygen's XML export) can make this informaiton available in customized format for various recipients: be it project management, testers, and the like.

Third Question: Why doxygen?

  • It's free - so it's perfect for
    • cheapskates
    • sneaking it into the development process, in case noone cares about at your place
    • evaluating if and how an automated documentation system can help you
    • find out what features you expect when you shop for something better
  • OpenSource with installer
    It's fairly comfortable to use (see also "Using Doxygen" below), so having the source code available comes as an added bonus.
  • Configurable
    With a basic style sheet, and twiddling the options in the doxygen configuration file (easy by using the doxywizard), you can customize many aspects ofthe documentation to your needs.

Documenting an existing code base

Maybe you have a large project, where you wished someone would have had the patience to add extractable comments. Yet, the idea of walking through documenting 10.000 lines of code, and documenting them makes you shudder. Here are some suggestions:

  • Set up doxygen for the project. It's five minutes, and without nothing will happen
  • Document everything you write anew.
  • Touch up the code you work on. If you fiddle around with some function anyway, it's easiest to add some extra comments. Often it is just copying around / adjusting some existing comments to look a bit nicer.
  • Spend 5 minutes before lunch break on adding comments. Or: comment one function for each visit to the CodeProject lounge

Soon you will feel more "fluid" in documenting your code, and adding brief comments to an existing class is a matter of minutes. If the benefits of having the documentation kick in, you are encouraged to carry on.

Working with Doxygen

The setup used above is quite generic. You can generate a default configuration file using doxygen -g, or by using the doxywizard. the latter makes playing around with various options fairly easy.

For each docmentable entity, doxygen looks for a brief comment, and a detailed description. The brief comment is addedto various overviews (liek the class member listing).

Comment Style

Doxygen recognizes other comment formats as well - I chose the above for both personal taste and compliance with those understood in .NET. For a comprehensive list, see Commenting the code in the doxygen documentation.

Other doxygen Options:

For the default.doxygen, I changed some of default options, notably:

  • EXTRACT_ALL enabled: so some generation is created even for "undocumented" code
    I'd strongly recommend for existing projects to first add some documentation to the most important class declarations and methods, and then turn off the EXTRACT_ALL option. This makes the documentation less cluttered, and gives you even more more inducement to document what isn't
  • JAVADOC_AUTOBRIEF: this allows to have both the brief comment anddetailed description in one block (despite it's name, it works for C++ sources, too)
    The first line of a comment block (up to the first period) is used as brief description.
  • WARN_FORMAT set to $file($line): $text - so you can double-click doxygen warning messages in the output window to jump to the relevant source line
  • INPUT : I added a single "." as INPUT directory, and checked the RECURSIVE option. this will scan the working directory (set to the workspace folder in the VC++ custom tool), and added a reasonable list of files to scan (.IDL files work very well, too!). You could specify exclude patterns, too (e.g. *_i.c and *_p.c for ATL projects to exclude some of the internal guts from documentation)
  • Source browser: I enabled the SOURCE_BROWSER option, so the sources are included and crosslinked (doxygen removes all doxygen-style comments, but leaves all other comments in).
  • I disabled the REFERENCED_BY_RELATION and REFERENCES_RELATION options. They can be valuable if you want to explore the interdependencies of complex code, but for the things I'm working on it's just clutter.
  • for the HTML_OUTPUT I set doxydoc as directory (it will be created under the working directory)
    Tip: When specifying dorectory names in doxygen config files -
    • if it contains spaces, put it into quotes (this is a good idea for other options as well)
    • do not end them with a backslash - doxygen uses it to spread argument lists over multiple lines
    • doxygen will try to create non-existing output directories, but cannot generate multiple levels.
  • GENERATE_TREEVIEW : While I left it disabled for the default, you shoud try it!

Documentation Markup:

Doxygen allows for simple markup tags in the comments (I used some in the sample documentation) they start with either a backslash, or an @. The most important I listed here:

/param name descripiton Intended for documenting function parameters. see the full sample source and documentation for how it looks like.
/return description desribe what a function returns
/b /c /e set the next word to bold, italic, or courier, respectively. e.g.
/// You can make things /b bold, /e italic, or set them in /c courier
results in
You can make things bold, italic, or set them in courier.
/code
/endcode
starts and ends a section of code, respectively. (it will be formatted nicely)
/n force a newline
/internal starts a paragraph with "internal information" (such as implementaiton details). The paragraph will be included only if the INTERNAL_DOCS option is enabled.
/mainpage Indictaes that the following section should appear on the main page. it's a good place to introduce your most important classes, etc. (entities will be crosslinked)
/par
/par Title
Starts a new paragraph (optionally with a paragraph title), works also inside other paragraphs (such as /param)
Lists Doxygen automatically creates a list if multiple lines start with a dash at the same position. Numbered lists can be created by starting the line with a dach and a hash (-#). See the doxygen documentation for more.
More...
(doxygen documentation)
Doxygen supports many more tags, many of them allowing for further markup, or are intended for working in conjucntion with the XML export. (e.g. you can makr the specificaiton of pre- and post-conditions, bugs, test cases, todo's, etc.)
HTML
(doxygen documentation)
Doxygen also supports HTML tags, which get converted to other outputs mroe or less correctly.

Additional Resources

Macros:

It's convenient to set up some auto-text bound to hotkeys for writing documentation. I just use some macros, and assign shortcuts to it manually: Setup is a bit of a hassle, but it's worth it:

  • copy doxygen.dsm into the [DevStudo]/Common/MSDev98/Macros folder
  • Start VC++, choose Tools/Customize...
  • on the "Add ins and macros" tab, enable the doxygen.dsm macro file
  • On the Keyboard tab, choose "Macros" under Category, and assign your preferred shortcuts to the commands

Here's a list of the macros I use:

Macro Name Description my shortcut
DoxyComment three slashes and a space (I use it rarely , but it's there) Ctrl-# (german keyboard..)
DoxyCommentNL newline + '/// ' - perfect for writing block comments (just press Ctrl-Enter instead of just Enter) Ctrl-Enter
DoxyCommentPrev '///< ' : for brief comments behind the declaration Ctrl-Shift-#
DoxyDocFunction a simple header to comment a function Ctrl-Shift-F

Style Sheets:

You can generate a default doxygen style sheet, HTML header and footer by calling

doxygen -w html <header_name> <footer_name> <stylesheet_name>

I did this for you already: doxygen_header.html, doxygen_footer.html, and doxygen_default.css.

The default style sheet is a good starting point for your own.

DoxyWizard:

In closing, just a little tip: Together with doxygen comes DoxyWizard, a UI tool to edit the configuration files. It's ok to use, the "quick help" gives a short explanaiton of each option. As I named all my config files .doxygen, I associated this extension with doxywizard, so life got much easier, and playing around with the options is much more fun.

Other Systems:

If you have experience with other documentation systems, feel free to (dis-)recommend them in the comments section - as long as you don't make it an advertisement, and stay within what's considered good taste on CP.

Enjoy! And document well.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


 

学习用 doxygen 生成源码文档


级别: 中级

Arpan Sen, 资深工程师, Studio B Productions

2008 年 10 月 13 日

维护用 C/C++ 开发的遗留系统并添加新特性是一项艰难的任务。幸运的是,doxygen 可以帮助您完成这个任务。doxygen 是一种用于 C/C++、Java™、Python 和其他编程语言的文档系统。本文在 C/C++ 项目的上下文中讨论 doxygen 的特性,以及如何用 doxygen 定义的标记生成代码文档。

维护用 C/C++ 开发的遗留系统并添加新特性是一项艰难的任务。这涉及几方面的问题:理解现有的类层次结构和全局变量,不同的用户定义类型,以及函数调用图分析等等。本文在 C/C++ 项目的上下文中通过示例讨论 doxygen 的几个特性。但是,doxygen 非常灵活,也可用于用 Python、Java、PHP 和其他语言开发的软件项目。本文的主要目的是帮助您从 C/C++ 源代码提取出信息,但也简要描述了如何用 doxygen 定义的标记生成代码文档。

安装 doxygen

有两种获得 doxygen 的方法。可以下载预编译的可执行文件,也可以从 SVN 存储库下载源代码并自己编译。清单 1 演示的是后一种方法。


清单 1. 安装和构建 doxygen 源代码
                
bash-2.05$ svn co https://doxygen.svn.sourceforge.net/svnroot/doxygen/trunk doxygen-svn

bash-2.05$ cd doxygen-svn
bash-2.05$ ./configure –prefix=/home/user1/bin
bash-2.05$ make

bash-2.05$ make install

注意,配置脚本把编译的源代码存储在 /home/user1/bin 中(进行编译后,会在 PATH 变量中添加这个目录),因为并非每个 UNIX® 用户都有写 /usr 文件夹的权限。另外,需要用 svn 实用程序下载源代码。





回页首


使用 doxygen 生成文档

使用 doxygen 生成源代码的文档需要执行三个步骤。

生成配置文件

在 shell 提示上,输入命令 doxygen -g 。这个命令在当前目录中生成一个可编辑的配置文件 Doxyfile。可以改变这个文件名,在这种情况下,应该调用 doxygen -g <user-specified file name>,见 清单 2


清单 2. 生成默认的配置文件
                
bash-2.05b$ doxygen -g
Configuration file 'Doxyfile' created.
Now edit the configuration file and enter
  doxygen Doxyfile
to generate the documentation for your project
bash-2.05b$ ls Doxyfile
Doxyfile

编辑配置文件

配置文件采用 <TAGNAME> = <VALUE> 这样的结构,与 Make 文件格式相似。下面是最重要的标记:

  • <OUTPUT_DIRECTORY>必须在这里提供一个目录名,例如 /home/user1/documentation,这个目录是放置生成的文档文件的位置。如果提供一个不存在的目录名,doxygen 会以这个名称创建具有适当用户权限的目录。
  • <INPUT>这个标记创建一个以空格分隔的所有目录的列表,这个列表包含需要生成文档的 C/C++ 源代码文件和头文件。例如,请考虑以下代码片段:
    INPUT = /home/user1/project/kernel /home/user1/project/memory
    

    在这里,doxygen 会从这两个目录读取 C/C++ 源代码。如果项目只有一个源代码根目录,其中有多个子目录,那么只需指定根目录并把 <RECURSIVE> 标记设置为 Yes

  • <FILE_PATTERNS>在默认情况下,doxygen 会搜索具有典型 C/C++ 扩展名的文件,比如 .c、.cc、.cpp、.h.hpp。如果 <FILE_PATTERNS> 标记没有相关联的值,doxygen 就会这样做。如果源代码文件采用不同的命名约定,就应该相应地更新这个标记。例如,如果项目使用 .c86 作为 C 文件扩展名,就应该在 <FILE_PATTERNS> 标记中添加这个扩展名。
  • <RECURSIVE>如果源代码层次结构是嵌套的,而且需要为所有层次上的 C/C++ 文件生成文档,就把这个标记设置为 Yes。例如,请考虑源代码根目录层次结构 /home/user1/project/kernel,其中有 /home/user1/project/kernel/vmm 和 /home/user1/project/kernel/asm 等子目录。如果这个标记设置为 Yes,doxygen 就会递归地搜索整个层次结构并提取信息。
  • <EXTRACT_ALL>这个标记告诉 doxygen,即使各个类或函数没有文档,也要提取信息。必须把这个标记设置为 Yes
  • <EXTRACT_PRIVATE>把这个标记设置为 Yes。否则,文档不包含类的私有数据成员。
  • <EXTRACT_STATIC>把这个标记设置为 Yes。否则,文档不包含文件的静态成员(函数和变量)。

清单 3 给出一个 Doxyfile 示例。


清单 3. 包含用户提供的标记值的 doxyfile 示例
                
OUTPUT_DIRECTORY = /home/user1/docs
EXTRACT_ALL = yes
EXTRACT_PRIVATE = yes
EXTRACT_STATIC = yes
INPUT = /home/user1/project/kernel
#Do not add anything here unless you need to. Doxygen already covers all 
#common formats like .c/.cc/.cxx/.c++/.cpp/.inl/.h/.hpp
FILE_PATTERNS = 
RECURSIVE = yes

运行 doxygen

在 shell 提示下输入 doxygen Doxyfile(或者已为配置文件选择的其他文件名)运行 doxygen。在最终生成 Hypertext Markup Language(HTML)和 Latex 格式(默认)的文档之前,doxygen 会显示几个消息。在生成文档期间,在 <OUTPUT_DIRECTORY> 标记指定的文件夹中,会创建两个子文件夹 htmllatex清单 4 是一个 doxygen 运行日志示例。


清单 4. doxygen 的日志输出
                
Searching for include files...
Searching for example files...
Searching for images...
Searching for dot files...
Searching for files to exclude
Reading input files...
Reading and parsing tag files
Preprocessing /home/user1/project/kernel/kernel.h
…
Read 12489207 bytes
Parsing input...
Parsing file /project/user1/project/kernel/epico.cxx
…
Freeing input...
Building group list...
..
Generating docs for compound MemoryManager::ProcessSpec
…
Generating docs for namespace std
Generating group index...
Generating example index...
Generating file member index...
Generating namespace member index...
Generating page index...
Generating graph info page...
Generating search index...
Generating style sheet...





回页首


文档输出格式

除了 HTML 之外,doxygen 还可以生成几种输出格式的文档。可以让 doxygen 生成以下格式的文档:

  • UNIX 手册页:<GENERATE_MAN> 标记设置为 Yes。在默认情况下,会在 <OUTPUT_DIRECTORY> 指定的目录中创建 man 子文件夹,生成的文档放在这个文件夹中。必须把这个文件夹添加到 MANPATH 环境变量中。
  • Rich Text Format(RTF):<GENERATE_RTF> 标记设置为 Yes。把 <RTF_OUTPUT> 标记设置为希望放置 .rtf 文件的目录;在默认情况下,文档放在 OUTPUT_DIRECTORY 中的 rtf 子文件夹中。要想支持跨文档浏览,应该把 <RTF_HYPERLINKS> 标记设置为 Yes。如果设置这个标记,生成的 .rtf 文件会包含跨文档链接。
  • Latex:在默认情况下,doxygen 生成 Latex 和 HTML 格式的文档。在默认的 Doxyfile 中,<GENERATE_LATEX> 标记设置为 Yes。另外,<LATEX_OUTPUT> 标记设置为 Latex,这意味着会在 OUTPUT_DIRECTORY 中创建 latex 子文件夹并在其中生成 Latex 文件。
  • Microsoft® Compiled HTML Help(CHM)格式:<GENERATE_HTMLHELP> 标记设置为 Yes。因为在 UNIX 平台上不支持这种格式,doxygen 只在保存 HTML 文件的文件夹中生成一个 index.hhp 文件。您必须通过 HTML 帮助编译器把这个文件转换为 .chm 文件。
  • Extensible Markup Language(XML)格式:<GENERATE_XML> 标记设置为 Yes。(注意,doxygen 开发团队还在开发 XML 输出)。

清单 5 提供的 Doxyfile 示例让 doxygen 生成所有格式的文档。


清单 5. 生成多种格式的文档的 Doxyfile
                
#for HTML 
GENERATE_HTML = YES
HTML_FILE_EXTENSION = .htm

#for CHM files
GENERATE_HTMLHELP = YES

#for Latex output
GENERATE_LATEX = YES
LATEX_OUTPUT = latex

#for RTF
GENERATE_RTF = YES
RTF_OUTPUT = rtf 
RTF_HYPERLINKS = YES

#for MAN pages
GENERATE_MAN = YES
MAN_OUTPUT = man
#for XML
GENERATE_XML = YES





回页首


doxygen 中的特殊标记

doxygen 包含几个特殊标记。

C/C++ 代码的预处理

为了提取信息,doxygen 必须对 C/C++ 代码进行预处理。但是,在默认情况下,它只进行部分预处理 —— 计算条件编译语句(#if…#endif),但是不执行宏展开。请考虑 清单 6 中的代码。


清单 6. 使用宏的 C++ 代码示例
                
#include <cstring>
#include <rope>

#define USE_ROPE

#ifdef USE_ROPE
  #define STRING std::rope
#else
  #define STRING std::string
#endif

static STRING name;

通过源代码中定义的 <USE_ROPE>,doxygen 生成的文档如下:

                Defines
    #define USE_ROPE
    #define STRING std::rope

Variables
    static STRING name

在这里可以看到 doxygen 执行了条件编译,但是没有对 STRING 执行宏展开。Doxyfile 中的 <ENABLE_PREPROCESSING> 标记在默认情况下设置为 Yes。为了执行宏展开,还应该把 <MACRO_EXPANSION> 标记设置为 Yes。这会使 doxygen 产生以下输出:

                Defines
   #define USE_ROPE
    #define STRING std::string

Variables
    static std::rope name

如果把 <ENABLE_PREPROCESSING> 标记设置为 No,前面源代码的 doxygen 输出就是:

                Variables
    static STRING name

注意,文档现在没有定义,而且不可能推导出 STRING 的类型。因此,总是应该把 <ENABLE_PREPROCESSING> 标记设置为 Yes

在文档中,可能希望只展开特定的宏。为此,除了把 <ENABLE_PREPROCESSING><MACRO_EXPANSION> 标记设置为 Yes 之外,还必须把 <EXPAND_ONLY_PREDEF> 标记设置为 Yes(这个标记在默认情况下设置为 No),并在 <PREDEFINED><EXPAND_AS_DEFINED> 标记中提供宏的细节。请考虑 清单 7 中的代码,这里只希望展开宏 CONTAINER


清单 7. 包含多个宏的 C++ 源代码
                
#ifdef USE_ROPE
  #define STRING std::rope
#else
  #define STRING std::string
#endif

#if ALLOW_RANDOM_ACCESS == 1
  #define CONTAINER std::vector
#else
  #define CONTAINER std::list
#endif

static STRING name;
static CONTAINER gList;

清单 8 给出配置文件。


清单 8. 允许有选择地展开宏的 Doxyfile
                
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED = CONTAINER
…

下面的 doxygen 输出只展开了 CONTAINER

                Defines
#define STRING   std::string 
#define CONTAINER   std::list

Variables
static STRING name
static std::list gList

注意,只有 CONTAINER 宏被展开了。在 <MACRO_EXPANSION><EXPAND_ONLY_PREDEF> 都设置为 Yes 的情况下,<EXPAND_AS_DEFINED> 标记只选择展开等号操作符右边列出的宏。

对于预处理过程,要注意的最后一个标记是 <PREDEFINED>。就像用 -D 开关向 C++ 编译器传递预处理器定义一样,使用这个标记定义宏。请考虑 清单 9 中的 Doxyfile。


清单 9. 定义了宏展开标记的 Doxyfile
                
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED = 
PREDEFINED = USE_ROPE= /
                             ALLOW_RANDOM_ACCESS=1

下面是 doxygen 生成的输出:

                Defines
#define USE_CROPE 
#define STRING   std::rope 
#define CONTAINER   std::vector

Variables
static std::rope name 
static std::vector gList

在使用 <PREDEFINED> 标记时,宏应该定义为 <macro name>=<value> 形式。如果不提供值,比如简单的 #define,那么只使用 <macro name>=<spaces> 即可。多个宏定义以空格或反斜杠(/)分隔。

从文档生成过程中排除特定文件或目录

在 Doxyfile 中的 <EXCLUDE> 标记中,添加不应该为其生成文档的文件或目录(以空格分隔)。因此,如果提供了源代码层次结构的根,并要跳过某些子目录,这将非常有用。例如,如果层次结构的根是 src_root,希望在文档生成过程中跳过 examples/ 和 test/memoryleaks 文件夹,Doxyfile 应该像 清单 10 这样。


清单 10. 使用 EXCLUDE 标记的 Doxyfile
                
INPUT = /home/user1/src_root
EXCLUDE = /home/user1/src_root/examples /home/user1/src_root/test/memoryleaks
…





回页首


生成图形和图表

在默认情况下,Doxyfile 把 <CLASS_DIAGRAMS> 标记设置为 Yes。这个标记用来生成类层次结构图。要想生成更好的视图,可以从 Graphviz 下载站点 下载 dot 工具。Doxyfile 中的以下标记用来生成图表:

  • <CLASS_DIAGRAMS>在 Doxyfile 中这个标记默认设置为 Yes。如果这个标记设置为 No,就不生成继承层次结构图。
  • <HAVE_DOT>如果这个标记设置为 Yes,doxygen 就使用 dot 工具生成更强大的图形,比如帮助理解类成员及其数据结构的协作图。注意,如果这个标记设置为 Yes<CLASS_DIAGRAMS> 标记就无效了。
  • <CLASS_GRAPH>如果 <HAVE_DOT> 标记和这个标记同时设置为 Yes,就使用 dot 生成继承层次结构图,而且其外观比只使用 <CLASS_DIAGRAMS> 时更丰富。
  • <COLLABORATION_GRAPH>如果 <HAVE_DOT> 标记和这个标记同时设置为 Yes,doxygen 会生成协作图(还有继承图),显示各个类成员(即包含)及其继承层次结构。

清单 11 提供一个使用一些数据结构的示例。注意,在配置文件中 <HAVE_DOT><CLASS_GRAPH><COLLABORATION_GRAPH> 标记都设置为 Yes


清单 11. C++ 类和结构示例
                
struct D {
  int d;
};

class A {
  int a;
};

class B : public A {
  int b;
};

class C : public B {
  int c;
  D d;
};

图 1 给出 doxygen 的输出。


图 1. 使用 dot 工具生成的类继承图和协作图
类继承图




回页首


代码文档样式

到目前为止,我们都是使用 doxygen 从原本没有文档的代码中提取信息。但是,doxygen 也鼓励使用文档样式和语法,这有助于生成更详细的文档。本节讨论 doxygen 鼓励在 C/C++ 代码中使用的一些常用标记。更多信息参见 参考资料

每个代码元素有两种描述:简短的和详细的。简短描述通常是单行的。函数和类方法还有第三种描述体内描述(in-body description),这种描述把在函数体中找到的所有注释块集中在一起。比较常用的一些 doxygen 标记和注释样式如下:

  • 简短描述:使用单行的 C++ 注释,或使用 </brief> 标记。
  • 详细描述:使用 JavaDoc 式的注释 /** … test … */(注意开头的两个星号 [*])或 Qt 式的注释 /*! … text … */
  • 体内描述:类、结构、联合体和名称空间等 C++ 元素都有自己的标记,比如 </class></struct></union></namespace>

为了为全局函数、变量和枚举类型生成文档,必须先对对应的文件使用 </file> 标记。清单 12 给出的示例包含用于四种元素的标记:函数标记(</fn>)、函数参数标记(</param>)、变量名标记(</var>)、用于 #define 的标记(</def>)以及用来表示与一个代码片段相关的问题的标记(</warning>)。


清单 12. 典型的 doxygen 标记及其使用方法
                
/*! /file globaldecls.h
      /brief Place to look for global variables, enums, functions
           and macro definitions
  */

/** /var const int fileSize
      /brief Default size of the file on disk
  */
const int fileSize = 1048576;

/** /def SHIFT(value, length)
      /brief Left shift value by length in bits
  */
#define SHIFT(value, length) ((value) << (length))

/** /fn bool check_for_io_errors(FILE* fp)
      /brief Checks if a file is corrupted or not
      /param fp Pointer to an already opened file
      /warning Not thread safe!
  */
bool check_for_io_errors(FILE* fp);

下面是生成的文档:

                Defines
#define SHIFT(value, length)   ((value) << (length))  
             Left shift value by length in bits.

Functions
bool check_for_io_errors (FILE *fp)  
        Checks if a file is corrupted or not.

Variables
const int fileSize = 1048576;
Function Documentation
bool check_for_io_errors (FILE* fp)
Checks if a file is corrupted or not.

Parameters
              fp: Pointer to an already opened file

Warning
Not thread safe! 





回页首


结束语

本文讨论如何用 doxygen 从遗留的 C/C++ 代码提取出大量相关信息。如果用 doxygen 标记生成代码文档,doxygen 会以容易阅读的格式生成输出。只要以适当的方式使用,doxygen 就可以帮助任何开发人员维护和管理遗留系统。



参考资料

学习
  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

  • doxygen 站点 包含关于 doxygen 的非常有价值的手册和几篇文章。

  • 下载 dot 实用程序

  • AIX and UNIX 专区:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。

  • AIX and UNIX 新手入门:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。

  • AIX and UNIX 专题汇总:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。

  • developerWorks 技术活动和网络广播:随时关注 developerWorks 技术活动和网络广播。

  • Podcasts:收听 IBM 技术专家的访谈录。

     

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 程序文档生成器介绍(doxygen) 的相关文章

  • OpenCv读/写视频色差

    我试图简单地使用 openCV 打开视频 处理帧并将处理后的帧写入新的视频文件 我的问题是 即使我根本不处理帧 只是打开视频 使用 VideoCapture 读取帧并使用 VideoWriter 将它们写入新文件 输出文件看起来比输入更 绿
  • asp.net 文本框文本模式数字,仅允许数字

    我只是想知道 ASP NET 中是否有一种方法只允许文本框中的数字textmode number 当我使用这个时
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 获取给定类文件的目录路径

    我遇到的代码尝试从类本身的 class 文件所在的同一目录中读取一些配置文件 File configFiles new File this getClass getResource getPath listFiles new Filenam
  • 向 ExpandoObject 添加方法时,“关键字 'this' 在静态属性、静态方法或静态字段初始值设定项中无效”

    我尝试向 ExpandoObject 添加一个动态方法 该方法将返回属性 动态添加 给它 但它总是给我错误 我在这里做错了什么吗 using System using System Collections Generic using Sys
  • 为什么要序列化对象需要 Serialized 属性

    根据我的理解 SerializedAttribute 不提供编译时检查 因为它都是在运行时完成的 如果是这样 那么为什么需要将类标记为可序列化呢 难道序列化器不能尝试序列化一个对象然后失败吗 这不就是它现在所做的吗 当某些东西被标记时 它会
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • 访问者和模板化虚拟方法

    在一个典型的实现中Visitor模式 该类必须考虑基类的所有变体 后代 在许多情况下 访问者中的相同方法内容应用于不同的方法 在这种情况下 模板化的虚拟方法是理想的选择 但目前这是不允许的 那么 模板化方法可以用来解析父类的虚方法吗 鉴于
  • IronPython:没有名为 json 的模块

    我安装了 IronPython 我的 python 文件如下所示 import sys print sys version import json 运行它的代码 var p Python CreateEngine var scope p C
  • 当前的 c++ 工作草案与当前标准有何不同

    通过搜索该标准的 PDF 版本 我最终找到了这个链接C 标准措辞草案 http www open std org jtc1 sc22 wg21 docs papers 2012 n3376 pdf从 2011 年开始 我意识到我可以购买最终
  • 如何从网站下载 .EXE 文件?

    我正在编写一个应用程序 需要从网站下载 exe 文件 我正在使用 Visual Studio Express 2008 我正在使用以下代码 private void button1 Click object sender EventArgs
  • 将数据打印到文件

    我已经超载了 lt lt 运算符 使其写入文件并写入控制台 我已经为同一个函数创建了 8 个线程 并且我想输出 hello hi 如果我在无限循环中运行这个线程例程 文件中的o p是 hello hi hello hi hello hi e
  • 基于xsd模式生成xml(使用.NET)

    我想根据我的 xsd 架构 cap xsd 生成 xml 文件 我找到了这篇文章并按照说明进行操作 使用 XSD 文件生成 XML 文件 https stackoverflow com questions 6530424 generatin
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 为什么我不应该对不是由 malloc() 分配的变量调用 free() ?

    我在某处读到 使用它是灾难性的free删除不是通过调用创建的对象malloc 这是真的 为什么 这是未定义的行为 永远不要尝试它 让我们看看当您尝试时会发生什么free 自动变量 堆管理器必须推断出如何获取内存块的所有权 为此 它要么必须使
  • 通过 NHibernate 进行查询,无需 N+1 - 包含示例

    我有一个 N 1 问题 我不知道如何解决它 可以在这个问题的底部找到完全可重复的样本 因此 如果您愿意 请创建数据库 设置 NUnit 测试和所有附带的类 并尝试在本地消除 N 1 这是我遇到的真实问题的匿名版本 众所周知 这段代码对于帮助
  • 将构建日期放入“关于”框中

    我有一个带有 关于 框的 C WinForms 应用程序 我使用以下方法将版本号放入 关于 框中 FileVersionInfo GetVersionInfo Assembly GetExecutingAssembly Location F
  • 当我“绘制”线条时,如何将点平均分配到 LineRenderer 的宽度曲线?

    我正在使用线条渲染器创建一个 绘图 应用程序 现在我尝试使用线条渲染器上的宽度曲线启用笔压 问题在于 AnimationCurve 的 时间 值 水平轴 从 0 标准化为 1 因此我不能在每次添加位置时都在其末尾添加一个值 除非有一个我不知
  • 将代码拆分为标头/源文件

    我从 Asio 的示例页面中获取了以下代码 class tcp connection public boost enable shared from this
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • 判断回文串C++

    题目描述 输入一串字符 字符个数不超过1000 判断它们是否构成回文 所谓回文字符串 就是一个字符串 从左到右读和从右到左读是完全一样的 比如 level aaabbaaa 输入 输入只有一行 包括一串字符 输出 输出只有一行TRUE或者F
  • 从mysql数据库中读取二进制文件_ASP中从数据库读取二进制文件数据代码

    driver name1 DRIVER Microsoft Access Driver mdb DBQ D 数据库 TREE MDB 根目录下数据库打开语句 dim search rs j search select from Files
  • 关于图像处理技术检测火焰的一些建议(仅个人观点)

    1 火焰检测是图像识别的一个细类 某种意义上图像识别的技术都可以用于火焰检测 因此如帧间差分法 RGB方法等都可直接搜相应方法获得源码 直接用于火焰检测 微调参数即可 当然这种检测结果是不佳的 2 火焰检测需要认清到底是要检测动态火焰还是静
  • Vue3打印功能

    目录 安装 vue3 print nb main js中引入 vue3 print nb 页面内引入 声明打印时的配置的变量 选择要打印的模板区域 配置对应的id包裹 配置完成了看效果 点击打印出现打印模态框 安装 vue3 print n
  • 002_Kubernetes安装配置

    文章目录 1 k8s环境平台规划 1 1 单master集群 1 2 多master集群 2 配置要求 3 Kubernetes集群主要有两种方式 3 1 kubeadm 3 2 二进制包 4 kubeadm kubectl kubelet
  • JS手写实现发布订阅设计模式

    大部分前端应该对设计模式了解都不多 但是对Vue理解深刻的同学一定都知道发布订阅模式 因为Vue2的响应式就是基于Object defineProperty 发布订阅模式实现的 今天我们就用JS简单实现一下发布订阅模式 观察者 watche
  • LeetCode刷题日记2021-12-7/1034. 边界着色-DFS深度优先搜素

    1034 边界着色 DFS深度优先搜素 题目描述 题解思路 题解代码 题目描述 给你一个大小为 m x n 的整数矩阵 grid 表示一个网格 另给你三个整数 row col 和 color 网格中的每个值表示该位置处的网格块的颜色 当两个
  • 详解Hugging Face Transformers的TrainingArguments

    前言 TrainingArguments是Hugging Face Transformers库中用于训练模型时需要用到的一组参数 用于控制训练的流程和效果 使用示例 from transformers import Trainer Trai
  • 神武3进不去 服务器响应,windows7系统玩神武2卡机的解决方法

    神武2是一款备受玩家们喜欢的游戏之一 不过有部分windows7系统用户在玩神武2游戏的时候 发现遇到了卡机的情况 一卡一卡非常不流畅 影响了正常游戏 要如何解决呢 本教程就给大家带来windows7系统玩神武2卡机的解决方法 1 可能导致
  • ZCA白化的步骤

    ZCA白化的主要用于去相关性 尽量使白化后的数据接近原始输入数据 对于含有m个样本的数据集 x 1 x 2 x m 假设每个样本的维度为n 即x i R n 对其进行ZCA白化的具体步骤如下 1 计算数据集的协方差矩阵 计算公式如下 1 m
  • Java 程序如何正确地打印日志?

    在 Java 开发中 打印日志是一项非常重要的工作 正确的打印日志可以帮助我们快速定位问题 并提高代码的可维护性和可读性 本文将为大家介绍 Java 程序如何正确地打日志 希望对大家有所帮助 一 为什么需要打印日志 在开发过程中 我们经常需
  • 仓库运行状况如何得知?数据挖掘是关键!

    库存 订单 出入库记录 物流信息 货物状态等数据 是仓库管理的重要组成部分 仓库数据的重要性 做好仓库数据管理对企业的重要性不言而喻 通过有效地管理数据 企业可以更好地了解市场需求和库存情况 快速响应市场变化 提高库存周转率和客户满意度 此
  • 阿里云centos7.9安装docker,创建nginx容器,启动vue3项目

    1 安装必要的依赖包 sudo yum install y yum utils device mapper persistent data lvm2 2 添加Docker存储库 sudo yum config manager add rep
  • 实现快速排序(数据结构与算法 - 排序)

    通过补全快速排序私有函数QSort 来供函数QuickSort调用 以此来实现快速排序的功能 相关知识 快速排序的基本过程是 从待排序记录中任选一个记录 以它的排序码作为中心值 将其它记录划分为两个部分 第一部分包含所有排序码小于等于中心值
  • 【TensorFlow】tf.reset_default_graph()函数

    如下是官网对tf reset default graph 函数描述的翻译 tf reset default graph函数用于清除默认图形堆栈并重置全局默认图形 注意 默认图形是当前线程的一个属性 该tf reset default gra
  • postman的参数是图片和文件如何设置,及操作提示this file is not in your working directory

    1 图片或者文件 作为参数的设置 在参数这里 选择文件 选择需要作为参数的文件 2 提示this file is not in your working directory 提示这个文件不在你的工作路劲下 设置一下当前的工作路径即可
  • 用sql语句对数据库表中的数据进行增删改

    如何使用sql语句对mysql数据库中表的数据进行增删改 这里新创了一个school数据库 在下面创建一张名为student表 创建student表的sql语句代码如下 使用school数据库 use school 判断是否存在studen
  • 手把手教你用 NebulaGraph AI 全家桶跑图算法

    前段时间 NebulaGraph 3 5 0 发布 whitewum 吴老师建议我把前段时间 NebulaGraph 社区里开启的新项目 ng ai 公开给大家 所以 就有了这个系列文章 本文是该系列的开篇之作 ng ai 是什么 ng a
  • Java中Scanner类中next与nextLine的区别

    1 next的意思是接受文字 有效文字 next不接收空格回车以及Tab 当你输入空格回车Tab的时候接收就会终止 并不会存入到String 变量中去 特别的情况 当在输入的时候先输入了几个空格然后再输入String中内容得时候String
  • C++ 程序文档生成器介绍(doxygen)

    http ly4cn cnblogs com archive 2005 11 23 282637 html 程序文档 曾经是程序员的一个头痛问题 写一个程序文档 比较花时间 但不是很难 麻烦的是当程序修改后 程序文档也要跟着同步更新 否则文