Page cover image

Command-Line Arguments

สุขุมาภรณ์ เหมือนวงศ์ธรรม 650710096

บทนำ

โดยปกติแล้วเราสามารถส่ง Arguments ไปยัง method ผ่าน Parameter ได้ แล้วในเมธอด Main()เราสามารถส่ง arguments ไปได้หรือไม่ ?

คำตอบคือ ' ได้ ' เราสามารถส่งพารามิเตอร์ไปยังเมธอด Main() ได้ และทำได้โดยใช้ Command-Line Arguments ที่ส่งโดยผู้ใช้หรือโปรแกรมเมอร์ไปยังเมธอด Main()

เมธอด Main() เป็นจุดเริ่มต้นของโปรแกรมในภาษา เมื่อตัวโปรแกรมเริ่มทำงาน เมธอด Main() จะถูกเรียกใช้งานเป็นเมธอดแรก ทุกอย่างในโปรแกรมจะเริ่มทำงานจากที่นี่

Parameter และ Argument คืออะไร

  • Parameter : คือค่าที่ระบุในส่วนหัวของฟังก์ชันหรือเมธอดเมื่อประกาศ ซึ่งเป็นตัวแปรที่ใช้ภายในฟังก์ชันเพื่อรับค่าจาก argument

  • Argument : คือค่าที่ถูกส่งเข้ามาให้ฟังก์ชันหรือเมธอดเมื่อเรียกใช้งาน เช่น ค่า 5 ที่ส่งเข้าไปในฟังก์ชันที่คาดหวังรับค่าเป็นพารามิเตอร์

เมธอด Main()

ในภาษา C# เมธอด Main() เป็น entry point เพียงตัวเดียวของการเริ่มทำงานโปรแกรม ในทุกโปรแกรมต้องมี เมธอด Main() เสมอ

class TestClass
{
    //เมธอด Main()
    static void Main(string[] args)
    {
        // แสดงจำนวน arguments ที่ส่งเข้ามาผ่าน command line
        Console.WriteLine(args.Length);
    }
}

แต่เราสามารถเขียนโค้ดในไฟล์โปรแกรมหลักได้โดยไม่ต้องสร้างเมธอด Main() ด้วยการใช้

Top-level statement ที่เขียนโค้ดโดยตรงในไฟล์โปรแกรมโดยที่ไม่ต้องห่อหุ้มโค้ดนั้นในคลาส (class) หรือเมธอด (method) ใดๆ ซึ่งโค้ดนั้นจะถูกมองว่าเป็น entry point ของโปรแกรม และ Top-level statement สามารถคืนค่าผลลัพธ์จากโปรแกรมได้ และเข้าถึง command-line arguments ได้ผ่านตัวแปร args ที่สามารถใช้ได้โดยตรงใน top-level code โดยไม่ต้องกำหนดพารามิเตอร์ใน Main()

using System.Text;

StringBuilder builder = new();
builder.AppendLine("The following arguments are passed:");

// แสดง command line arguments จากตัวแปร args 
foreach (var arg in args)
{
    builder.AppendLine($"Argument={arg}");
}

Console.WriteLine(builder.ToString());

// Return a success code.
return 0;

ตัวอย่างการประกาศเมธอด Main() ใน C#

// หากไม่ใช้ argument เมธอด Main() จะประกาศแบบไม่ระบุ parameter
static void Main() { }
static int Main() { }
static async Task Main() { }
static async Task<int> Main() { }

// string[] args คือพารามิเตอร์ที่เราจะส่งค่าเข้าไปผ่าน command line
static void Main() { }
static int Main(string[] args) { }
static async Task Main(string[] args) { }
static async Task<int> Main(string[] args) { }

การเพิ่ม async และประเภทการคืนค่าแบบ Task หรือ Task<int> ทำให้โค้ดโปรแกรมง่ายขึ้นเมื่อแอปพลิเคชั่นแบบคอนโซลต้องการเริ่มต้นและรอ (await) การทำงานแบบ asynchronous ในเมธอด Main

Main() return values

