Problem: When I move files to trash from other partition, they move to home's directory.
Example: Remove files /mnt/sdd1/test. "test" was moved to ~/.local/share/Trash/files/test.
Solution:
1. Make directory on top level of mounted partition named ".Trash-$uid" (ex. Trash-1000) with read/write permission.
2. Or change mounted directory's permission to 777
2015/01/11
2011/12/03
.NET Framework - ListView
สวัสดีท่านผู้อ่านทุกท่านครับ
ผมได้สร้าง ListView ขึ้นมาหนึ่งตัว แล้วตั้งชื่อว่า listView แล้วกำหนด Column ไว้ 3 ตัว คือ No., Name และ Uri และกำหนดค่าที่อ่านใน Binding
เสร็จแล้วก็มาเขียนโค้ดคำสั่งกันครับ
ก่อนอื่นเลยก็เพิ่ม namespace System.Collections.ObjectModel ด้วยนะครับ
WebListItem เป็น class ที่สร้างขึ้นมาเพื่อเก็บข้อมูล แล้วก็ต้องตั้งชื่อ property ให้ตรงกับที่เขียนใน Binding ด้วยนะครับ
หลังจากนั้นก็สร้าง ObservableCollection<WebListItem> สำหรับเก็บค่าขึ้นมา แล้วกำหนดให้ listView ของเราดึงข้อมูลจาก collection ที่เราสร้าง
เป็นยังไงบ้างครับ ใช้ไม่ยากเลยใช่ไหมหล่ะครับ
วันนี้ผมจะมาแนะนำวิธีใช้ ListView ซึ่งเป็น Control ตัวหนึ่งใน WPF ครับ
ก่อนอื่นเลยก็ต้องสร้าง Project ใหม่ เป็น WPF
แล้วก็มาเขียนโค้ด XAML กันเลย~
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <ListView x:Name="listView"> <ListView.View> <GridView> <GridViewColumn Header="No." Width="Auto" DisplayMemberBinding="{Binding No}" /> <GridViewColumn Header="Name" Width="180" DisplayMemberBinding="{Binding Name}"/> <GridViewColumn Header="Uri" Width="250" DisplayMemberBinding="{Binding Uri}"/> </GridView> </ListView.View> </ListView> </Grid> </Window>
ผมได้สร้าง ListView ขึ้นมาหนึ่งตัว แล้วตั้งชื่อว่า listView แล้วกำหนด Column ไว้ 3 ตัว คือ No., Name และ Uri และกำหนดค่าที่อ่านใน Binding
เสร็จแล้วก็มาเขียนโค้ดคำสั่งกันครับ
ก่อนอื่นเลยก็เพิ่ม namespace System.Collections.ObjectModel ด้วยนะครับ
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; namespace WpfApplication1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { ObservableCollection<WebListItem> WebCollection = new ObservableCollection<WebListItem>(); public MainWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); } void MainWindow_Loaded(object sender, RoutedEventArgs e) { listView.ItemsSource = WebCollection; WebCollection.Add(new WebListItem { No = 1, Name = "Google", Uri = new Uri("http://www.google.com") } ); WebCollection.Add(new WebListItem { No = 2, Name = "Google+", Uri = new Uri("http://plus.google.com") }); WebCollection.Add(new WebListItem { No = 3, Name = "Gmail", Uri = new Uri("http://mail.google.com") }); WebCollection.Add(new WebListItem { No = 4, Name = "Facebook", Uri = new Uri("http://www.facebook.com") }); WebCollection.Add(new WebListItem { No = 5, Name = "MSDN", Uri = new Uri("http://msdn.microsoft.com") }); } } class WebListItem { public int No { get; set; } public string Name { get; set; } public Uri Uri { get; set; } } }
WebListItem เป็น class ที่สร้างขึ้นมาเพื่อเก็บข้อมูล แล้วก็ต้องตั้งชื่อ property ให้ตรงกับที่เขียนใน Binding ด้วยนะครับ
หลังจากนั้นก็สร้าง ObservableCollection<WebListItem> สำหรับเก็บค่าขึ้นมา แล้วกำหนดให้ listView ของเราดึงข้อมูลจาก collection ที่เราสร้าง
เป็นยังไงบ้างครับ ใช้ไม่ยากเลยใช่ไหมหล่ะครับ
2011/12/02
.NET Framework - Memory Leak เวลาใช้ System.Windows.Controls.Image
สวัสดีครับ เมื่อไม่กี่วันมานี้ผมเจอปัญหา Memory Leak ตอนใช้ System.Windows.Controls.Image ใน WPF มาครับ มาดูกันว่าผมทำยังไงมันถึงเกิดปัญหาขึ้น
ปัญหามีอยู่ว่า ผมโหลดภาพด้วย BitmapImage จำนวน 10 ภาพแล้วแสดงผลด้วย Image และผมต้องการที่จะลบภาพออก ปรากฏว่าเกิด Memory Leak ขึ้น โปรแกรมผมกิน Ram ไป เท่ากับตอนที่โหลดภาพ 10 ภาพ
เพื่อความสะดวกผมจะขอโหลดภาพขึ้นมาแค่ภาพเดียว เป็นไฟล์ png ขนาด 5.27MB ความละเอียด 1810x4034
Code ข้างบนนี้เกิด Memory Leak
ผมลองเอา
ออกปรากฏว่าปัญหา Memory Leak หายไป แต่ตัว Image ยังจองพื้นที่ใน Window อยู่จึงต้องกำหนดความกว้างกับความสูงเป็น 0 แทน
เท่านี้ก็ช่วยลด Memory ที่ใช้แล้ว ถึงจะลดได้ไม่หมด แม้ว่าจะลบ Image ออก แล้วใช้ GC.Collect() หน่วยความจำก็ไม่กลับคืนมาทั้งหมด
จะเห็นว่าตอนเปิดโปรแกรมใหม่ ๆ ใช้ Ram 14,596K
พอโหลดภาพมาแสดงใช้ Ram 72,984K
พอลบภาพออกจะใช้ Ram ลดลงเหลือ 45,032K
ตอนนี้ผมก็ยังไม่รู้จะแก้ได้ยังไง
ปัญหามีอยู่ว่า ผมโหลดภาพด้วย BitmapImage จำนวน 10 ภาพแล้วแสดงผลด้วย Image และผมต้องการที่จะลบภาพออก ปรากฏว่าเกิด Memory Leak ขึ้น โปรแกรมผมกิน Ram ไป เท่ากับตอนที่โหลดภาพ 10 ภาพ
เพื่อความสะดวกผมจะขอโหลดภาพขึ้นมาแค่ภาพเดียว เป็นไฟล์ png ขนาด 5.27MB ความละเอียด 1810x4034
public partial class MainWindow : Window { Image img; public MainWindow() { InitializeComponent(); img = new Image(); stackPanel1.Children.Add(img); } private void button1_Click(object sender, RoutedEventArgs e) { var bi = new BitmapImage(); bi.BeginInit(); bi.UriSource = new Uri(@"H:\img.png"); bi.EndInit(); if (bi.CanFreeze) bi.Freeze(); img.Width = bi.PixelWidth; img.Height = bi.PixelHeight; img.Source = bi; bi = null; img.Visibility = System.Windows.Visibility.Visible; } private void button2_Click(object sender, RoutedEventArgs e) { img.Source = null; img.Visibility = System.Windows.Visibility.Collapsed; } }
Code ข้างบนนี้เกิด Memory Leak
ผมลองเอา
img.Visibility = System.Windows.Visibility.Collapsed;
ออกปรากฏว่าปัญหา Memory Leak หายไป แต่ตัว Image ยังจองพื้นที่ใน Window อยู่จึงต้องกำหนดความกว้างกับความสูงเป็น 0 แทน
private void button2_Click(object sender, RoutedEventArgs e) { img.Source = null; img.Width = img.Height = 0.0; }
เท่านี้ก็ช่วยลด Memory ที่ใช้แล้ว ถึงจะลดได้ไม่หมด แม้ว่าจะลบ Image ออก แล้วใช้ GC.Collect() หน่วยความจำก็ไม่กลับคืนมาทั้งหมด
จะเห็นว่าตอนเปิดโปรแกรมใหม่ ๆ ใช้ Ram 14,596K
พอโหลดภาพมาแสดงใช้ Ram 72,984K
พอลบภาพออกจะใช้ Ram ลดลงเหลือ 45,032K
ตอนนี้ผมก็ยังไม่รู้จะแก้ได้ยังไง
2011/11/16
.NET Framework - #2 Windows Application
สวัสดีครับ เป็นยังไงกันบ้างครับ
วันนี้เราจะมาสร้าง Form ใน Windows กันครับ
เหมือนเดิมนะครับ ให้สร้าง Project เปล่า ๆ ขึ้นมา แล้วก็เพิ่ม References 3 ตัวคือ System, System.Drawing และ System.Windows.Forms
สำหรับ C++/CLI ให้เพิ่มตรง Project Properties นะครับ
F#, C#, VB.NET ก็เพิ่มตรง References ได้เลยครับ
แล้วก็ไปตั้งค่าอีกนิดนึงครับ
C#, VB.NET, F# ให้เข้าไปที่ Project Properties แล้วตั้ง Output type เป็น Windows Application
ส่วน C++/CLI ให้เข้าไปที่ Project Properties, ในส่วนของ Linker ตรง System เปลี่ยน SubSystem เป็น Windows และตรง Advanced เปลี่ยน Entry Point เป็น main
ตั้งค่าเสร็จแล้ว ก็มาเขียนโค้ดกันเลยครับ~~~~!!!
C++/CLI
using namespace System; using namespace System::Drawing; using namespace System::Windows::Forms; [STAThread] int main() { Form ^f = gcnew Form(); f->Text = "C++/CLI Form"; Application::Run(f); return 0; }
C#
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Form f = new Form(); f.Text = "C# Form"; Application.Run(f); } }
VB.NET
Option Strict On Option Explicit On Imports System Imports System.Drawing Imports System.Windows.Forms Module Program <STAThread> Sub Main() Dim f As New Form() f.Text = "VB.NET Form" Application.Run(f) End Sub End Module
F#
open System open System.Drawing open System.Windows.Forms [<STAThread>] let f = new Form(Text = "F# Form") Application.Run(f)
เป็นยังไงกันบ้างครับ เห็นไหมครับว่าภาษา .NET เหมือนกันโค้ดแทบไม่ต่างกันเลย ต่างกันแค่ไวยากรณ์ของภาษานั้น ๆ
วันนี้ก็เอาไว้เท่านี้นะครับ ขอให้สนุกกับการเขียนโปรแกรมครับผม ^w^
(โปรแกรมที่ผมใช้วันนี้คือ Visual Studio 11 Developer Preview นะครับ)
2011/11/11
F# - #3
สวัสดีครับ วันนี้เราก็มาฝึกเขียนภาษา F# กันเหมือนเดิมนะครับ
ก่อนอื่นผมจะขอพูดเกี่ยวกับฟังก์ชันอีกหน่อยนะครับ
คราวนี้ให้เปิดตัว F# Interactive (Console) นะครับ
แล้วลองพิมพ์ลงไปว่า
จะเห็นว่า f กับ g จะไม่เหมือนกัน
ลองมาดูที่ฟังก์ชัน f กันก่อน
val f : int -> int -> int
หมายถึง f จะรับค่า int 2 ตัว แล้วส่งค่า int กลับมา
ส่วน g
val g : int * int -> int
หมายถึง g จะรับค่า int * int ที่เป็น tuple แล้วจะส่งค่า int กลับออกมา
คราวนี้เราลองมากำหนดชนิดของค่าที่รับเข้าไปกัน
val f : float -> float -> float
จะเห็นว่าผลลัพท์ (ค่าที่ฟังก์ชันส่งกลับมา) จะเปลี่ยนด้วย
คราวนี้เรากลับมาที่ Visual Studio กันนะครับ
วันนี้เราจะมาดูวิธีเขียนเงื่อนไขกัน
วิธีเขียนจะคล้าย ๆ Object Pascal กับ VB.NET
ส่วนเครื่องหมายจะมี
= เท่ากับ
< น้อยกว่า
> มากกว่า
<> ไม่เท่ากับ
แต่ถ้ามีหลายเงื่อนไข จะใช้ && (and) กับ || (or) เป็นตัวเชื่อม และ elif จะหมายถึง else if
คราวนี้มาดูวิธีตรวจสอบค่ากันบ้าง ที่ในภาษา C/C++, C# เป็น switch case แต่ใน F# จะใช้ match with
เครื่องหมาย | (pipe) จะเหมือนกับ case ในภาษา C#
| x when a > 3 หมายถึง ให้ค่าเป็น x ถ้า a > 3 หรือจะเขียนเป็น | x when x > 3 ก็ได้
| _ when a < -4 ไม่สามารถเขียนเป็น _ when _ < -4 ได้
นอกจากนี้ยังเขียนเป็น | x when x > 3 && x < 6 ได้อีกด้วย
ลองเขียนเคสอื่น ๆ ดูนะครับ
คราวนี้ลองมาดู resursive function (ฟังก์ชันเรียกตัวเอง) กันบ้าง
เราจะใช้ rec ต่อหลัง let เพื่อบอกว่า ฟังก์ชันที่จะสร้างเป็นฟังก์ชันแบบ recursive ครับ
ส่วน failwith หมายถึง ให้แสดง error ครับ ลองใส่ค่าติดลบดูก็ได้ครับ
ส่วนที่ต้องใส่วงเล็บ ตรง fac(n - 1) ก็เพราะว่า ถ้าเราเขียนเป็น n * fac n - 1 มันจะกลายเป็น n * fac(n) - 1
คราวนี้เราลองมารับค่ากันบ้างครับ
ก่อนอื่นเราต้องเรียก namespace System ขึ้นมาก่อน ด้วยคำสั่ง open เหมือนกับ using ใน C# และ Import ใน VB.NET
คราวนี้ถ้าจะรับข้อความเข้ามาทั้งบรรทัด
และเราจะแยกข้อความออกจากกันถ้าเจอเว้นวรรค
ตอนนี้เราจะได้ a เป็น array นะครับ จึงไม่สามารถใช้ %s กับ a ได้
จากตรงนี้ลองพิมพ์ข้อความลงไปว่า Hello World
เราจะได้ [|"Hello"; "World"|]
ซึ่งเราจะเขียนแบบนี้ตอนสร้าง array ครับ
สมาชิกแต่ละตัวจะใช้ ; (semi-colon) เป็นคั่น และใช้ [| |] ครอบ
แล้วถ้าต้องการรับค่าเข้ามาแล้วแปลงเป็น int หล่ะจะทำยังไง
เช่น ใส่ค่าเข้ามาว่า 1 6 12 จะให้รับเข้ามาเป็น array [|1; 6; 12|]
เราจะใช้คำสั่ง Array.map เข้ามาช่วย แล้วเขียนฟังก์ชันข้างใน
หรือจะเขียนว่า
ก็ได้
แล้วเจ้า |> (pipe + >) มันคืออะไร ?
เครื่องหมาย |> นิยามโดย
ลองดูกับฟังก์ชันง่าย ๆ
เราจะเขียนเป็น
ก็ได้ มีความหมายเหมือนกัน
เริ่มงงกันแล้วใช่ไหมครับ งั้นวันนี้พอแค่นี้ก่อนละกันครับ เดี๋ยวผมจะมาพูดเรื่อง Array อีกทีนะครับ
ก่อนอื่นผมจะขอพูดเกี่ยวกับฟังก์ชันอีกหน่อยนะครับ
คราวนี้ให้เปิดตัว F# Interactive (Console) นะครับ
แล้วลองพิมพ์ลงไปว่า
let f a b = a + b;;
let g(a, b) = a + b;;
จะเห็นว่า f กับ g จะไม่เหมือนกัน
ลองมาดูที่ฟังก์ชัน f กันก่อน
val f : int -> int -> int
หมายถึง f จะรับค่า int 2 ตัว แล้วส่งค่า int กลับมา
ส่วน g
val g : int * int -> int
หมายถึง g จะรับค่า int * int ที่เป็น tuple แล้วจะส่งค่า int กลับออกมา
คราวนี้เราลองมากำหนดชนิดของค่าที่รับเข้าไปกัน
let f (a : float) (b : float) = a + b;;
val f : float -> float -> float
จะเห็นว่าผลลัพท์ (ค่าที่ฟังก์ชันส่งกลับมา) จะเปลี่ยนด้วย
คราวนี้เรากลับมาที่ Visual Studio กันนะครับ
วันนี้เราจะมาดูวิธีเขียนเงื่อนไขกัน
let a = 10
if a < 20 then printfn "a < 20"
else printfn "a >= 20"
วิธีเขียนจะคล้าย ๆ Object Pascal กับ VB.NET
ส่วนเครื่องหมายจะมี
= เท่ากับ
< น้อยกว่า
> มากกว่า
<> ไม่เท่ากับ
แต่ถ้ามีหลายเงื่อนไข จะใช้ && (and) กับ || (or) เป็นตัวเชื่อม และ elif จะหมายถึง else if
let a = 10
if a < 20 && a >= 0 then printfn "0 <= a < 20"
elif a >= 20 then printfn "a >= 20"
else printfn "a < 0"
คราวนี้มาดูวิธีตรวจสอบค่ากันบ้าง ที่ในภาษา C/C++, C# เป็น switch case แต่ใน F# จะใช้ match with
let a = 4
match a with
| 0 -> printfn "Zero"
| 1 -> printfn "One"
| 2 | 3 -> printfn "2 or 3"
| x when a > 3 -> printfn "%i" x | _ when a < -4 -> printfn "< -4"
| _ -> printfn "Other"
เครื่องหมาย | (pipe) จะเหมือนกับ case ในภาษา C#
| x when a > 3 หมายถึง ให้ค่าเป็น x ถ้า a > 3 หรือจะเขียนเป็น | x when x > 3 ก็ได้
| _ when a < -4 ไม่สามารถเขียนเป็น _ when _ < -4 ได้
นอกจากนี้ยังเขียนเป็น | x when x > 3 && x < 6 ได้อีกด้วย
ลองเขียนเคสอื่น ๆ ดูนะครับ
คราวนี้ลองมาดู resursive function (ฟังก์ชันเรียกตัวเอง) กันบ้าง
let rec fac n = match n with | _ when n < 0 -> failwith "n must >= 0" | 0 | 1 -> 1 | _ -> n * fac(n - 1)
เราจะใช้ rec ต่อหลัง let เพื่อบอกว่า ฟังก์ชันที่จะสร้างเป็นฟังก์ชันแบบ recursive ครับ
ส่วน failwith หมายถึง ให้แสดง error ครับ ลองใส่ค่าติดลบดูก็ได้ครับ
ส่วนที่ต้องใส่วงเล็บ ตรง fac(n - 1) ก็เพราะว่า ถ้าเราเขียนเป็น n * fac n - 1 มันจะกลายเป็น n * fac(n) - 1
คราวนี้เราลองมารับค่ากันบ้างครับ
ก่อนอื่นเราต้องเรียก namespace System ขึ้นมาก่อน ด้วยคำสั่ง open เหมือนกับ using ใน C# และ Import ใน VB.NET
open System printf "Enter a number: "
let a = int(Console.ReadLine()) printfn "%i" a
คราวนี้ถ้าจะรับข้อความเข้ามาทั้งบรรทัด
open System printf "Enter a string: "
let a = Console.ReadLine() printfn "%s" a
และเราจะแยกข้อความออกจากกันถ้าเจอเว้นวรรค
open System printf "Enter a string: "
let a = Console.ReadLine().Split() printfn "%A" a
ตอนนี้เราจะได้ a เป็น array นะครับ จึงไม่สามารถใช้ %s กับ a ได้
จากตรงนี้ลองพิมพ์ข้อความลงไปว่า Hello World
เราจะได้ [|"Hello"; "World"|]
ซึ่งเราจะเขียนแบบนี้ตอนสร้าง array ครับ
let a = [|1; 2; 3; 4|] printfn "%A" a
สมาชิกแต่ละตัวจะใช้ ; (semi-colon) เป็นคั่น และใช้ [| |] ครอบ
แล้วถ้าต้องการรับค่าเข้ามาแล้วแปลงเป็น int หล่ะจะทำยังไง
เช่น ใส่ค่าเข้ามาว่า 1 6 12 จะให้รับเข้ามาเป็น array [|1; 6; 12|]
open System printf "Enter a string: "
let a = Array.map(fun x -> int x) (Console.ReadLine().Split()) printfn "%A" a
เราจะใช้คำสั่ง Array.map เข้ามาช่วย แล้วเขียนฟังก์ชันข้างใน
หรือจะเขียนว่า
let a = Console.ReadLine().Split() |> Array.map(fun x -> int x)
ก็ได้
แล้วเจ้า |> (pipe + >) มันคืออะไร ?
เครื่องหมาย |> นิยามโดย
let (|>) x f = f x
ลองดูกับฟังก์ชันง่าย ๆ
open System let a = Math.Cos 5.0 printfn "%f" a
เราจะเขียนเป็น
let a = 5.0 |> Math.Cos
ก็ได้ มีความหมายเหมือนกัน
เริ่มงงกันแล้วใช่ไหมครับ งั้นวันนี้พอแค่นี้ก่อนละกันครับ เดี๋ยวผมจะมาพูดเรื่อง Array อีกทีนะครับ
2011/11/10
F# - #2
สวัสดีครับ วันนี้เราจะมาฝึกเขียนภาษา F# กันอีกเช่นเคย แต่จะเป็นเรื่องอะไร ลองทายดูสิครับ
...
วันนี้เราจะมาเขียนฟังก์ชันกันครับ !!!!
อ่านถูกแล้วหล่ะครับ มันคือฟังก์ชัน นั้นแหละครับ
บางคนอาจจะงง ยังไม่ทันไรก็ขึ้นฟังก์ชันแล้ว ?
จริง ๆ แล้วฟังก์ชันในภาษา F# นั้นสร้างไม่ยากเลยครับ เพราะว่าใช้คำสั่ง let เหมือนกัน
เหมือนกันเลยครับ แต่ต้องใส่ () ต่อท้ายเท่านั้นเอง เราก็จะได้ myFun เป็นฟังก์ชันแล้ว... เย้
ต่อไปมาลองสร้างฟังก์ชันที่มีการรับค่าเข้าไปดูครับ
เป็นยังไงบ้างครับ ง่ายใช่ไหมหล่ะครับ
แล้วถ้าฟังก์ชันมีหลายบรรทัดหล่ะ จะเขียนยังไงดี ?
ก่อนอืนเลยต้องบอกว่า scope ใน F# จะใช้ย่อหน้าครับ เช่นในภาษา C/C++, C# จะเป็น { } ใน Object Pascal เป็น begin end; เป็นต้น
จะเห็นว่าคำสั่งที่อยู่ในย่อหน้า ตั้งแต่ let r1 จนถึง r2 จะเป็นคำสั่งในฟังก์ชัน f ครับ
ลองมาดูกันทีละบรรทัดนะครับ
หมายถึง สร้างฟังก์ชัน f ที่รับค่า x เข้าไป
คือการสร้างค่าคงที่ ที่อยู่ในฟังก์ชันครับ เพราะฉะนั้นเราจึงใช้ r1 กับ r2 ได้แค่ในฟังก์ชัน f เท่านั้น
คือการส่งค่ากลับออกมาให้ฟังก์ชันครับ คล้าย ๆ กับ return r2; ในภาษา C/C++, C# ฯลฯ
นอกจากนี้เรายังสามารถประกาศค่าคงที่ ที่ชื่อซ้ำกันในฟังก์ชันได้อีกด้วย
คำสั่งนี้จะเหมือนกับคำสั่งก่อนหน้านี้เลยครับ
จริง ๆ แล้วเราจะใส่วงเล็บตอนประกาศฟังก์ชันหรือตอนเรียใช้ก็ได้นะครับ
นอกจากนี้ยังสามารถใช้ชื่อซ้ำกันใน scope ที่ซ้อนกันได้
จะเห็นว่าตำสั่ง r + 1 จะหมายถึง r ที่เป็น x * x และ r * 2 จะหมายถึง r ตัวแรกที่อยู่หลัง let f x
Tuple คืออะไร ? http://en.wikipedia.org/wiki/Tuple
ลองดูตัวอย่างกันดีกว่าครับ
เราจะได้ a = 1 และ b = 2 ครับ คิดว่าดูจากตัวอย่างแล้วน่าจะเข้าใจนะครับ
คราวนี้
ลองรันดูนะครับ แล้วดูว่า a คืออะไร ?
ถ้ารันดูแล้วจะรู้ว่า a จะเท่ากับ (1, 2)
แล้วจะเอาค่าออกมายังไงหล่ะ ?
เราจะใช้ฟังก์ชัน fst เพื่อเอาค่าของตัวแรกออกมา และใช้ snd เพื่อเอาค่าตัวหลังออกมา ซึ่งฟังก์ชันทั้ง 2 ตัวนี้มีอยู่แล้วครับ แต่ถ้าใครจะเขียนเองก็ไม่ยากครับ
แต่ต้องใส่วงเล็บด้วยนะครับ จะเขียนเป็น fst a b ไม่ได้ เพราะ (a, b) มันคือ tuple ไงครับ
ลองดูตัวอย่างกันอีกหน่อย
เราไม่สามารถเขียนแบบนี้ได้นะครับ เพราะ f จะต้องรับค่าเข้าไป 2 ค่า แต่ (4, 5) มันคือ ค่าเดียวครับ
จึงต้องเขียนเป็นแบบนี้
และแน่นอนครับว่าแบบข้างล่างนี้ก็ใช้ไม่ได้
เพราะว่า f รับค่าเข้าไปแค่ค่าเดียว คือข้อมูลแบบ tuple (a, b) แต่ f 4 5 หมายถึง ส่ง 4 กับ 5 เข้าไปให้ f
ต่อไปมาดูการละค่ากันครับ
จะได้ x = 1 ครับ เครื่องหมาย _ (underscore) หมายถึงละค่าครับ เพราะฉะนั้นเลข 2 จังไม่ถูกเก็บเข้ามา
และ _ ไม่สามารถตั้งเป็นชื่อได้ เราจึงไม่สามารถ printfn "%A" _ ได้ครับ
...
วันนี้เราจะมาเขียนฟังก์ชันกันครับ !!!!
อ่านถูกแล้วหล่ะครับ มันคือฟังก์ชัน นั้นแหละครับ
บางคนอาจจะงง ยังไม่ทันไรก็ขึ้นฟังก์ชันแล้ว ?
จริง ๆ แล้วฟังก์ชันในภาษา F# นั้นสร้างไม่ยากเลยครับ เพราะว่าใช้คำสั่ง let เหมือนกัน
let myFun() = 5
let a = myFun() printfn "%A" a
เหมือนกันเลยครับ แต่ต้องใส่ () ต่อท้ายเท่านั้นเอง เราก็จะได้ myFun เป็นฟังก์ชันแล้ว... เย้
ต่อไปมาลองสร้างฟังก์ชันที่มีการรับค่าเข้าไปดูครับ
let add a b = a + b
let r = add 6 4 printfn "%A" r
เป็นยังไงบ้างครับ ง่ายใช่ไหมหล่ะครับ
แล้วถ้าฟังก์ชันมีหลายบรรทัดหล่ะ จะเขียนยังไงดี ?
ก่อนอืนเลยต้องบอกว่า scope ใน F# จะใช้ย่อหน้าครับ เช่นในภาษา C/C++, C# จะเป็น { } ใน Object Pascal เป็น begin end; เป็นต้น
let f x = let r1 = x * x let r2 = r1 + 20 r2 printfn "%A" (f 6)
จะเห็นว่าคำสั่งที่อยู่ในย่อหน้า ตั้งแต่ let r1 จนถึง r2 จะเป็นคำสั่งในฟังก์ชัน f ครับ
ลองมาดูกันทีละบรรทัดนะครับ
let f x =
หมายถึง สร้างฟังก์ชัน f ที่รับค่า x เข้าไป
let r1 = x * x let r2 = r1 + 20
คือการสร้างค่าคงที่ ที่อยู่ในฟังก์ชันครับ เพราะฉะนั้นเราจึงใช้ r1 กับ r2 ได้แค่ในฟังก์ชัน f เท่านั้น
r2
คือการส่งค่ากลับออกมาให้ฟังก์ชันครับ คล้าย ๆ กับ return r2; ในภาษา C/C++, C# ฯลฯ
นอกจากนี้เรายังสามารถประกาศค่าคงที่ ที่ชื่อซ้ำกันในฟังก์ชันได้อีกด้วย
let f x = let r = x * x let r = r + 20 r
คำสั่งนี้จะเหมือนกับคำสั่งก่อนหน้านี้เลยครับ
จริง ๆ แล้วเราจะใส่วงเล็บตอนประกาศฟังก์ชันหรือตอนเรียใช้ก็ได้นะครับ
let f(x) = let r = x * x let r = r + 20 r printfn "%A" (f(6))
นอกจากนี้ยังสามารถใช้ชื่อซ้ำกันใน scope ที่ซ้อนกันได้
let f x = let r = let r = x * x r + 1 r * 2 printfn "%A" (f 3)
จะเห็นว่าตำสั่ง r + 1 จะหมายถึง r ที่เป็น x * x และ r * 2 จะหมายถึง r ตัวแรกที่อยู่หลัง let f x
Tuple คืออะไร ? http://en.wikipedia.org/wiki/Tuple
ลองดูตัวอย่างกันดีกว่าครับ
let (a, b) = (1, 2) // หรือ let a, b = 1, 2
printfn "a = %A" a printfn "b = %A" b
เราจะได้ a = 1 และ b = 2 ครับ คิดว่าดูจากตัวอย่างแล้วน่าจะเข้าใจนะครับ
คราวนี้
let a = (1, 2) printfn "%A" a
ลองรันดูนะครับ แล้วดูว่า a คืออะไร ?
ถ้ารันดูแล้วจะรู้ว่า a จะเท่ากับ (1, 2)
แล้วจะเอาค่าออกมายังไงหล่ะ ?
let a = (1, 2)
let x = fst a
let y = snd a printfn "x = %A\ny = %A" x y
เราจะใช้ฟังก์ชัน fst เพื่อเอาค่าของตัวแรกออกมา และใช้ snd เพื่อเอาค่าตัวหลังออกมา ซึ่งฟังก์ชันทั้ง 2 ตัวนี้มีอยู่แล้วครับ แต่ถ้าใครจะเขียนเองก็ไม่ยากครับ
let fst(a, b) = a
let snd(a, b) = b
แต่ต้องใส่วงเล็บด้วยนะครับ จะเขียนเป็น fst a b ไม่ได้ เพราะ (a, b) มันคือ tuple ไงครับ
ลองดูตัวอย่างกันอีกหน่อย
let f a b = a + b
let x = f(4, 5) printfn "%A" x
เราไม่สามารถเขียนแบบนี้ได้นะครับ เพราะ f จะต้องรับค่าเข้าไป 2 ค่า แต่ (4, 5) มันคือ ค่าเดียวครับ
จึงต้องเขียนเป็นแบบนี้
let f(a, b) = a + b
let x = f(4, 5) printfn "%A" x
และแน่นอนครับว่าแบบข้างล่างนี้ก็ใช้ไม่ได้
let f(a, b) = a + b
let x = f 4 5 printfn "%A" x
เพราะว่า f รับค่าเข้าไปแค่ค่าเดียว คือข้อมูลแบบ tuple (a, b) แต่ f 4 5 หมายถึง ส่ง 4 กับ 5 เข้าไปให้ f
ต่อไปมาดูการละค่ากันครับ
let a = (1, 2)
let x, _ = a printfn "%A" x
จะได้ x = 1 ครับ เครื่องหมาย _ (underscore) หมายถึงละค่าครับ เพราะฉะนั้นเลข 2 จังไม่ถูกเก็บเข้ามา
และ _ ไม่สามารถตั้งเป็นชื่อได้ เราจึงไม่สามารถ printfn "%A" _ ได้ครับ
2011/11/09
F# - #1
สวัสดีครับ วันนี้เราจะมาหัดเขียนโปรแกรมในภาษา F# กันครับ
ภาษา F# คืออะไร ? ลองดูที่ wikipedia นะครับ http://en.wikipedia.org/wiki/F_Sharp_(programming_language)
ก่อนอื่นเลยเราต้องมาลงเจ้า Compiler กับ IDE กันก่อนนะครับ
ตัว Compiler โหลดได้จาก http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/ หรือถ้าหาไม่เจอก็เข้า http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=18706 ก็ได้ครับ
ส่วน IDE ก็ใช้ Visual Studio 2010 Shell ครับ http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=115
แล้วก็อย่าลืมลง .NET Framework ด้วยนะครับ http://www.microsoft.com/download/en/details.aspx?id=17851
เอาหล่ะ เราลองมาเขียนโปรแกรมแรกกันเลยดีกว่า ลองทายสิว่าโปรแกรมอะไร...
ใช่แล้ว มันก็คือ Hello World นั้นเอง
ก่อนอื่นเลยก็เปิดโปรแกรม Visual Studio 2010 Shell สร้าง Project ใหม่นะครับ เลือกที่ F# Application แล้วกด OK โล้ดดด
แล้วเราจะได้ source code เปล่า ๆ ที่ comment 1 บรรทัด เขียนไว้ว่า
จะลบทิ้งก็ได้นะครับ
สำหรับคนที่เคยเขียนภาษาอื่นมาก่อนเช่น C# หรือ VB.NET อาจจะตกใจเพราะว่าไม่เจอ code อะไรเลย ปกติใน C# หรือ VB.NET เมื่อสร้าง project ใหม่แล้วจะมี template มาให้
เอาละครับ เรามาเขียน code กันเลย
ง่าย ๆ สั้น ๆ ครับ ไม่ต้องสร้าง class ไม่ต้องสร้าง function อะไรเลย แค่พิมพ์ลงไปว่า
ไม่ต้องตกใจครับ แค่บรรทัดเดียวครับ "code มีแค่บรรทัดเดียว"
เสร็จลองรันดูนะครับ ถ้ารันแบบ Debug (F5) จะมีหน้าต่างดำ ๆ โผล่ออกมาแล้วหายไป ให้รันแบบไม่ใช้ Debug (Ctrl + F5) แทนนะครับ
เป็นยังไงบ้างครับ สั้นดีใช่ไหมหล่ะครับ
เอาหล่ะครับ เรามาสร้างค่าคงที่กันดีกว่าครับ...
แน่นอนครับ ว่ามันคือ "ค่าคงที่"
เราก็เจอกันไปแล้วในโปรแกรมที่เขียนกันเมื่อกี้ ก็คือ "Hello World" นี่แหละ มันคือค่าคงที่ชนิด String นี่แหละครับ
และ!! เราจะใช้คำสั่ง let (ให้) ในการตั้งชื่อให้กับค่าคงที่ครับ
เราจะได้ s เป็นค่าคงที่ ที่เก็บ "Hello World" เอาไว้
ซึ่งแน่นอนว่า s เป็นค่าคงที่ !! เราจึงไม่สามารถเปลี่ยนแปลงค่า s ได้
นี่คือแนวคิดแบบ functional programming ครับ หรือก็คือ ทุก ๆ อย่างนั้นเป็นค่าคงที่ รวมถึง function ด้วย
เราคงเคยเจอกันมาเยอะแล้ว..
เคยเจอมาเยอะแล้วจริง ๆ ครับ ในวิชาคณิตศาสตร์ยังไงหล่ะครับ เช่น ถ้า a = 10 แล้วเราก็ไม่สามารถเปลี่ยนค่า a ได้ถูกไหมครับ
แต่ F# ไม่ได้เป็น functional language ซะดีเดียว เราจึงสามารถเปลี่ยนแปลงค่าได้
เราจะใช้คำสั่ง mutable (ไม่แน่นอน) ต่อท้าย let ครับ เพื่อให้เราสามารถเปลี่ยนแปลงค่าได้
เราจะได้ a ที่แปลงร่างกลายเป็นตัวแปรแล้ว !
แต่ระวังอย่างหนึ่งนะครับ เครื่องหมาย = ไม่ใช่หมายถึง ให้ a = 6 ซะทีเดียว
เครื่องหมาย = คือเครื่องหมายกำหนดค่าให้ตั้งชื่อค่าคงที่ (ในคำสั่ง let) และเป็นเครื่องหมายทางตรรกศาสตร์
เช่นถ้าเราเจอ a = 4 โดยที่ไม่มี let แสดงว่า เครื่องหมาย = กำลังทำหน้าที่ตรวจสอบค่าว่า a เท่ากับ 4 รึเปล่า
เพราะฉะนั้นเราจึงไม่สมารถใช้ = เปลี่ยนค่าของ mutable ได้ แต่จะใช้เครื่องหมาย <- (น้อยกว่า + ขีด) แทน
และแน่นอนว่า ตอนนี้ a มีชนิดข้อมูลเป็น int (จำนวนเต็ม) เราไม่สามารถเปลี่ยนค่าให้กลายเป็นอย่างอื่นได้ เช่น
ทำไม่ได้แน่นอนครับ
แล้ว... %A คืออะไร ?
คนที่เคยเขียนภาษา C/C++ มาก่อนจะรู้ได้ทันทีเลยว่าคืออะไร (รึเปล่า)
มันก็คล้าย ๆ กับ %d %f ในภาษา C/C++ นั้นแหละ
แต่ %A จะดีกว่าหน่อยนึง ก็คือเราจะใส่ค่าอะไรลงไปก็ได้ เดี๋ยวมันจะเรียกฟังก์ชัน ToString() ของค่านั้น ๆ ออกมาให้
ภาษา F# คืออะไร ? ลองดูที่ wikipedia นะครับ http://en.wikipedia.org/wiki/F_Sharp_(programming_language)
ก่อนอื่นเลยเราต้องมาลงเจ้า Compiler กับ IDE กันก่อนนะครับ
ตัว Compiler โหลดได้จาก http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/ หรือถ้าหาไม่เจอก็เข้า http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=18706 ก็ได้ครับ
ส่วน IDE ก็ใช้ Visual Studio 2010 Shell ครับ http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=115
แล้วก็อย่าลืมลง .NET Framework ด้วยนะครับ http://www.microsoft.com/download/en/details.aspx?id=17851
เอาหล่ะ เราลองมาเขียนโปรแกรมแรกกันเลยดีกว่า ลองทายสิว่าโปรแกรมอะไร...
ใช่แล้ว มันก็คือ Hello World นั้นเอง
ก่อนอื่นเลยก็เปิดโปรแกรม Visual Studio 2010 Shell สร้าง Project ใหม่นะครับ เลือกที่ F# Application แล้วกด OK โล้ดดด
แล้วเราจะได้ source code เปล่า ๆ ที่ comment 1 บรรทัด เขียนไว้ว่า
// Learn more about F# at http://fsharp.net
จะลบทิ้งก็ได้นะครับ
สำหรับคนที่เคยเขียนภาษาอื่นมาก่อนเช่น C# หรือ VB.NET อาจจะตกใจเพราะว่าไม่เจอ code อะไรเลย ปกติใน C# หรือ VB.NET เมื่อสร้าง project ใหม่แล้วจะมี template มาให้
เอาละครับ เรามาเขียน code กันเลย
ง่าย ๆ สั้น ๆ ครับ ไม่ต้องสร้าง class ไม่ต้องสร้าง function อะไรเลย แค่พิมพ์ลงไปว่า
printfn "Hello World"
ไม่ต้องตกใจครับ แค่บรรทัดเดียวครับ "code มีแค่บรรทัดเดียว"
เสร็จลองรันดูนะครับ ถ้ารันแบบ Debug (F5) จะมีหน้าต่างดำ ๆ โผล่ออกมาแล้วหายไป ให้รันแบบไม่ใช้ Debug (Ctrl + F5) แทนนะครับ
เป็นยังไงบ้างครับ สั้นดีใช่ไหมหล่ะครับ
เอาหล่ะครับ เรามาสร้างค่าคงที่กันดีกว่าครับ...
แน่นอนครับ ว่ามันคือ "ค่าคงที่"
เราก็เจอกันไปแล้วในโปรแกรมที่เขียนกันเมื่อกี้ ก็คือ "Hello World" นี่แหละ มันคือค่าคงที่ชนิด String นี่แหละครับ
และ!! เราจะใช้คำสั่ง let (ให้) ในการตั้งชื่อให้กับค่าคงที่ครับ
let s = "Hello World"
เราจะได้ s เป็นค่าคงที่ ที่เก็บ "Hello World" เอาไว้
ซึ่งแน่นอนว่า s เป็นค่าคงที่ !! เราจึงไม่สามารถเปลี่ยนแปลงค่า s ได้
นี่คือแนวคิดแบบ functional programming ครับ หรือก็คือ ทุก ๆ อย่างนั้นเป็นค่าคงที่ รวมถึง function ด้วย
เราคงเคยเจอกันมาเยอะแล้ว..
เคยเจอมาเยอะแล้วจริง ๆ ครับ ในวิชาคณิตศาสตร์ยังไงหล่ะครับ เช่น ถ้า a = 10 แล้วเราก็ไม่สามารถเปลี่ยนค่า a ได้ถูกไหมครับ
แต่ F# ไม่ได้เป็น functional language ซะดีเดียว เราจึงสามารถเปลี่ยนแปลงค่าได้
เราจะใช้คำสั่ง mutable (ไม่แน่นอน) ต่อท้าย let ครับ เพื่อให้เราสามารถเปลี่ยนแปลงค่าได้
let mutable a = 6
เราจะได้ a ที่แปลงร่างกลายเป็นตัวแปรแล้ว !
แต่ระวังอย่างหนึ่งนะครับ เครื่องหมาย = ไม่ใช่หมายถึง ให้ a = 6 ซะทีเดียว
เครื่องหมาย = คือเครื่องหมายกำหนดค่าให้ตั้งชื่อค่าคงที่ (ในคำสั่ง let) และเป็นเครื่องหมายทางตรรกศาสตร์
เช่นถ้าเราเจอ a = 4 โดยที่ไม่มี let แสดงว่า เครื่องหมาย = กำลังทำหน้าที่ตรวจสอบค่าว่า a เท่ากับ 4 รึเปล่า
เพราะฉะนั้นเราจึงไม่สมารถใช้ = เปลี่ยนค่าของ mutable ได้ แต่จะใช้เครื่องหมาย <- (น้อยกว่า + ขีด) แทน
let mutable a = 6 printfn "%A" a a <- 10 printfn "%A" a
และแน่นอนว่า ตอนนี้ a มีชนิดข้อมูลเป็น int (จำนวนเต็ม) เราไม่สามารถเปลี่ยนค่าให้กลายเป็นอย่างอื่นได้ เช่น
a <- "Text"
a <- 3.2
ทำไม่ได้แน่นอนครับ
แล้ว... %A คืออะไร ?
คนที่เคยเขียนภาษา C/C++ มาก่อนจะรู้ได้ทันทีเลยว่าคืออะไร (รึเปล่า)
มันก็คล้าย ๆ กับ %d %f ในภาษา C/C++ นั้นแหละ
แต่ %A จะดีกว่าหน่อยนึง ก็คือเราจะใส่ค่าอะไรลงไปก็ได้ เดี๋ยวมันจะเรียกฟังก์ชัน ToString() ของค่านั้น ๆ ออกมาให้
2011/11/06
.NET Framework - #1 Hello World.
สวัสดีครับ หายหน้าหายตาไปนาน ลืมผมหรือยังครับเนี่ย ฮ่า ๆ ๆ
วันนี้เราจะมาเขียนโปรแกรมบน .NET Framework กันครับ จะใช้ภาษาอะไรเลือกกันตามสบายเลยครับ
.NET Framework คืออะไร ?
.NET Framework ก็คือ platform ที่พัฒนาโดย Microsoft เพื่อที่จะให้การพัฒนาโปรแกรมทำได้ง่ายขึ้น โดยที่เวลา compile ตัว compiler จะแปล code ในภาษาที่เราเขียนเป็นภาษากลาง เรียกว่า MSIL เวลาเรียกใช้โปรแกรมตัว CLR ใน .NET Framework จะแปล MSIL ให้เป็นภาษาเครื่องอีกที
ก่อนอื่นเลยต้องลงโปรแกรม Visual Studio 2010 ก่อนครับ จะใช้เวอร์ชัน Express หรือจะเป็นเวอร์ชันทดลองใช้ก็ได้ครับ โหลดได้ที่ http://www.microsoft.com/visualstudio/en-us
ผมขอใช้ Visual Studio 2010 Pro Trial นะครับ
ลงเสร็จแล้วเราลองมาเขียนโปรแกรมง่าย ๆ กันครับ
เป็นโปรแกรมแสดงข้อความคำว่า Hello World. ผ่าน Console
C++/CLI
สำหรับภาษา C++/CLI นะครับ ให้สร้าง Project เป็นแบบ CLR Empty Project นะครับ แล้วสร้างไฟล์ .cpp ขึ้นมาหนึ่งไฟล์ อาจจะตั้งชื่อว่า main.cpp ก็ได้
C#
ให้สร้าง Empty Project แล้วสร้าง Code ไฟล์ขึ้นมาใหม่นะครับ
VB
ให้สร้าง Empty Project แล้วสร้าง Code ขึ้นมาเหมือนกันครับ แล้วก็อย่าลืมไปตั้งใน Project Properties เปลี่ยนตรง Application type เป็น Console.Application ด้วยนะครับ
F#
วันนี้เราจะมาเขียนโปรแกรมบน .NET Framework กันครับ จะใช้ภาษาอะไรเลือกกันตามสบายเลยครับ
.NET Framework คืออะไร ?
.NET Framework ก็คือ platform ที่พัฒนาโดย Microsoft เพื่อที่จะให้การพัฒนาโปรแกรมทำได้ง่ายขึ้น โดยที่เวลา compile ตัว compiler จะแปล code ในภาษาที่เราเขียนเป็นภาษากลาง เรียกว่า MSIL เวลาเรียกใช้โปรแกรมตัว CLR ใน .NET Framework จะแปล MSIL ให้เป็นภาษาเครื่องอีกที
ก่อนอื่นเลยต้องลงโปรแกรม Visual Studio 2010 ก่อนครับ จะใช้เวอร์ชัน Express หรือจะเป็นเวอร์ชันทดลองใช้ก็ได้ครับ โหลดได้ที่ http://www.microsoft.com/visualstudio/en-us
ผมขอใช้ Visual Studio 2010 Pro Trial นะครับ
ลงเสร็จแล้วเราลองมาเขียนโปรแกรมง่าย ๆ กันครับ
เป็นโปรแกรมแสดงข้อความคำว่า Hello World. ผ่าน Console
C++/CLI
สำหรับภาษา C++/CLI นะครับ ให้สร้าง Project เป็นแบบ CLR Empty Project นะครับ แล้วสร้างไฟล์ .cpp ขึ้นมาหนึ่งไฟล์ อาจจะตั้งชื่อว่า main.cpp ก็ได้
using namespace System; int main() { Console::WriteLine("Hello World."); Console::ReadKey(); return 0; }
C#
ให้สร้าง Empty Project แล้วสร้าง Code ไฟล์ขึ้นมาใหม่นะครับ
using System; class Program { static void Main() { Console.WriteLine("Hello World."); Console.ReadKey(); } }
VB
ให้สร้าง Empty Project แล้วสร้าง Code ขึ้นมาเหมือนกันครับ แล้วก็อย่าลืมไปตั้งใน Project Properties เปลี่ยนตรง Application type เป็น Console.Application ด้วยนะครับ
Option Strict On Option Explicit On Imports System Module Program Sub Main() Console.WriteLine("Hello World.") Console.ReadKey() End Sub End Module
F#
สร้าง Project เป็นแบบ F# Application นะครับ
ในภาษา F# ผมขอใช้ printfn แทน Console.WriteLine นะครับ
ในภาษา F# ผมขอใช้ printfn แทน Console.WriteLine นะครับ
open System printfn "Hello World." Console.ReadKey() |> ignore
2011/10/04
C++ - String
สวัสดีผู้อ่านทุกท่านครับ วันนี้ผมจะมาแนะนำ class ตัวหนึ่ง ที่คิดว่าจะทำให้การเขียนโปรแกรมง่ายขึ้น
และเพื่อให้เข้าใจเรื่อง class มากขึ้น
class ที่ผมจะมาแนะนำให้รู้จักคือ string
class string ใน C++ ไม่เหมือนกับ string ใน ภาษา C
ในภาษา C ตัวแปร string คือแถวลำดับของ char
แต่ string ใน C++ จะจัดการกับหน่วยความจำให้กับเราเอง เราไม่ต้องไปยุ่งกับมัน
ก่อนอื่นเลย เราจะต้อง include ไฟล์ที่จำเป็นเข้ามาก่อน คือ
#include <string>
string อยู่ใน namespace std เวลาจะประกาศ object เราจะต้องข้ึนต้นด้วย std
std::string s;
หรือจะประกาศ using namespace std; ไว้เลยก็ได้
using namespace std;
string s;
ลองมาดูฟังก์ชันที่ใช้บ่อยใน string กัน
string::size()
string::length()
ทั้งสองฟังก์ชันนี้จะ return ค่าความยาวของข้อความออกมา
เช่น
s = "Test String";
cout << s.length() << endl;
จะได้ผลลัพท์คือ 11
string::max_size()
จะ return ค่าความยาวของข้อความทั้งหมดที่ string จะสามารถเก็บได้
string::resize(size_t n)
string::resize(size_t n, char c)
จะเป็นการเปลี่ยนขนาดของ string และถ้าเป็นการเพิ่มขนาด จะเอา c ไปต่อท้าย
แต่ถ้าไม่ได้ใส่ค่า c ค่า default คือ '\0'
s = "Test String";
s.resize(7); // s = "Test St"
s.resize(9, '_'); // s = "Test St__"
s.resize(12); // s = "Test St__"
string::clear()
เป็นการลบค่าใน string ออก
string::empty()
เป็นการตรวจสอบว่า string มีข้อมูลหรือไม่
string::at(size_t pos)
string::operator[]
คือ char ตัวที่ pos ของ string เช่น s[2]
string::operator+=
เป็นการต่อ string เช่น
s = "String1";
s += " String2";
// s = "String1 String2";
มีความหมายเหมือนกับ
s = s + " String2";
เป็นยังไงกันบ้างครับ string ใช้ง่ายใช่ไหมหล่ะ
เรามาต่อเรื่อง class กันดีกว่า
คราวนี้ผมจะพูดเรื่องการนำฟังก์ชันใน class ออกมาเขียนข้างนอก
จำได้ไหมครับ ว่า class เขียนยังไง ?
คราวนี้ผมจะเขียนแต่ prototype ของฟังก์ชัน
class triangle {
private:
float b, h;
public:
void setBase(float);
void setHight(float);
float getArea();
};
ผมจะนิยามฟังก์ชันข้างนอก ต้องใช้ เครื่องหมาย scope (::) ขั่นระหว่างชื่อ class กับชื่อฟังก์ชัน
หวังว่าบทความนี้จะมีประโยชน์สำหรับใครหลาย ๆ คน นะครับ
และเพื่อให้เข้าใจเรื่อง class มากขึ้น
class ที่ผมจะมาแนะนำให้รู้จักคือ string
class string ใน C++ ไม่เหมือนกับ string ใน ภาษา C
ในภาษา C ตัวแปร string คือแถวลำดับของ char
แต่ string ใน C++ จะจัดการกับหน่วยความจำให้กับเราเอง เราไม่ต้องไปยุ่งกับมัน
ก่อนอื่นเลย เราจะต้อง include ไฟล์ที่จำเป็นเข้ามาก่อน คือ
#include <string>
string อยู่ใน namespace std เวลาจะประกาศ object เราจะต้องข้ึนต้นด้วย std
std::string s;
หรือจะประกาศ using namespace std; ไว้เลยก็ได้
using namespace std;
string s;
ลองมาดูฟังก์ชันที่ใช้บ่อยใน string กัน
string::size()
string::length()
ทั้งสองฟังก์ชันนี้จะ return ค่าความยาวของข้อความออกมา
เช่น
s = "Test String";
cout << s.length() << endl;
จะได้ผลลัพท์คือ 11
string::max_size()
จะ return ค่าความยาวของข้อความทั้งหมดที่ string จะสามารถเก็บได้
string::resize(size_t n)
string::resize(size_t n, char c)
จะเป็นการเปลี่ยนขนาดของ string และถ้าเป็นการเพิ่มขนาด จะเอา c ไปต่อท้าย
แต่ถ้าไม่ได้ใส่ค่า c ค่า default คือ '\0'
s = "Test String";
s.resize(7); // s = "Test St"
s.resize(9, '_'); // s = "Test St__"
s.resize(12); // s = "Test St__"
string::clear()
เป็นการลบค่าใน string ออก
string::empty()
เป็นการตรวจสอบว่า string มีข้อมูลหรือไม่
string::at(size_t pos)
string::operator[]
คือ char ตัวที่ pos ของ string เช่น s[2]
string::operator+=
เป็นการต่อ string เช่น
s = "String1";
s += " String2";
// s = "String1 String2";
มีความหมายเหมือนกับ
s = s + " String2";
เป็นยังไงกันบ้างครับ string ใช้ง่ายใช่ไหมหล่ะ
เรามาต่อเรื่อง class กันดีกว่า
คราวนี้ผมจะพูดเรื่องการนำฟังก์ชันใน class ออกมาเขียนข้างนอก
จำได้ไหมครับ ว่า class เขียนยังไง ?
คราวนี้ผมจะเขียนแต่ prototype ของฟังก์ชัน
class triangle {
private:
float b, h;
public:
void setBase(float);
void setHight(float);
float getArea();
};
ผมจะนิยามฟังก์ชันข้างนอก ต้องใช้ เครื่องหมาย scope (::) ขั่นระหว่างชื่อ class กับชื่อฟังก์ชัน
void triangle::setBase(float base)
{
b = base;
}
void triangle::setHight(float hight)
{
h = hight;
}
float triangle::getArea()
{
return 0.5 * b * h;
}
ทำไมถึงต้องทำแบบนี้ ?
เพราะว่าถ้าในฟังก์ชันมีคำสั่งเยอะมาก จะทำให้เรามองภาพรวมของ class ยาก
ถ้าใน class มีแต่ prototype และตัวแปร เราจะมองเห็นภาพรวมง่ายขึ้น
หวังว่าบทความนี้จะมีประโยชน์สำหรับใครหลาย ๆ คน นะครับ
2011/10/03
C++ - Classes
จาก Data Structure ที่ผมได้กล่าวไปเมื่อคราวที่แล้ว ยังจำกันได้ไหมเอ่ย
Data Structure คือ กลุ่มของข้อมูลหลาย ๆ ชนิดมารวมอยู่ด้วยกัน
และ Class ก็เหมือน Structure คือกลุ่มของข้อมูลหลาย ๆ ชนิด แต่ยังมี Method อีกด้วย
สรุปคือ
Data Structure = Data
Class = Data + Methods
เพื่อความเข้าใจ ผมจะขอยกตัวอย่าง
ยังจำกันได้ไหมว่า structure ประกาศยังไง ?
struct human {
char name[255];
int age;
};
ถ้าเราต้องการที่จะประกาศ class เราก็แค่เปลี่ยนคำว่า struct เป็น class
class human {
char name[255];
int age;
};
เหมือนกันเลย แค่เปลี่ยนตัวหน้านิดเดียว
แต่ !! เมื่อเราสร้าง object (ตัวแปรของ class เราจะไม่เรียกว่าตัวแปร แต่จะเรียกว่า object แทน) ของ class human เราไม่สามารถที่จะเรียกสมาชิกในนั้นได้...
อย่างเช่น
human a;
เราจะไม่สามารถเรียก
a.name = "Name";
ได้ ทำไมถึงเป็นแบบนี้ ?
คำตอบคือ เพราะว่า class มีการปกป้องข้อมูลของตนเอง เพื่อจำกัดสิทธิ์ในการเข้าถึง
ในภาษา C++ รูปแบบสิทธิ์ของการเข้าถึงข้อมูลจะมี 3 แบบ (ใน Object Pascal มี 4 แบบ)
ได้แก่
- private
- public
- protected
เมื่อเราสร้างตัวแปรใน class แล้วไม่ได้กำหนดขอบเขตการเข้าถึง มันจะถูกกำหนดให้เป็น private โดยอัตโนมัติ
เมื่อขอบเขตถูกกำหนดเป็น private ตัวแปรนั้น ๆ จะไม่สามารถถูกเข้าถึงจากภายนอกได้ เราจึงไม่สามารถเรียก a.name ได้
ถ้าเราต้องการให้ตัวแปรนั้น ๆ สามารถถูกเรียกจากภายนอกได้ เราต้องกำหนดสิทธิ์เป็น public
เราจะได้หน้าตาของ class human แบบใหม่
class human {
public:
char name[255];
int age;
};
คราวนี้เราก็สามารถเรียก a.name ได้แล้ว
ถ้าเราต้องการกำหนดขอบเขตเป็น private ก็แค่ใส่ private: เข้าไป
ส่วน protected ผมขอยังไม่พูดถึงตอนนี้
แล้ว Method คืออะไร ?
ถ้าจะให้พูดง่าย ๆ เลย มันก็คือฟังก์ชันนั่นแหละ
ของดูตัวอย่าง class นี้
class triangle {
private:
float b, h;
public:
void setBase(float base)
{
b = base;
}
void setHight(float hight)
{
h = hight;
}
float getArea()
{
return 0.5 * b * h;
}
};
จะเห็นว่า เราไม่สามารถจะเรียกใช้ตัวแปร b กับ h ใน class นี้ได้
แต่เราสามารถเข้าถึงผ่านทาง function ที่อยู่ใน class แทน
ทำไมถึงต้องทำแบบนี้ ?
ก็เพราะ เพื่อไม่ให้ข้อมูลถูกแก้ไขตามใจชอบ สามารถป้องกันการเปลี่ยนข้อมูลแล้วเกิดข้อผิดพลาดได้อีกด้วย
เมื่อเราจะใช้เราก็เรียกผ่านฟังก์ชันพวกนี้ เช่น
triangle s;
s.setBase(4.2);
s.setHight(6.0);
cout << s.getArea() << endl;
class จะช่วยให้การเขียนโปรแกรมมีความยืดหยุดมากขึ้น
ยังเหลืออีกหลาย ๆ เรื่องเกี่ยวกับ class ที่ผมไม่ได้ยกมาพูดตอนนี้
แต่ผมจะมาพูดให้ฟังในคราวหน้า หวังว่าทุกท่านจะสนุกกับการสร้าง class นะครับ ^_^
C++ - Data Structures
เรารู้จักกลุ่มของข้อมูลชนิดเดียวกันมาแล้ว เรียกว่า array
คราวนี้ผมจะแนะนำให้รู้จักกลุ่มของข้อมูลต่างชนิดกัน ที่เรียกว่า Data Structure
Data Structure คือ กลุ่มของข้อมูลต่างชนิดกันเอามารวมไว้ด้วยกันและตั้งชื่อเพื่อใช้เรียก
ไวยากรณ์
struct structure_name {
type_1 member_1;
type_2 member_2;
...
type_n member_n;
};
ตัวอย่าง
struct human {
char name[255];
int age;
};
เวลาประกาศตัวแปรก็ประกาศเหมือนตัวแปรแบบปกติ
human a;
เวลาเรียกใช้เราจะใช้ . (จุด) เพื่อบอกข้อมูล member ของ structure นั้น
เช่น ถ้าเราจะเข้าถึงข้อมูลที่ชื่อ name ใน a เราจะใช้ a.name
a.name = "Name";
a.age = 5;
แล้วถ้าต้องการตัวแปร human หลาย ๆ ตัว เราก็สามารถสร้างเป็น array ได้
human b[20];
คือการประกาศตัวแปร array ของ human 20 ตัว
เมื่อเราสร้างตัวแปร structure ที่เป็น pointer
human *c = new human;
แล้วถ้าเราต้องการจะเข้าถึง member ของ c จะต้องเขียนยังไง ?
c.age = 5;
หรือ
*c.age = 5;
ทั้งสองแบบข้างบนเป็นวิธีที่ผิด
เราจะต้องนำค่าของ c ออกมาก่อนโดยการใช้ *c แล้วค่อยเข้าถึง member เราจึงต้องใส่ ( ) ครอบ *c
(*c).age = 5;
แต่ถ้าจะพิมพ์วงเล็บ แล้วใส่ * อีก ทำให้เสียเวลาพิมพ์มาก จึงมีสัญลักษณ์ตัวหนึ่งที่ใช้ลดรูป (*_) คือ ->
เราจึงสามารถเปลี่ยนได้เป็น
c->age = 5;
นอกจากนี้เรายังสามารถประกาศตัวแปรหลังจากประกาศ structure ได้เลย โดยการเขียนชื่อตัวแปรต่อท้ายก่อนเครื่องหมาย ;
struct human {
char name[255];
int age;
} a, b, c;
คือการประกาศตัวแปร a, b, c เป็น human
คราวนี้ผมจะแนะนำให้รู้จักกลุ่มของข้อมูลต่างชนิดกัน ที่เรียกว่า Data Structure
Data Structure คือ กลุ่มของข้อมูลต่างชนิดกันเอามารวมไว้ด้วยกันและตั้งชื่อเพื่อใช้เรียก
ไวยากรณ์
struct structure_name {
type_1 member_1;
type_2 member_2;
...
type_n member_n;
};
ตัวอย่าง
struct human {
char name[255];
int age;
};
เวลาประกาศตัวแปรก็ประกาศเหมือนตัวแปรแบบปกติ
human a;
เวลาเรียกใช้เราจะใช้ . (จุด) เพื่อบอกข้อมูล member ของ structure นั้น
เช่น ถ้าเราจะเข้าถึงข้อมูลที่ชื่อ name ใน a เราจะใช้ a.name
a.name = "Name";
a.age = 5;
แล้วถ้าต้องการตัวแปร human หลาย ๆ ตัว เราก็สามารถสร้างเป็น array ได้
human b[20];
คือการประกาศตัวแปร array ของ human 20 ตัว
เมื่อเราสร้างตัวแปร structure ที่เป็น pointer
human *c = new human;
แล้วถ้าเราต้องการจะเข้าถึง member ของ c จะต้องเขียนยังไง ?
c.age = 5;
หรือ
*c.age = 5;
ทั้งสองแบบข้างบนเป็นวิธีที่ผิด
เราจะต้องนำค่าของ c ออกมาก่อนโดยการใช้ *c แล้วค่อยเข้าถึง member เราจึงต้องใส่ ( ) ครอบ *c
(*c).age = 5;
แต่ถ้าจะพิมพ์วงเล็บ แล้วใส่ * อีก ทำให้เสียเวลาพิมพ์มาก จึงมีสัญลักษณ์ตัวหนึ่งที่ใช้ลดรูป (*_) คือ ->
เราจึงสามารถเปลี่ยนได้เป็น
c->age = 5;
นอกจากนี้เรายังสามารถประกาศตัวแปรหลังจากประกาศ structure ได้เลย โดยการเขียนชื่อตัวแปรต่อท้ายก่อนเครื่องหมาย ;
struct human {
char name[255];
int age;
} a, b, c;
คือการประกาศตัวแปร a, b, c เป็น human
2011/10/02
C++ - Pointer to Array
สวัสดีรอบสองของวันนี้ครับ
คราวนี้ผมจะมาเขียนเรื่องการใช้ Pointer เป็น Array
ปกติในภาษา C เวลาจะประกาศตัวแปรแบบ array เราจะประกาศเป็น
int a[5];
คือการประกาศตัวแปร a เป็น array ของ int มีสมาชิก 5 ตัว (0 - 4)
และเวลาที่เราจะประกาศ Pointer เราจะเขียนเป็น
int *b;
คือให้ b เป็น pointer ของ int
ในภาษา C ถ้าเราต้องการให้ pointer เป็น array เราจะต้องจองหน่วยความจำให้มันโดยใช้ฟังก์ชัน calloc
ถ้าจะให้ b เป็น array ที่มีสมาชิก 5 ตัวเราจะเขียนว่า
b = (int*)calloc(5, sizeof(int));
และจะใช้
คราวนี้ผมจะมาเขียนเรื่องการใช้ Pointer เป็น Array
ปกติในภาษา C เวลาจะประกาศตัวแปรแบบ array เราจะประกาศเป็น
int a[5];
คือการประกาศตัวแปร a เป็น array ของ int มีสมาชิก 5 ตัว (0 - 4)
และเวลาที่เราจะประกาศ Pointer เราจะเขียนเป็น
int *b;
คือให้ b เป็น pointer ของ int
ในภาษา C ถ้าเราต้องการให้ pointer เป็น array เราจะต้องจองหน่วยความจำให้มันโดยใช้ฟังก์ชัน calloc
void* calloc(size_t num, size_t size);
ถ้าจะให้ b เป็น array ที่มีสมาชิก 5 ตัวเราจะเขียนว่า
b = (int*)calloc(5, sizeof(int));
และจะใช้
void free(void*);
ในการลบข้อมูลที่จองออก
free(b)
ในภาษา C++ เราสามารถเขียนอีกแบบหนึ่งได้
เวลาจะประกาศตัวแปร int แต่ต้องการให้เป็น pointer เราจะใช้คำสั่ง new ในการจองหน่วยความจำ
int *c = new int;
และเราจะใช้ คำสั่ง delete ลบค่าออก
delete c;
แต่ถ้าต้องการให้ตัวแปรเป็นแบบ array เราจะใส่จำนวนสมาชิกลงไปด้วย
int *d = new int[5];
คือการประกาศให้ d เป็น array ที่มีสมาชิก 5 ตัว
เห็นไหมครับว่าง่ายกว่าภาษา C เยอะเลย
เวลาจะลบข้อมูลเราก็จะใช้
delete [] d;
แล้ว array สองมิติ จะสร้างยังไงดี ?
int **e = new int*[5];
for (int i = 0; i < 5; i++)
e[i] = new int[3];
คือการประกาศให้ e เป็น array ขนาด 5x3
จากตัวอย่างเราจะสังเกตได้ว่า เราไม่จำเป็นที่จะต้องประกาศ array เป็นสี่เหลี่ยมเสมอไป
เราอาจจะประกาศเป็นรูปอะไรก็ได้
int **f = new int*[3];
f[0] = new int[2];
f[1] = new int[3];
f[2] = new int;
Subscribe to:
Posts (Atom)













