D 编程 - 快速指南


D 编程 - 概述

D 编程语言是由 Digital Mars 的 Walter Bright 开发的一种面向对象的多范式系统编程语言。它的开发始于1999年,并于2001年首次发布。D(1.0)的主要版本于2007年发布。目前,我们有D2版本。

D 是语法为 C 风格的语言,并使用静态类型。D 中有许多 C 和 C++ 的功能,但也有一些这些语言的功能未包含在 D 中。D 的一些值得注意的新增内容包括:

  • 单元测试
  • 真正的模块
  • 垃圾收集
  • 第一类数组
  • 免费开放
  • 关联数组
  • 动态数组
  • 内部类
  • 闭包
  • 匿名函数
  • 惰性评估
  • 闭包

多种范式

D 是一种多范式编程语言。多种范式包括,

  • 至关重要的
  • 面向对象
  • 元编程
  • 功能性
  • 同时

例子

import std.stdio; 
 
void main(string[] args) { 
   writeln("Hello World!"); 
}

学习D

学习 D 时最重要的事情是关注概念,不要迷失在语言技术细节中。

学习编程语言的目的是成为一名更好的程序员;也就是说,在设计和实施新系统以及维护旧系统方面变得更加有效。

D 的范围

D 编程有一些有趣的功能,官方 D 编程网站声称 D 方便、强大且高效。D 编程在核心语言中添加了 C 语言以标准库形式提供的许多功能,例如可调整大小的数组和字符串函数。D 是中级到高级程序员的优秀第二语言。D 在处理内存和管理指针方面做得更好,而这在 C++ 中经常引起问题。

D 编程主要针对现有程序转换的新程序。它为大型团队将使用数百万行代码编写的大型新项目提供了内置测试和验证的理想选择。

D 编程 - 环境

D 的本地环境设置

如果您仍然愿意为 D 编程语言设置环境,您的计算机上需要有以下两个软件:(a) 文本编辑器,(b)D 编译器。

D 编程的文本编辑器

这将用于输入您的程序。少数编辑器的示例包括 Windows 记事本、操作系统编辑命令、Brief、Epsilon、EMACS 和 vim 或 vi。

文本编辑器的名称和版本可能因不同操作系统而异。例如,记事本将在 Windows 上使用,vim 或 vi 可以在 Windows 上使用,也可以在 Linux 或 UNIX 上使用。

您使用编辑器创建的文件称为源文件,包含程序源代码。D 程序的源文件以扩展名“ .d ”命名。

在开始编程之前,请确保您有一个文本编辑器,并且您有足够的经验来编写计算机程序、将其保存在文件中、构建它并最终执行它。

D 编译器

大多数当前的 D 实现都直接编译成机器代码以实现高效执行。

我们有多个可用的 D 编译器,其中包括以下内容。

  • DMD - Digital Mars D 编译器是 Walter Bright 的官方 D 编译器。

  • GDC - GCC 后端的前端,使用开放的 DMD 编译器源代码构建。

  • LDC - 基于 DMD 前端的编译器,使用 LLVM 作为其编译器后端。

以上不同编译器可以到D downloads下载

我们将使用 D 版本 2,建议不要下载 D1。

让我们有一个 helloWorld.d 程序,如下所示。我们将使用它作为我们在您选择的平台上运行的第一个程序。

import std.stdio; 
 
void main(string[] args) { 
   writeln("Hello World!"); 
}

我们可以看到以下输出。

$ hello world

在 Windows 上安装 D

下载 Windows安装程序

运行下载的可执行文件来安装 D,可以按照屏幕上的说明进行操作。

现在我们可以构建并运行广告文件 helloWorld.d,方法是使用 cd 切换到包含该文件的文件夹,然后使用以下步骤 -

C:\DProgramming> DMD helloWorld.d 
C:\DProgramming> helloWorld

我们可以看到以下输出。

hello world

C:\DProgramming 是我用来保存示例的文件夹。您可以将其更改为您保存D程序的文件夹。

在 Ubuntu/Debian 上安装 D

下载 Debian安装程序

运行下载的可执行文件来安装 D,可以按照屏幕上的说明进行操作。

现在我们可以构建并运行广告文件 helloWorld.d,方法是使用 cd 切换到包含该文件的文件夹,然后使用以下步骤 -

$ dmd helloWorld.d 
$ ./helloWorld

我们可以看到以下输出。

$ hello world 

在 Mac OS X 上安装 D

下载 Mac安装程序

运行下载的可执行文件来安装 D,可以按照屏幕上的说明进行操作。

现在我们可以构建并运行广告文件 helloWorld.d,方法是使用 cd 切换到包含该文件的文件夹,然后使用以下步骤 -

$ dmd helloWorld.d 
$ ./helloWorld