เราสามารถคืนค่า int ออกมาจาก เมธอด Main() ด้วยการประกาศเมธอดแบบใดแบบหนึ่ง:

static int Main()
static int Main(string[] args)
static async Task<int> Main()
static async Task<int> Main(string[] args)

หากไม่ต้องการให้เมธอด Main() คืนค่าอะไรออกมา ให้คืนค่าเป็น void

static void Main()
static void Main(string[] args)
static async Task Main()
static async Task Main(string[] args)

Async Main() return values

เมื่อประกาศให้เมธอด Main() คืนค่าแบบ async (รองรับการทำงานแบบอะซิงโครนัส) ตัวคอมไพเลอร์จะสร้างโค้ดพื้นฐาน (boilerplate code) ให้สำหรับการเรียกใช้เมธอดที่ทำงานแบบอะซิงโครนัสใน Main โดยอัตโนมัติ ซึ่งจะช่วยให้โค้ดสามารถรันได้ตามลำดับกระบวนการที่ถูกต้อง

class Program
{
    //ใช้ async ในเมธอด Main โดยตรง 
    static async Task<int> Main(string[] args)
    {
        //ช้ await เพื่อรอผลลัพธ์ของการทำงาน AsyncConsoleWork โดยไม่ต้องใช้ GetAwaiter().GetResult()
        return await AsyncConsoleWork();
    }

    private static async Task<int> AsyncConsoleWork()
    {
        // main body here 
        return 0;
    }
}

แต่ถ้าไม่ได้ใช้คีย์เวิร์ด async จะต้องเขียนโค้ดสำหรับจัดการการทำงานอะซิงโครนัสด้วยตนเอง โค้ดในตัวอย่างนี้จะทำให้แน่ใจว่าโปรแกรมจะรันจนกระทั่งการดำเนินการอะซิงโครนัสเสร็จสิ้นสมบูรณ์

class AsyncMainReturnValTest
{
    //ใช้เมธอด Main โดยไม่ได้ระบุคีย์เวิร์ด async
    public static int Main()
    {   
        //.GetAwaiter().GetResult() บังคับให้รอผลลัพธ์ของงานอะซิงโครนัสแบบบล็อกการทำงาน เขียนเพิ่มเอง
        return AsyncConsoleWork().GetAwaiter().GetResult();
    }
    //ใช้การดำเนินการอะซิงโครนัสภายในได้ โดยจะคืนค่า Task<int>
    private static async Task<int> AsyncConsoleWork()
    {
        // Main body here
        return 0;
    }
}

Command-Line Arguments คืออะไร?

Command-Line Arguments คือข้อมูลที่ผู้ใช้ส่งให้กับโปรแกรมเมื่อรันจาก command line โดยจะถูกส่งเข้าไปใน parameter ของเมธอด Main(parameter)

อย่างไรก็ตาม Main() จะไม่รับ argument จากเมธอดอื่นๆ ภายในโปรแกรม แต่จะรับค่าที่ส่งเข้ามาจาก command line เท่านั้น

เมื่อผู้ใช้ส่ง argument ให้กับโปรแกรมเมื่อรันจาก command line จะถูกส่งเข้าไปใน parameter ของเมธอด Main(string[] args) โดยข้อมูลเหล่านี้จะถูกเก็บในตัวแปรที่ชื่อว่า argsในรูปแบบของ array ประเภท string ช่วยให้โปรแกรมสามารถรับข้อมูลที่แตกต่างกัน (ประเภท int, double, float, char ฯลฯ) ได้ตามที่ผู้ใช้ระบุ

เราสามารถตรวจสอบได้ว่ามี arguments อยู่ใน Main() หรือไม่ โดยการใช้Length ที่เป็น property ของอาร์เรย์ที่สามารถเข้าถึงได้ เพื่อบอกจำนวนสมาชิกทั้งหมดในอาร์เรย์นั้น

//จำนวนของ command-line arguments ที่อยู่ในอาร์เรย์ args ซึ่งถูกส่งเข้ามาเมื่อรันโปรแกรม
if (args.Length == 0)
{
    System.Console.WriteLine("Please enter a numeric argument.");
    return 1;
}

