跳轉到內容

D 程式設計/第一個程式示例

來自華夏公益教科書,開放的書籍,為開放的世界

待完成。

D 程式的結構

[編輯 | 編輯原始碼]

每個程式都必須有一個起點。在 D 中,這個起點是名為 main 的函式,除了 Windows GUI 程式,它使用 WinMain。你必須有一個這些函式來建立一個可執行的應用程式。

注意

  • 雖然這個函式是程式處理流程的起點,但你的程式碼的其他部分可能在 main 獲得控制之前執行。這些是模組和類建構函式,將在後面討論。
  • 一個或多個沒有 main 函式的模組集合被稱為,它不是一個可執行程式。相反,庫中的函式被應用程式用作預先編寫的功能。

簡單的 D 程式

[編輯 | 編輯原始碼]

注意

  • 在 D 程式語言中,main 函式必須返回 voidint 資料型別。這個返回值將返回給作業系統。
  • 如果指定了 void 返回型別,應用程式將返回一個值為 0int,否則程式必須提供一個返回值。
  • 在 D 程式語言中,main 函式必須指定不帶引數或以 char[][] 形式帶單個引數,它是一個包含命令列引數的 UTF8 字串陣列。

總之,main 函式可以採用四種格式之一 ...

int main() // Application defined return value,   ignores command line
int main(char[][] args)  // Application defined return value, uses command line
void main() // returns 0, ignores command line
void main(char[][] args) //returns 0, uses command line
import std.stdio;
void main() 
{ 
 writefln("Hello World!");
}

這個程式只是在控制檯上列印 "Hello World!",後面跟著一個換行符,然後退出。第一行匯入標準庫模組 std.stdio。這個模組定義了函式 writefln,它用於寫入標準輸出。這個程式不使用命令列引數,並將返回零給作業系統。

你需要編譯它來將其轉換為可執行程式。首先,你將原始碼儲存到一個具有 ".d" 副檔名的文字檔案中。假設我們把這個檔案叫做 hw.d,以下是使用 DigitalMars 編譯器編譯它的方法 ...

dmd hw.d
import std.stdio;
void main(char[][] p_Args) 
{ 
 foreach(char[] l_Arg; p_Args)
 {
   writefln("Argument '%s'", l_Arg);
 }
}

這個程式打印出每個命令列引數。main 的引數是

char[][] p_Args

它將引數命名為 p_Args 並將其資料型別宣告為 char[][],它是一個可變長度的 UTF8 字串陣列。這意味著 main 傳遞了一組零個或多個字串。

foreach 語句是處理陣列中每個元素的一種方法。在上面的格式中,它命名了一個臨時變數 l_Arg,它將依次接收每個元素,因為 foreach 在陣列 p_Args 中移動。臨時變數的範圍限定在 foreach 塊內,因此外部程式碼無法看到它。

writefln 函式不僅向控制檯寫入內容,還允許你格式化輸出。%s 是一個格式化程式碼,它指定了後續引數將在控制檯輸出中出現的位置。在這種情況下,如果 l_Arg 包含 "abc",則輸出將是 "Argument 'abc'"。

這個註釋豐富的示例突出了許多比 C++ 的改進。

#!/usr/bin/dmd -run
/* sh style script syntax is supported! */
/* Hello World in D
   To compile:
     dmd hello.d
   or to optimize:
     dmd -O -inline -release hello.d
   or to get generated documentation:
     dmd hello.d -D
  */
import std.stdio;  // References to  commonly used I/O routines.
void main(char[][] args)   // 'void' here means return 0 by default.
{
    // Write-Formatted-Line
     writefln("Hello World, "   // automatic concatenation of string literals
              "Reloaded");
     // Strings are denoted as a dynamic array of chars 'char[]'
     // auto type inference and built-in foreach
     foreach(argc, argv; args)
    {
        // OOP is supported, of course! And automatic type inference.
         auto cl = new CmdLin(argc, argv);
 
        // 'writefln' is the improved 'printf' !!
         // user-defined class properties.
         writefln(cl.argnum, cl.suffix, " arg: %s", cl.argv);
        // Garbage Collection or explicit memory management - your choice!!!
         delete cl;
    }
     // Nested structs, classes and functions!
     struct specs
    {
        // all vars. automatically initialized
         int count, allocated;
    }
 
    // Note that declarations read right-to-left. 
    // So that 'char[][]' reads as an array of an array of chars.

    specs argspecs(char[][] args)
    // Optional (built-in) function contracts.
     in{
        assert (args.length > 0); // assert built in
     }
    out(result){
        assert(result.count == CmdLin.total);
        assert(result.allocated > 0);
    }
    body{
        specs* s = new specs;
        // no need for '->'
         s.count = args.length;  // The 'length' property is number of elements.
         s.allocated = typeof(args).sizeof; // built-in properties for native types
         foreach(argv; args)
            s.allocated += argv.length * typeof(argv[0]).sizeof;
        return *s;
    }
 
    // built-in string and common string operations, e.g. '~' is concatenate.
     char[] argcmsg  = "argc = %d";
    char[] allocmsg = "allocated = %d";
    writefln(argcmsg ~ ", " ~ allocmsg,
         argspecs(args).count,argspecs(args).allocated);
}
/**
   Stores a single command line argument.
 */
 class CmdLin
{
    private {
     int _argc;
     char[] _argv;
     static uint _totalc;
    }
 
 public:
/************
      Object constructor.
      params:
        argc = ordinal count of this argument.
        argv = text of the parameter
  *********/
     this(int argc, char[] argv)
    {
        _argc = argc + 1;
        _argv = argv;
        _totalc++;
    }
 
    ~this() /// Object destructor
     {
        // Doesn't actually do anything for this example.
     }
 
     int argnum() /// A property that returns arg number
     {
        return _argc;
    }
     char[] argv() /// A property  that returns arg text
     {
        return _argv;
    }
     wchar[] suffix() /// A property  that returns ordinal suffix
     {
        wchar[] suffix;  // Built in  Unicode strings (utf8,utf16, utf32)
         switch(_argc)
        {
        case 1:
            suffix = "st";
            break;
        case 2:
            suffix = "nd";
            break;
        case 3:
            suffix = "rd";
            break;
        default:  // 'default' is mandatory with "-w" compile switch.
             suffix = "th";
        }
        return suffix;
    }
 
/* **************
      * A property of the whole class, not just an instance.
      * returns: The total number of commandline args added.
      *************/
     static typeof(_totalc) total()
    {
        return _totalc;
    }
     // Class invariant, things that must be true after any method is run.
     invariant
     {
         assert(_argc > 0);
         assert(_totalc >= _argc);
     }
}
華夏公益教科書