我们可以看到以下输出。

$ hello world

在 Fedora 上安装 D

下载 Fedora安装程序

运行下载的可执行文件来安装 D,可以按照屏幕上的说明进行操作。

现在我们可以构建并运行广告文件 helloWorld.d,方法是使用 cd 切换到包含该文件的文件夹,然后使用以下步骤 -

$ dmd helloWorld.d 
$ ./helloWorld

我们可以看到以下输出。

$ hello world

在 OpenSUSE 上安装 D

下载 OpenSUSE安装程序

运行下载的可执行文件来安装 D,可以按照屏幕上的说明进行操作。

现在我们可以构建并运行广告文件 helloWorld.d,方法是使用 cd 切换到包含该文件的文件夹,然后使用以下步骤 -

$ dmd helloWorld.d 
$ ./helloWorld

我们可以看到以下输出。

$ hello world

集成开发环境

在大多数情况下,我们以插件的形式提供对 D 的 IDE 支持。这包括,

  • Visual D插件是Visual Studio 2005-13的插件

  • DDT是一个 eclipse 插件,提供代码补全、使用 GDB 进行调试。

  • Mono-D代码完成,通过 dmd/ldc/gdc 支持进行重构。它已成为 GSoC 2012 的一部分。

  • Code Blocks是一个多平台 IDE,支持 D 项目创建、突出显示和调试。

D 编程 - 基本语法

D 学习起来非常简单,让我们开始创建我们的第一个 D 程序吧!

第一个D计划

让我们编写一个简单的 D 程序。所有 D 文件的扩展名为 .d。因此,将以下源代码放入 test.d 文件中。

import std.stdio;  

/* My first program in D */ 
void main(string[] args) { 
   writeln("test!"); 
}

假设 D 环境设置正确,让我们使用以下命令运行编程:

$ dmd test.d 
$ ./test

我们可以看到以下输出。

test

现在让我们看看D程序的基本结构,以便您轻松理解D编程语言的基本构件。

导入D

库是可重用程序部分的集合,可以在导入的帮助下供我们的项目使用。这里我们导入标准io库,它提供了基本的I/O操作。上面程序中使用的writeln是D标准库中的函数。它用于打印一行文本。D 中的库内容根据要执行的任务类型分为模块。该程序使用的唯一模块是 std.stdio,它处理数据输入和输出。

主功能

Main函数是程序的开始,它决定了执行的顺序以及程序的其他部分应该如何执行。

D 中的代币

AD 程序由各种标记组成,标记可以是关键字、标识符、常量、字符串文字或符号。例如,以下 D 语句由四个标记组成 -

writeln("test!");

各个令牌是 -

writeln (
   "test!"
)
;

评论

注释就像 D 程序中的支持文本一样,它们会被编译器忽略。多行注释以 /* 开头,以字符 */ 结尾,如下所示 -

/* My first program in D */ 

单个注释是在注释的开头使用 // 编写的。

// my first program in D

身份标识

AD 标识符是用于标识变量、函数或任何其他用户定义项的名称。标识符以字母 A 到 Z 或 a 到 z 或下划线 _ 开头,后跟零个或多个字母、下划线和数字(0 到 9)。

D 不允许在标识符中使用标点字符,例如 @、$ 和 %。D 是区分大小写的编程语言。因此,Manpowermanpower是 D 中两个不同的标识符。以下是可接受的标识符的一些示例 -

mohd       zara    abc   move_name  a_123 
myname50   _temp   j     a23b9      retVal

关键词

下面的列表显示了 D 中的一些保留字。这些保留字不能用作常量或变量或任何其他标识符名称。

抽象的 别名 对齐 汇编
断言 汽车 身体 布尔值
字节 案件 投掷 抓住
字符 班级 常量 继续
字符 调试 默认 代表
已弃用 双倍的 别的
枚举 出口 外部的 错误的
最终的 最后 漂浮 为了
foreach 功能 如果
进口 进出 整数
界面 不变的 长的
混合 模块 新的
无效的 出去 覆盖 包裹
杂注 私人的 受保护的 民众
真实的 参考 返回 范围
短的 静止的 结构体 极好的
转变 同步的 模板
真的 尝试 类型ID
类型 优字节 单位 乌龙
联盟 单元测试 超短 版本
空白 字符型 尽管

D 中的空白

仅包含空格(可能带有注释)的行称为空行,D 编译器完全忽略它。

空白是 D 中用来描述空白、制表符、换行符和注释的术语。空格将语句的一部分与另一部分分隔开,并使解释器能够识别语句中一个元素(例如 int)的结束位置和下一个元素的开始位置。因此,在以下声明中 -

local age