อาร์เรย์ args ไม่สามารถเป็นค่า null ได้ ดังนั้นจึงปลอดภัยที่จะเข้าถึง property Length โดยไม่ต้องตรวจสอบค่า null

สามารถแปลง argument string เป็นประเภท int ได้โดยใช้คลาส Convert หรือเมธอด Parse

//แปลงจาก string เป็น int
long num = Int64.Parse(args[0]);

ตัวอย่างการใช้ Command-Line Arguments ในภาษา C#

ตัวอย่างที่ 1:

//Test1.cs
using System;
namespace FirstProgram
{
    class Program
    {
        //รับ argument 
        static void Main(string[] args)
        {  
            //แสดงผล argument ที่รับเข้ามาค่าแรก
            Console.WriteLine($"First Command Line Argument {args[0]}");
            //แสดงผล argument ที่รับเข้ามาค่าที่สอง
            Console.WriteLine($"Second Command Line Argument {args[1]}");
            //แสดงผล argument ที่รับเข้ามาค่าที่สาม
            Console.WriteLine($"Third Command Line Argument {args[2]}");
        }
    }
}

วิธีการส่งค่า argument ผ่านทาง command line

  1. เปิด Command Prompt หรือ Terminal ในโฟลเดอร์ที่มีไฟล์ Test1.cs

  2. compile โปรแกรมด้วยคำสั่ง dotnet build

  3. รันโปรแกรมด้วยคำสั่ง dotnet run พร้อมระบุ argument ที่จะส่งไป

Iutput:

//ไม่ใส่ -- เมื่อส่ง argument ไม่มีเครื่องหมาย - หรือ -- นำหน้า
dotnet run value1 value2 value3

Output:

First Command Line Argument value1
Second Command Line Argument value2
Third Command Line Argument value3 

ตัวอย่างที่ 2:C#

//Program.cs
public class Functions
{
    public static long Factorial(int n)
    {
        // Test for invalid input.
        if ((n < 0) || (n > 20))
        {
            return -1;
        }

        // Calculate the factorial iteratively rather than recursively.
        long tempResult = 1;
        for (int i = 1; i <= n; i++)
        {
            tempResult *= i;
        }
        return tempResult;
    }
}

class MainClass
{
    static int Main(string[] args)
    {
        // ทดสอบว่ามีการระบุ argument อินพุตหรือไม่
        if (args.Length == 0)
        {
            Console.WriteLine("Please enter a numeric argument.");
            Console.WriteLine("Usage: Factorial <num>");
            return 1;
        }

        // Try to convert the input arguments to numbers. This will throw
        // an exception if the argument is not a number.
        // num = int.Parse(args[0]);
        int num;
        bool test = int.TryParse(args[0], out num);
        if (!test)
        {
            Console.WriteLine("Please enter a numeric argument.");
            Console.WriteLine("Usage: Factorial <num>");
            return 1;
        }

        // คำนวณ factorial.
        long result = Functions.Factorial(num);

        // แสดงผลลัพธ์
        if (result == -1)
            Console.WriteLine("Input must be >= 0 and <= 20.");
        else
            Console.WriteLine($"The Factorial of {num} is {result}.");

        return 0;
    }
}

Iutput:

//-- ใช้แยก argument ที่ถูกส่งไปให้ CLI (เครื่องมือที่ใช้จัดการโครงสร้าง .NET) กับ argument ที่ถูกส่งไปให้โปรแกรมที่คุณรัน
dotnet run -- 3

Output:

The factorial of 3 is 6

เปรียบเทียบ Command-Line Arguments กับภาษา Java, C, Python

Java

ใน Java เมื่อโปรแกรมถูกเรียกใช้ JVM (Java Virtual Machine) จะเริ่มรันจากเมธอด main() เป็นอันดับแรก โดยเราสามารถส่งค่า argument ไปที่เมธอด main() ด้วย command line ผ่านทาง parameter ของเมธอด main(String[] args) เราสามารถส่งข้อมูลประเภท int, double, float, char ฯลฯ ได้โดยข้อมูลเหล่านี้จะถูกเก็บในตัวแปรที่ชื่อว่า argsในรูปแบบของ array ประเภท String เหมือนกับภาษา C#