local 和 Age 之间必须至少有一个空白字符(通常是空格),以便解释器能够区分它们。另一方面,在下面的声明中

int fruit = apples + oranges   //get the total fruits

水果和 = 之间或 = 和苹果之间不需要空格字符,但如果您希望出于可读性目的,可以自由地包含一些空格字符。

D 编程 - 变量

变量只不过是我们的程序可以操作的存储区域的名称。D中的每个变量都有一个特定的类型,它决定了变量内存的大小和布局;该内存中可以存储的值的范围;以及可以应用于变量的操作集。

变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大小写字母不同,因为 D 区分大小写。基于上一章中解释的基本类型,将有以下基本变量类型 -

先生。 类型和描述
1

字符

通常是一个八位位组(一个字节)。这是一个整数类型。

2

整数

机器最自然的整数大小。

3

漂浮

单精度浮点值。

4

双倍的

双精度浮点值。

5

空白

代表没有类型。

D 编程语言还允许定义各种其他类型的变量,例如枚举、指针、数组、结构体、联合等,我们将在后续章节中介绍。在本章中,我们只研究基本变量类型。

D 中的变量定义

变量定义告诉编译器在何处以及为变量创建多少空间。变量定义指定一种数据类型并包含该类型的一个或多个变量的列表,如下所示 -

type variable_list;

这里,type必须是有效的 D 数据类型,包括 char、wchar、int、float、double、bool 或任何用户定义的对象等,variable_list可以由一个或多个以逗号分隔的标识符名称组成。这里显示了一些有效的声明 -

int    i, j, k; 
char   c, ch; 
float  f, salary; 
double d;

该行int i, j, k; 两者都声明并定义了变量 i、j 和 k;它指示编译器创建名为 i、j 和 k 的 int 类型变量。

变量可以在其声明中初始化(分配初始值)。初始化器由一个等号后跟一个常量表达式组成,如下所示 -

type variable_name = value;

例子

extern int d = 3, f = 5;    // declaration of d and f.  
int d = 3, f = 5;           // definition and initializing d and f.  
byte z = 22;                // definition and initializes z.  
char x = 'x';               // the variable x has the value 'x'.

当在 D 中声明变量时,它始终被设置为其“默认初始化程序”,可以通过T.init手动访问,其中T是类型(例如int.init)。整数类型的默认初始值设定项为 0,布尔值的默认初始值设定项为 false,浮点数的默认初始值设定项为 NaN。

D 中的变量声明

变量声明向编译器保证存在一个具有给定类型和名称的变量,以便编译器继续进行进一步编译,而无需有关该变量的完整详细信息。变量声明仅在编译时才有意义,编译器在程序链接时需要实际的变量声明。

例子

尝试以下示例,其中变量已在程序开始时声明,但在主函数内定义和初始化 -

import std.stdio; 
 
int a = 10, b = 10; 
int c;
float f;  

int main () { 
   writeln("Value of a is : ", a); 
   
   /* variable re definition: */ 
   int a, b; 
   int c; 
   float f;
   
   /* Initialization */ 
   a = 30; 
   b = 40; 
   writeln("Value of a is : ", a); 
   
   c = a + b; 
   writeln("Value of c is : ", c);  
   
   f = 70.0/3.0; 
   writeln("Value of f is : ", f); 
   return 0; 
}

当上面的代码被编译并执行时,它会产生以下结果 -

Value of a is : 10 
Value of a is : 30 
Value of c is : 70 
Value of f is : 23.3333

D 中的左值和右值

D 中有两种表达式 -

  • 左值- 作为左值的表达式可以显示为赋值的左侧或右侧。

  • 右值- 作为右值的表达式可以出现在赋值的右侧,但不能出现在左侧。

变量是左值,因此可能出现在赋值的左侧。数字文字是右值,因此不能被赋值,也不能出现在左侧。以下声明是有效的 -

int g = 20;

但以下不是有效的语句,会生成编译时错误 -

10 = 20;

D 编程 - 数据类型

在 D 编程语言中,数据类型是指用于声明不同类型的变量或函数的广泛系统。变量的类型决定了它在存储中占据多少空间以及如何解释存储的位模式。

D 中的类型可以分类如下 -

先生。 类型和描述
1

基本类型

它们是算术类型,由三种类型组成:(a) 整数、(b) 浮点数和 (c) 字符。

2

枚举类型

它们又是算术类型。它们用于定义在整个程序中只能分配某些离散整数值的变量。

3

类型无效

类型说明符void表示没有可用值。

4

派生类型

它们包括 (a) 指针类型、(b) 数组类型、(c) 结构类型、(d) 联合类型和 (e) 函数类型。

数组类型和结构类型统称为聚合类型。函数的类型指定函数的返回值的类型。我们将在下一节中看到基本类型,而其他类型将在接下来的章节中介绍。

整数类型

下表列出了标准整数类型及其存储大小和值范围 -

类型 存储大小 取值范围
布尔值 1字节 假或真
字节 1字节 -128 至 127
优字节 1字节 0 至 255
整数 4字节 -2,147,483,648 至 2,147,483,647
单位 4字节 0 至 4,294,967,295
短的 2字节 -32,768 至 32,767
超短 2字节 0 至 65,535
长的 8字节 -9223372036854775808 至 9223372036854775807
乌龙 8字节 0 至 18446744073709551615

要获取类型或变量的确切大小,可以使用sizeof运算符。表达式type.(sizeof)生成对象或类型的存储大小(以字节为单位)。以下示例获取任何机器上 int 类型的大小 -

import std.stdio; 
 
int main() { 
   writeln("Length in bytes: ", ulong.sizeof); 

   return 0; 
}

当您编译并执行上述程序时,它会产生以下结果 -

Length in bytes: 8 

浮点类型

下表提到了标准浮点类型的存储大小、值范围及其用途 -

类型 存储大小 取值范围 目的
漂浮 4字节 1.17549e-38 至 3.40282e+38 小数点后 6 位
双倍的 8字节 2.22507e-308 至 1.79769e+308 小数点后 15 位
真实的 10字节 3.3621e-4932 至 1.18973e+4932 硬件支持的最大浮点类型,或 double;以较大者为准
浮动 4字节 1.17549e-38i 至 3.40282e+38i float 的虚值类型
双重 8字节 2.22507e-308i 至 1.79769e+308i double 的虚值类型
我真的 10字节 3.3621e-4932 至 1.18973e+4932 实数的虚值类型
浮点型 8字节 1.17549e-38+1.17549e-38i 至 3.40282e+38+3.40282e+38i 由两个浮点数组成的复数类型
双倍 16字节 2.22507e-308+2.22507e-308i 至 1.79769e+308+1.79769e+308i 由两个双精度数组成的复数类型
创造的 20字节 3.3621e-4932+3.3621e-4932i 至 1.18973e+4932+1.18973e+4932i 由两个实数组成的复数类型

以下示例打印浮点类型及其范围值占用的存储空间 -

import std.stdio;

int main() { 
   writeln("Length in bytes: ", float.sizeof); 

   return 0; 
}

当您编译并执行上述程序时,它会在 Linux 上产生以下结果 -

Length in bytes: 4

字符类型

下表列出了标准字符类型及其存储大小及其用途。

类型 存储大小 目的
字符 1字节 UTF-8 编码单元
字符型 2字节 UTF-16 编码单元
字符 4字节 UTF-32 代码单元和 Unicode 代码点

以下示例打印 char 类型占用的存储空间。

import std.stdio;

int main() {
   writeln("Length in bytes: ", char.sizeof);
   
   return 0;
}

当您编译并执行上述程序时,它会产生以下结果 -

Length in bytes: 1

虚空类型

void 类型指定没有可用值。它用于两种情况 -

先生。 类型和描述
1

函数返回 void

D 中有多种不返回值的函数,或者您可以说它们返回 void。无返回值的函数的返回类型为 void。例如,void exit(int status);

2

函数参数为 void

D 中有多种不接受任何参数的函数。没有参数的函数可以接受 void。例如,int rand(void);

此时您可能不理解 void 类型,所以让我们继续,我们将在接下来的章节中介绍这些概念。

D 编程 - 枚举

枚举用于定义命名常量值。枚举类型是使用enum关键字声明的。

枚举语法_

枚举定义的最简单形式如下 -

enum enum_name {  
   enumeration list 
}

在哪里,

  • enum_name指定枚举类型名称

  • 枚举列表是以逗号分隔的标识符列表。

枚举列表中的每个符号都代表一个整数值,该值比其前面的符号大 1。默认情况下,第一个枚举符号的值为 0。例如 -

enum Days { sun, mon, tue, wed, thu, fri, sat };

例子

以下示例演示了枚举变量的使用 -

import std.stdio;

enum Days { sun, mon, tue, wed, thu, fri, sat };

int main(string[] args) {
   Days day;

   day = Days.mon;
   writefln("Current Day: %d", day); 
   writefln("Friday : %d", Days.fri); 
   return 0;
}

当上面的代码被编译并执行时,它会产生以下结果 -

Current Day: 1 
Friday : 5

在上面的程序中,我们可以看到如何使用枚举。最初,我们创建一个名为day的变量,用于用户定义的枚举 Days。然后我们使用点运算符将其设置为mon 。我们需要使用 writefln 方法来打印存储的 mon 的值。您还需要指定类型。它是整数类型,因此我们使用 %d 进行打印。