เมื่อส่ง argument ไปยัง JVM แล้ว JVM จะห่อ argument เหล่านี้และส่งไปยัง args[] สามารถตรวจสอบจำนวนของ argument ที่ถูกส่งเข้ามาผ่าน command line ในโดยใช้เมธอด args.length JVM จะจัดเก็บ argument แรกไว้ที่ args[0] argument ที่สองไว้ที่ args[1] argument ที่สามไว้ที่ args[2] อย่างนี้ไปเรื่อยๆ

  • พารามิเตอร์ในเมธอด Main:Java ฟังก์ชัน main ใน Java ต้องมี String[] args เป็นพารามิเตอร์เสมอ และ return type เป็น void เท่านั้น C# ฟังก์ชัน Main ใน C# มีความยืดหยุ่นมากกว่า สามารถ return ค่าเป็น void, int, Task, หรือ Task<int> ได้ และรองรับการใช้ async สำหรับการทำงานแบบอะซิงโครนัส

C

ฟังก์ชัน main() ในภาษา C มักจะเขียนโดยไม่มี Argument และมีการส่งคืนค่าเป็น 0 หรือไม่มีการส่งคืนค่า โดยปกติภายในฟังก์ชัน main() มีคำสั่ง scanf() เพื่อให้ผู้ใช้ป้อนค่าเข้าไป แต่แทนที่จะเขียนโค้ดค่าต่างๆ เหล่านั้นไว้ภายในโค้ด เราสามารถส่งค่า หรือ argument จาก command line ไปยังฟังก์ชัน main() ได้ เมื่อโปรแกรมทำงาน ค่าเหล่านี้จะถูกเรียกว่า Command-Line Arguments โปรแกรมสามารถรับข้อมูลนี้ผ่านฟังก์ชัน main() โดยผ่านพารามิเตอร์สองตัว คือ

argc (argument count): บอกจำนวนของ arguments ที่ส่งเข้ามา ควรเป็นค่าบวกเสมอ

argv[] (argument vector): เป็น array ของ strings เป็นตัวชี้ที่ไปยัง arguments จริง ๆทั้งหมด โดย argv[0] มักเป็นชื่อของโปรแกรม

  • การประกาศ: C ต้องการ argc และ argv ใน main ในขณะที่ C# ใช้ string[] args

  • การเข้าถึง: C ใช้ char *argv[] และ C# ใช้ string[] args

  • index ของ argument แรก: Cargv[0] คือ ชื่อโปรแกรม แต่ C# args[0] คือ argument แรก

Python

Python มีวิธีหลากหลายในการใช้ Command-Line Arguments เช่น sys.argv

โมดูล sys ให้ฟังก์ชันและตัวแปรที่ใช้เพื่อจัดการส่วนต่างๆ ของ Python runtime environment โมดูลนี้ให้การเข้าถึงตัวแปรบางตัวที่ใช้หรือบำรุงรักษาโดย Interpreter และฟังก์ชันที่โต้ตอบกับ Interpreter เช่นตัวแปร sys.argv ซึ่งเป็นโครงสร้างของ list แบบง่าย วัตถุประสงค์หลัก คือเป็น lists ของ Command-Line Arguments

sys.argv[0] คือชื่อของสคริปต์ Python

len(sys.argv) ระบุจำนวน arguments ที่โปรแกรมรับเข้ามาจะรวมถึงชื่อไฟล์สคริปต์ด้วย

  • การนำเข้า: Python ต้องนำเข้า sys โมดูล ในขณะที่ C# ใช้พารามิเตอร์ใน Main

  • การประกาศ: Python ไม่มีการประกาศ main เฉพาะ ขณะที่ C# ต้องมีเมธอด Main

  • การจัดการ: Python ใช้ sys.argv ซึ่งเป็นลิสต์เพื่อเก็บ arguments ขณะที่ C# ใช้ string[] args

  • index ของ argument แรก: Python sys.argv[0] คือชื่อของสคริปต์ Python แต่ C# args[0] คือ argument แรก