命名枚举属性

上面的示例使用名称 Days 进行枚举,称为命名枚举。这些命名枚举具有以下属性 -

  • Init - 它初始化枚举中的第一个值。

  • min - 它返回枚举的最小值。

  • max - 返回枚举的最大值。

  • sizeof - 它返回枚举的存储大小。

让我们修改前面的示例以利用这些属性。

import std.stdio;

// Initialized sun with value 1 
enum Days { sun = 1, mon, tue, wed, thu, fri, sat };

int main(string[] args) { 
   writefln("Min : %d", Days.min); 
   writefln("Max : %d", Days.max);
   writefln("Size of: %d", Days.sizeof); 
   return 0; 
}

当上面的代码被编译并执行时,它会产生以下结果 -

Min : 1
Max : 7
Size of: 4

匿名枚举

没有名称的枚举称为匿名枚举。下面给出了匿名枚举的示例。

import std.stdio; 
 
// Initialized sun with value 1 
enum { sun , mon, tue, wed, thu, fri, sat }; 
 
int main(string[] args) { 
   writefln("Sunday : %d", sun); 
   writefln("Monday : %d", mon); 
   return 0; 
}

当上面的代码被编译并执行时,它会产生以下结果 -

Sunday : 0
Monday : 1

匿名枚举的工作方式与命名枚举几乎相同,但它们没有 max、min 和 sizeof 属性。

具有基本类型语法的枚举

具有基本类型的枚举的语法如下所示。

enum :baseType {  
   enumeration list 
}

一些基本类型包括 long、int 和 string。下面显示了使用 long 的示例。

import std.stdio;
  
enum : string { 
   A = "hello", 
   B = "world", 
} 
  
int main(string[] args) { 
   writefln("A : %s", A); 
   writefln("B : %s", B); 
   
   return 0; 
}

当上面的代码被编译并执行时,它会产生以下结果 -

A : hello
B : world

更多功能

D 中的枚举提供了诸如在具有多种类型的枚举中初始化多个值之类的功能。一个例子如下所示。

import std.stdio;
  
enum { 
   A = 1.2f,  // A is 1.2f of type float 
   B,         // B is 2.2f of type float 
   int C = 3, // C is 3 of type int 
   D          // D is 4 of type int 
}
  
int main(string[] args) { 
   writefln("A : %f", A); 
   writefln("B : %f", B); 
   writefln("C : %d", C); 
   writefln("D : %d", D);  
   return 0; 
}

当上面的代码被编译并执行时,它会产生以下结果 -

A : 1.200000
B : 2.200000
C : 3
D : 4

D 编程 - 文字

作为源代码的一部分在程序中键入的常量值称为文字

文字可以是任何基本数据类型,可以分为整数、浮点数字、字符、字符串和布尔值。

同样,文字的处理方式与常规变量一样,只是它们的值在定义后不能修改。

整数文字

整数文字可以是以下类型 -

  • 十进制使用正常的数字表示形式,第一位数字不能为 0,因为该数字被保留用于指示八进制系统。这不包括 0 本身:0 为零。

  • 八进制使用 0 作为数字前缀。

  • 二进制使用 0b 或 0B 作为前缀。

  • 十六进制使用 0x 或 0X 作为前缀。

整数文字还可以具有 U 和 L 的组合后缀,分别表示无符号和长整型。后缀可以是大写或小写,并且可以是任何顺序。

当您不使用后缀时,编译器本身会根据值的大小在 int、uint、long 和 ulong 之间进行选择。

以下是整数文字的一些示例 -

212         // Legal 
215u        // Legal 
0xFeeL      // Legal 
078         // Illegal: 8 is not an octal digit 
032UU       // Illegal: cannot repeat a suffix 

以下是各种类型整数文字的其他示例 -

85         // decimal 
0213       // octal
0x4b       // hexadecimal 
30         // int 
30u        // unsigned int 
30l        // long 
30ul       // unsigned long 
0b001      // binary

浮点文字

浮点文字可以用十进制系统(如 1.568)或十六进制系统(如 0x91.bc)指定。

在十进制中,指数可以通过在字符 e 或 E 后面加上一个数字来表示。例如,2.3e4 表示“2.3 乘以 10 的 4 次方”。可以在指数值之前指定“+”字符,但没有任何作用。例如 2.3e4 和 2.3e + 4 是相同的。

在指数值之前添加的“-”字符将含义更改为“除以 10 的次方”。例如,2.3e-2 表示“2.3 除以 10 的 2 次方”。

在十六进制系统中,该值以 0x 或 0X 开头。指数由 p 或 P 指定,而不是 e 或 E。指数并不表示“10 的次方”,而是“2 的次方”。例如0xabc.defP4中的P4表示“abc.de乘以2的4次方”。