Code ของแต่ละภาษา

//Test.cs
using System;

class Test {
    public static void Main(string[] args) {
        // แสดงจำนวน arguments
        Console.WriteLine("Total arguments: " + args.Length);
        
        // แสดงแต่ละ argument
        for (int i = 0; i < args.Length; i++) {
            Console.WriteLine("Argument " + i + ": " + args[i]);
        }
    }
}

วิธีการส่งค่า argument ผ่านทาง command line ของแต่ละภาษา

  1. เปิด Command Prompt หรือ Terminal ในโฟลเดอร์ที่มีไฟล์ Test.cs

  2. compile โปรแกรมด้วยคำสั่ง dotnet build

  3. รันโปรแกรมด้วยคำสั่ง dotnet run พร้อมระบุ argument ที่จะส่งไป

Input :

dotnet run a b c 1 2 3 4.0 def

Output

Total arguments: 8
Argument 0: a
Argument 1: b
Argument 2: c
Argument 3: 1
Argument 4: 2
Argument 5: 3
Argument 6: 4.0
Argument 7: def

ตารางเปรียบเทียบการใช้งาน command-line arguments ในภาษา C#, Java, C, และ Python

หัวข้อ
C#
Java
C
Python

พารามิเตอร์ในเมธอด Main

static void Main(string[] args)

public static void main(String[] args)

int main(int argc, char *argv[])

import sys

ชนิดของ arguments

string[] args (อาร์เรย์ของ string)

String[] args (อาร์เรย์ของ string)

char *argv[] (อาร์เรย์ของ string) + int argc (จำนวน arguments)

sys.argv (ลิสต์ของ string)

การเข้าถึง arguments

args[i]

args[i]

argv[i]

sys.argv[i]

จำนวนของ arguments

args.Length

args.length

argc

len(sys.argv)

index ของ argument แรก

args[0] (argument แรก ไม่มีชื่อโปรแกรม)

args[0] (argument แรก ไม่มีชื่อโปรแกรม)

argv[1] (argument แรก, argv[0] คือชื่อโปรแกรม)

sys.argv[1] (argument แรก, sys.argv[0] คือชื่อสคริปต์)

จำนวนของ arguments ในการรัน command line

dotnet run -- arg1 arg2 ...

java Test arg1 arg2 ...

Test.exe arg1 arg2 ...

python Test.py arg1 arg2 ...

Slides

References

เนื้อหาและตัวอย่างของภาษา C#

ตัวอย่างที่ใช้ในการเปรียบเทียบของแต่ละภาษา:

น.ท.ไพศาล โมลิสกุลมงคล. (ตุลาคม 2545). Microsoft Visual C#.NET. กรุงเทพฯ: หจก.ไทยเจริญการพิมพ์.

เนื้อหาและตัวอย่างที่ 2 ใน C#:

BillWagner. (2024, June 22). Main() and command-line arguments - C#. Microsoft Learn. https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line

เนื้อหาเพิ่มเติม:

GeeksforGeeks. (2019, February 26). C# | Command Line Arguments. GeeksforGeeks. https://www.geeksforgeeks.org/c-sharp-command-line-arguments/

ตัวอย่างที่ 1 ใน C#:

Tutorials, D. N. (2022, August 9). Command Line Arguments in C# with Examples - Dot Net Tutorials. Dot Net Tutorials. https://dotnettutorials.net/lesson/command-line-arguments-in-csharp/

เนื้อหาการเปรียบเทียบกับภาษา Java, C, Python

Java:

GeeksforGeeks. (2023, May 20). Command line arguments in Java. GeeksforGeeks. https://www.geeksforgeeks.org/command-line-arguments-in-java/

C:

Command line arguments in C. (n.d.). https://www.tutorialspoint.com/cprogramming/c_command_line_arguments.htm

Python:

GeeksforGeeks. (2024, June 20). Command line arguments in Python. GeeksforGeeks. https://www.geeksforgeeks.org/command-line-arguments-in-python/

Last updated