以下是浮点文字的一些示例 -

3.14159       // Legal 
314159E-5L    // Legal 
510E          // Illegal: incomplete exponent 
210f          // Illegal: no decimal or exponent 
.e55          // Illegal: missing integer or fraction 
0xabc.defP4   // Legal Hexa decimal with exponent 
0xabc.defe4   // Legal Hexa decimal without exponent.

默认情况下,浮点文字的类型为 double。f 和 F 表示浮点数,L 说明符表示实数。

布尔文字

有两个布尔文字,它们是标准 D 关键字的一部分 -

  • true值代表 true。

  • false值代表 false。

您不应将 true 值视为等于 1,将 false 值视为等于 0。

字符文字

字符文字用单引号括起来。

字符文字可以是普通字符(例如“x”)、转义序列(例如“\t”)、ASCII 字符(例如“\x21”)、Unicode 字符(例如“\u011e”)或作为命名字符(例如 '\©','\♥', '\€' )。

D 中有一些字符,当它们前面有反斜杠时,它们将具有特殊含义,它们用于表示换行符 (\n) 或制表符 (\t)。在这里,您有一些此类转义序列代码的列表 -

转义序列 意义
\\ \ 特点
\' ' 特点
\" “ 特点
\? ?特点
\A 警报或铃声
\b 退格键
\F 换页
\n 新队
\r 回车符
\t 水平制表符
\v 垂直标签

以下示例显示了一些转义序列字符 -

import std.stdio;
  
int main(string[] args) { 
   writefln("Hello\tWorld%c\n",'\x21'); 
   writefln("Have a good day%c",'\x21'); 
   return 0; 
}

当上面的代码被编译并执行时,它会产生以下结果 -

Hello   World!

Have a good day!

字符串文字

字符串文字用双引号括起来。字符串包含与字符文字类似的字符:普通字符、转义序列和通用字符。

您可以使用字符串文字将长行分成多行,并使用空格将它们分隔开。

以下是字符串文字的一些示例 -

import std.stdio;

int main(string[] args) {
   writeln(q"MY_DELIMITER
      Hello World
      Have a good day
      MY_DELIMITER");

   writefln("Have a good day%c",'\x21'); 
   auto str = q{int value = 20; ++value;}; 
   writeln(str); 
}

在上面的例子中,你可以发现使用 q"MY_DELIMITER MY_DELIMITER" 来表示多行字符。另外,您可以看到 q{} 代表 D 语言语句本身。

D 编程 - 运算符

运算符是告诉编译器执行特定数学或逻辑操作的符号。D 语言具有丰富的内置运算符,并提供以下类型的运算符 -

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 按位运算符
  • 赋值运算符
  • 杂项运算符

本章一一讲解算术、关系、逻辑、位、赋值等运算符。

算术运算符

下表列出了 D 语言支持的所有算术运算符。假设变量A为 10,变量B为 20,则 -

显示示例

操作员 描述 例子
+ 它添加了两个操作数。 A + B 得出 30
- 它从第一个操作数中减去第二个操作数。 A - B 给出 -10
* 它将两个操作数相乘。 A * B 给出 200
/ 它将分子除以分母。 B / A 给出 2
% 它返回整数除法的余数。 B % A 给出 0
++ 增量运算符将整数值加一。 A++ 给出 11
-- 递减运算符将整数值减一。 A-- 给出 9

关系运算符

下表列出了D语言支持的所有关系运算符。假设变量A为 10,变量B为 20,则 -

显示示例

操作员 描述 例子
== 检查两个操作数的值是否相等,如果相等则条件为真。 (A == B) 不正确。
!= 检查两个操作数的值是否相等,如果值不相等则条件成立。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是,则条件为真。 (A > B) 不正确。
< 检查左操作数的值是否小于右操作数的值,如果是,则条件为真。 (A < B) 为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是,则条件为真。 (A >= B) 不正确。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是,则条件为真。 (A <= B) 为真。

逻辑运算符

下表列出了D语言支持的所有逻辑运算符。假设变量A为 1,变量B为 0,则 -

显示示例

操作员 描述 例子
&& 它称为逻辑与运算符。如果两个操作数均非零,则条件为真。 (A && B) 是错误的。
|| 它称为逻辑或运算符。如果两个操作数中的任何一个非零,则条件为真。 (A || B) 为真。
它被称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑 NOT 运算符将为假。 !(A && B) 为真。

按位运算符

位运算符作用于位并执行逐位运算。&、| 和 ^ 的真值表如下 -

p q 质与问 p| q p^q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

假设A = 60;B = 13。在二进制格式中,它们如下 -

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

〜A = 1100 0011

D 语言支持的按位运算符如下表所示。假设变量 A 为 60,变量 B 为 13,则 -

显示示例

操作员 描述 例子
& 如果两个操作数中都存在,则二进制 AND 运算符会将一位复制到结果中。 (A & B) 将给出 12,即 0000 1100。
| 如果任一操作数中存在该位,则二元或运算符会复制该位。 (A | B) 给出 61。意味着 0011 1101。
^ 如果在一个操作数中设置了该位,但不是在两个操作数中都设置了该位,则二进制 XOR 运算符会复制该位。 (A ^ B) 给出 49。意味着 0011 0001
二进制补码运算符是一元的,具有“翻转”位的效果。 (~A ) 给出 -61。表示 2 的补码形式的 1100 0011。
<< 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 A << 2 给出 240。意味着 1111 0000
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 A >> 2 给出 15。意味着 0000 1111。

赋值运算符

D 语言支持以下赋值运算符 -

显示示例

操作员 描述 例子
= 这是简单的赋值运算符。它将右侧操作数中的值分配给左侧操作数 C = A + B 将 A + B 的值赋给 C
+= 它是加AND赋值运算符。它将右操作数添加到左操作数并将结果分配给左操作数 C += A 等价于 C = C + A
-= 它是减法与赋值运算符。它从左操作数中减去右操作数,并将结果赋给左操作数。 C -= A 相当于 C = C - A
*= 它是乘法与赋值运算符。它将右操作数与左操作数相乘,并将结果赋给左操作数。 C *= A 相当于 C = C * A
/= 它是除法与赋值运算符。它将左操作数与右操作数相除,并将结果赋给左操作数。 C /= A 相当于 C = C / A
%= 它是模与赋值运算符。它使用两个操作数取模并将结果分配给左操作数。 C %= A 相当于 C = C % A
<<= 它是左移AND赋值运算符。 C <<= 2 与 C = C << 2 相同
>>= 它是右移与赋值运算符。 C >>= 2 与 C = C >> 2 相同
&= 它是按位与赋值运算符。 C &= 2 与 C = C & 2 相同
^= 它是按位异或和赋值运算符。 C ^= 2 与 C = C ^ 2 相同
|= 它是按位或和赋值运算符 C |= 2 与 C = C | 相同 2

杂项运算符 - Sizeof 和三元

还有一些其他重要的运算符,包括sizeof? :由D语言支持。

显示示例

操作员 描述 例子
大小() 返回变量的大小。 sizeof(a)(其中 a 是整数)返回 4。
& 返回变量的地址。 &A; 给出变量的实际地址。
* 指向变量的指针。 *A; 给出指向变量的指针。
?: 条件表达式 如果条件为真,则值 X:否则值 Y。

D 中的运算符优先级

运算符优先级决定表达式中术语的分组。这会影响表达式的计算方式。某些运算符优先于其他运算符。

例如,乘法运算符的优先级高于加法运算符。

让我们考虑一个表达式

x = 7 + 3 * 2。

这里,x 被分配为 13,而不是 20。原因很简单,运算符 * 的优先级高于 +,因此先计算 3*2,然后将结果与 7 相加。

在这里,优先级最高的运算符出现在表的顶部,优先级最低的运算符出现在底部。在表达式中,首先计算优先级较高的运算符。

显示示例

类别 操作员 关联性
后缀 () [] -> . ++ - - 左到右
一元 + - ! ~ ++ - - (类型)* & sizeof 右到左
乘法 * / % 左到右
添加剂 + - 左到右
转移 <<>> 左到右
关系型 <<=>>= 左到右
平等 ==!= 左到右
按位与 & 左到右
按位异或 ^ 左到右
按位或 | 左到右
逻辑与 && 左到右
逻辑或 || 左到右
有条件的 ?: 右到左
任务 = += -= *= /= %=>>= <<= &= ^= |= 右到左
逗号 , 左到右

D 编程 - 循环

可能存在一种情况,当您需要多次执行一段代码时。一般来说,语句是按顺序执行的:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。

编程语言提供了各种控制结构,允许更复杂的执行路径。

循环语句多次执行一条语句或一组语句。以下循环语句的一般形式主要用于编程语言 -

循环架构

D 编程语言提供以下类型的循环来处理循环要求。单击以下链接查看其详细信息。

先生。 循环类型和描述
1 while 循环

当给定条件为真时,它会重复一个语句或一组语句。它在执行循环体之前测试条件。

2 for循环

它多次执行一系列语句并缩写管理循环变量的代码。

3 do...while 循环

与 while 语句类似,只不过它测试循环体末尾的条件。

4 嵌套循环

您可以在任何另一个 while、for 或 do..while 循环中使用一个或多个循环。

循环控制语句

循环控制语句改变其正常顺序的执行。当执行离开作用域时,在该作用域中创建的所有自动对象都将被销毁。

D 支持以下控制语句 -

先生。 控制语句和描述
1 中断语句

终止循环或 switch 语句并将执行转移到紧随循环或 switch 之后的语句。

2 继续声明

导致循环跳过其主体的其余部分并在重复之前立即重新测试其条件。

无限循环

如果条件永远不会变为假,则循环将成为无限循环。for循环传统上用于此目的。由于构成 for 循环的三个表达式都不是必需的,因此您可以通过将条件表达式留空来创建无限循环。

import std.stdio;

int main () {

   for( ; ; ) {
      writefln("This loop will run forever.");
   }
   return 0;
}

当条件表达式不存在时,假定为真。您可能有一个初始化和增量表达式,但 D 程序员更常用 for(;;) 构造来表示无限循环。

注意- 您可以通过按 Ctrl + C 键终止无限循环。

D 编程 - 决策

决策结构包含要评估的条件以及要执行的两组语句。如果条件为真,则执行一组语句;如果条件为假,则执行另一组语句。

以下是大多数编程语言中典型决策结构的一般形式 -

D 中的决策陈述

D 编程语言将任何非零非空值假定为true,如果它为零null 则将其假定为false值。

D 编程语言提供以下类型的决策语句。

先生。 声明及说明
1 if 语句

if语句由一个布尔表达式后跟一个或多个语句组成。

2 if...else 语句

if语句后面可以跟一个可选的else 语句,该语句在布尔表达式为 false 时执行。

3 嵌套 if 语句

您可以在另一个ifelse if语句中使用一个ifelse if语句。

4 switch语句

switch语句允许测试变量是否与值列表相等

5 嵌套 switch 语句

您可以在另一个switch语句中使用一个switch语句。

这 ?: D 中的运算符

我们已经介绍了条件运算符 ? :在上一章中可以用来替换if...else语句。它具有以下一般形式

Exp1 ? Exp2 : Exp3;

其中 Exp1、Exp2 和 Exp3 是表达式。注意冒号的使用和位置。

的值?表达式确定如下 -

  • 对 Exp1 进行评估。如果为真,则计算 Exp2 并成为整个 ? 的值。表达。

  • 如果 Exp1 为 false,则计算 Exp3 并且其值成为表达式的值。

D 编程 - 函数

本章介绍 D 编程中使用的函数。

D 中的函数定义

基本函数定义由函数头和函数体组成。

句法

return_type function_name( parameter list ) { 
   body of the function 
}

这是函数的所有部分 -

  • 返回类型- 函数可以返回一个值。return_type是函数返回值的数据类型有些函数执行所需的操作而不返回值。在本例中, return_type 是关键字void

  • 函数名称- 这是函数的实际名称。函数名和参数列表共同构成函数签名。

  • 参数- 参数就像占位符。当调用函数时,您将一个值传递给参数。该值称为实际参数或参数。参数列表是指函数参数的类型、顺序和数量。参数可选;也就是说,函数可以不包含参数。

  • 函数体- 函数体包含定义函数功能的语句集合。

调用函数

您可以按如下方式调用函数 -

function_name(parameter_values)

D 中的函数类型

D 编程支持多种函数,如下所列。

  • 纯函数
  • 无抛出函数
  • 参考功能
  • 自动功能
  • 可变参数函数
  • 输入输出函数
  • 属性功能

下面解释了各种功能。

纯函数

纯函数是无法通过其参数访问全局或静态、可变状态保存的函数。这可以基于以下事实实现优化:保证纯函数不会改变未传递给它的任何内容,并且在编译器可以保证纯函数无法更改其参数的情况下,它可以实现完整的函数纯度,即也就是说,保证函数对于相同的参数始终返回相同的结果)。

import std.stdio; 

int x = 10; 
immutable int y = 30; 
const int* p;  

pure int purefunc(int i,const char* q,immutable int* s) { 
   //writeln("Simple print"); //cannot call impure function 'writeln'
   
   debug writeln("in foo()"); // ok, impure code allowed in debug statement 
   // x = i;  // error, modifying global state 
   // i = x;  // error, reading mutable global state 
   // i = *p; // error, reading const global state
   i = y;     // ok, reading immutable global state 
   auto myvar = new int;     // Can use the new expression: 
   return i; 
}

void main() { 
   writeln("Value returned from pure function : ",purefunc(x,null,null)); 
}

当上面的代码被编译并执行时,它会产生以下结果 -

Value returned from pure function : 30 

无抛出函数

Nothrow 函数不会抛出任何从 Exception 类派生的异常。Nothrow 函数与 throw 函数是协变的。

Nothrow 保证函数不会发出任何异常。