12 May 2012

ลองเล่น AngularJS

เดือนก่อนเห็น @kobkrit แนะนำ AngularJS ที่พัฒนาโดย Google ไว้ใน Google+ ลองอ่านดูก็น่าสนใจ เป็น JavaScript framework แบบ MVC สำหรับสร้าง web application วันนี้ต้องเขียน script สำหรับสร้าง password ใหม่ให้กับระบบที่ดูแลอยู่ เลยค้นไม้คันมือลองใช้ AngularJS ดูหน่อย ทำแอพพลิเคชันแบบง่ายๆ ให้ใส่ username แล้วจะสร้าง password ให้พร้อมทั้งเขียน SQL statement สำหรับเอาไปใช้ update เลยเอา code มาแปะไว้เผื่อมีคนสนใจ ใช้ง่ายดีทีเดียว

ส่วนแรกเป็น HTML ทำหน้าที่เป็น view ใน MVC
<!doctype html>
<html ng-app>
 <head>
  <title>Password Generator</title>
  <script src="./angular-1.0.0rc8.min.js"></script>
  <script src="./pwdgen.js"></script>
  <style type="text/css">
   pre { border: 1px dotted black; }
  </style>
 </head>
 <body>
  <div ng-controller="PasswordCtrl">
   <form ng-submit="genPassword()">
    <label>Name</label>
    <input type="text" ng-model="fullname" 
      placeholder="Enter name">

    <label>User Name</label>
    <input type="text" ng-model="username" 
      placeholder="Enter user name">

    <input type="submit" value="generate">
   </form>
   <div>
    <label>Output</list>
    <pre>{{outputs.list}}</pre>
    <label>SQL</list>
    <pre>{{outputs.sql}}</pre>
   </div>
  </div>
 </body>
</html>

ส่วนที่สองเป็น JavaScript สำหรับทำหน้าที่เป็น controller วิธีสร้าง password ก็ง่ายๆ แค่กำหนดชุดตัวอักษรที่จะใช้ใน password พยายามตัวตัวที่กำกวมออก แล้วก็ random มาต่อกัน 6 ตัว เป็นอันเสร็จสิ้น
function PasswordCtrl($scope) {
 $scope.outputs = {
  sql: '\n',
  list: '\n'
 };

 $scope.genPassword = function() {
  var characters = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz';
  var passwd = '';
  if ($scope.outputs.sql == '\n') {
   $scope.outputs.sql = '';
   $scope.outputs.list = '';
  }
  for(i=0;i<6;i++) {
   var r = Math.floor(Math.random() * characters.length);
   passwd += characters[r];
  }
  
  $scope.outputs.list += $scope.fullname + '\t' +
    $scope.username + '\t' + passwd + '\n';
  $scope.outputs.sql += 'update faculties set password=MD5(\'' +
    passwd + '\') where username=\'' + $scope.username + '\';\n';  

  $scope.fullname = '';
  $scope.username = '';
 };
}

10 May 2012

คำสั่งและ Package ของ LaTeX ที่ใช้บ่อย (3) -- Tabular

Tabular เป็น environment มาตรฐานของ LaTeX สำหรับวาดตารางในเอกสาร วิธีใช้งานก็ไม่ยาก คือกำหนดรูปแบบการจัดข้อความในแต่ละคอลัมน์ไว้ แล้วก็เขียนเนื้อหาไปที่ละแถว รูปแบบของคอลัมน์แบบมาตรฐานที่เราใช้ได้คือ l คือ ชิดซ้าย, r คือ ชิดขวา, c คือ กึ่งกลาง, p{length} เมื่อต้องการ ตัวอย่างเช่น

\documentclass[12pt]{article}
\begin{document}
 \begin{tabular}{|c|c|c|}
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
 \end{tabular}
\end{document}


รวมคอลัมน์เข้าด้วยกัน

\multicolumn ใช้สำหรับรวมเซลล์หลายคอลัมน์เข้าเป็นเซลล์เดียว สามารถระบุการจัดตัวอักษรได้ด้วย รูปแบบคำสั่งคือ\multicolumn{#cells}{format}{content} โดย #cells คือจำนวนเซลล์ที่เราต้องการรวมเข้าด้วยกัน, format คือรูปแบบการจัดตัวอักษรชิดซ้าย กลาง หรือขวา และ content คือเนื้อหาของเซลล์ที่รวมกันแล้ว บางครั้งคำสั่ง \multicolumn นี้ก็ใช้สำหรับเปลี่ยนแบบรูปแบบการจัดตัวอักษรโดยไม่จำเป็นต้องรวมเซลล์ก็ได้ ตัวอย่างการใช้งาน

\documentclass[12pt]{article}
\begin{document}
 \begin{tabular}{|c|c|c|}
  \hline
  Hello & Hello & Hello \\
  \hline
  \multicolumn{2}{|c|}{Hello} & Hello \\
  \hline
  \multicolumn{3}{|c|}{Hello} \\
  \hline
 \end{tabular}
\end{document}


ลากเส้น

\hline ใช้สำหรับลากเส้นแนวนอน คั่นระหว่างแถว โดยคำสั่งนี้จะต้องใช้หลังจากเครื่องหมาย \\ ที่ระบุว่าหมดแถวแล้ว ถ้าต้องการขีดเส้นเฉพาะบางคอลัมน์ จะใช้คำสั่ง \cline{col1-col2} โดย LaTeX เริ่มนับคอลัมน์จากคอลัมน์ที่ 1 คำสั่ง \cline นี่จะใช้หลายๆ ครั้งในแถวเดียวกันได้ เพื่อให้เราสามารถขีดเส้นหลายช่วงได้ ตัวอย่างการใช้งาน

\documentclass[12pt]{article}

\begin{document}
 \begin{tabular}{|c|c|c|c|}
  \hline
  Hello & Hello & Hello & Hello \\
  \cline{1-2}
  Hello & Hello & Hello & Hello \\
  \cline{1-1}\cline{3-3}
  Hello & Hello & Hello & Hello \\
  \hline
 \end{tabular}
\end{document}


ยืดแถวให้สูงขึ้น

\arraystretch เป็นตัวกำหนดค่าสำหรับความสูงของแถว แต่ LaTeX จะกำหนดความสูงให้อัตโนมัติอยู่แล้ว การเปลี่ยนค่า \arraystretch จะกำหนดความสูงให้มากขึ้นหรือน้อยลง เป็นจำนวนเท่าของความสูงมาตรฐาน จะใช้คำสั่ง \renewcommand ในการเปลี่ยนแปลงค่านี้ เช่น การใช้คำสั่ง \renewcommand{\arraystretch}{1.5} ก่อนเริ่มตาราง จะทำให้ความสูงของแถวในตารางเป็นหนึ่งเท่าครึ่งของความสูงมาตรฐาน ตัวอย่างการใช้งาน

\documentclass[12pt]{article}

\begin{document}
 \begin{tabular}{|c|c|c|}
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
 \end{tabular}
 
 \vspace{5mm}

 {\renewcommand{\arraystretch}{2.0}
 \begin{tabular}{|c|c|c|}
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
 \end{tabular}}
\end{document}


เปลี่ยนระยะห่างขอบเซลล์

LaTeX กำหนดให้มีระยะห่างระหว่างเส้นแบ่งเซลล์กับเนื้อหาในเซลล์ไว้ขนาดหนึ่ง ซึ่งเราสามารถเปลี่ยนระยะห่างนี้ได้โดยใส่รูปแบบ @{} ระหว่างรูปแบบของแต่ละเซลล์ เช่น \begin{tabular}{|@{}l|r@{\hspace{1cm}} จะได้ตารางที่มีคอลัมน์แรกจัดข้อความเริ่มชิดเส้นขอบซ้ายของคอลัมน์โดยไม่มีช่องว่าง ส่วนคอลัมน์ที่
2 จัดข้อความชิดขวา แต่ห่าง 1cm จากเส้นขอบขวาของคอลัมน์ หลักการทำงานของ @{} ก็คือ คำสั่งที่ใช้กำหนดช่องว่างระหว่างคอลัมน์ จะถูกแทนที่ด้วยคำสั่งใดๆ ก็ตามที่อยู่ใน {} เราจึงกำหนดระยะห่างได้ตามต้องการ หรือจะใส่เครื่องหมายอะไรลงไปแทนก็ได้

\documentclass[12pt]{article}

\begin{document}
 \begin{tabular}{|@{}l|c|r@{\hspace{1cm}}|}
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
  Hello & Hello & Hello \\
  \hline
 \end{tabular}
\end{document}


วันนี้พอแค่นี้ก่อนดีกว่า เอาไว้ว่างๆ ค่อยเขียนใหม่

03 May 2012

คำสั่งและ Package ของ LaTeX ที่ใช้บ่อย (2)

Verbatim

ผมชอบใช้ package fancyvrb เวลาแทรก source code ลงในเอกสาร เพราะสามารถกำหนดรูปแบบได้ต่างๆ ได้ง่าย เช่น สามารถทำกรอบรอบรูป สามารถกำหนดหมายเลขบรรทัดได้



fancyvrb ใช้คำสั่ง \fvset สำหรับระบุรูปแบบของเนื้อหา ในตัวอย่าง frame=single คือกำหนดให้มีเส้นกรอบเป็นเส้นเดี่ยว numbers=left ให้แสดงเลขบรรทัดทางซ้าย tabsize=2 กำหนดขนาดของ tab เป็น 2 ตัวอักษร เสร็จแล้วเวลาจะแทรก code ก็ใช้ Verbatim environment ตามปกติ ส่วน gobble=1 หมายถึง ไม่ให้นับตัวอักษร 1 ตัวทางซ้ายของทุกบรรทัดเป็นส่วนหนึ่งของเนื้อหา ทำให้เราสามารถจัด indentation ของ LaTeX ได้ตามใจ ในกรณีตัวอักษรตัวแรกทางซ้ายจะไม่แสดงในเอกสารผลลัพธ์

ความสามารถอีกอย่างหนึ่งที่ผมชอบมากๆ ของ fancyvrb คือ สามารถดึงข้อความจาก source file ภายนอกมาใช้งานได้ด้วย ทำให้สะดวกในการทำเอกสารที่มี source code ที่ยังมีการแก้ไขอยู่ เช่น



คำสั่ง \VerbatimInput{hello.c} กำหนดให้เอาเนื้อหาของ hello.c มาแสดงใน Verbatim environment คำสั่งนี้ช่วยทำให้สะดวกในการจัดการเอกสาร เพราะเราสามารถแก้ไข source code และตรวจสอบ source code นั้นได้ตลอดเวลา แค่คอมไพล์ LaTeX ใหม่ เอกสารก็จะถูกต้องสวยงาม ไม่มีปัญหาว่าลืมเอา source code ที่แก้ไขแล้วมาแปะใหม่หรือยัง

จุดอ่อนของ fancyvrb มีอยู่ที่เดียวคือ ไม่มี syntax highlight แต่ผมไม่ได้สนใจมาก ถ้าจะให้มี syntax highlight คงต้องไปใช้ package อื่น เช่น listings ซึ่งผมไม่ค่อยรู้สึกว่ามันสวยเท่าไหร่

02 May 2012

คำสั่งและ Package ของ LaTeX ที่ใช้บ่อย (1)

วันนี้มาเขียนรวมคำสั่งและ package ที่ใช้เองบ่อยๆ ไว้ดีกว่า เอาไปหาเองได้ง่ายๆ

กำหนดขนาดกระดาษและระยะขอบ

ผมชอบใช้ geometry สำหรับกำหนดระยะขอบกระดาษ
\usepackage[hmargin=2in,vmargin=1in,a4paper]{geometry}
hmargin เอาไว้กำหนดระยะขอบซ้ายขวา ส่วน vmargin ใช้กำหนดระยะขอบบนล่างของกระดาษ

หัวท้ายกระดาษ

ผมใช้ fancyhdr สำหรับระบุหัวท้ายกระดาษ
\usepackage{fancyhdr}
\pagestyle{fancy}
\lhead{ITS336/ITS451 Artificial Intelligence}
\chead{}
\rhead{Academic Year 2011}
\lfoot{}
\cfoot{}
\rfoot{SIIT, Thammasat University}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}
วิธีใช้ก็ไม่ยาก \[lcr]head ใช้ระบุหัวกระดาษซ้าย กลาง ขวา ตามลำดับ ส่วน \[lcr]foot ใช้ระบุท้ายกระดาษ ส่วน \headrulewidth และ \footrulewidth ใช้ระบุให้มีเส้นคั่นระหว่างส่วนหัวท้ายกับเนื้อหาหลัก ถ้าไม่อยากให้มีก็กำหนดให้เป็น 0pt

กำหนดเลขหน้า

คำสั่ง \thepage เป็น counter สำหรับระบุเลขหน้าปัจจุบัน เช่น เราจะระบุเลขหน้าไว้กลางท้ายกระดาษด้วยคำสั่ง
\cfoot{\thepage}
ถ้าต้องการกำหนดเลขหน้าให้เป็นค่าอื่น ไม่เริ่มจากศูนย์ก็ใช้
\setcounter{page}{100}

วันนี้เอาแค่นี้ก่อนละกัน ยังไม่เรื่องฟอนท์อีก

27 April 2012

The Help

คืนนี้เปลี่ยนบรรยากาศมาเขียนเรื่องที่ไม่เกี่ยวกับภาษา C บ้างดีกว่า ที่พยายามเขียนเรื่องภาษา C เยอะ ก็เพราะเห็นว่ามันน่าจะมีประโยชน์กับหลายๆ คน แต่ผมก็อยากเขียนด้วยแหละ ผมเป็นพวกเห็นแก่ตัว ถ้าไม่อยากก็ไม่ทำหรอก ถ้าอยาก แล้วสิ่งที่มันไปพ้องกับประโยชน์คนอื่น ก็ถือว่าโชคดี



วันนี้จะเล่าเรื่องหนังชื่อ The Help ที่ @cutiening แนะนำให้ดู แล้วก็ไปเดินหาซื้ออยู่หลายร้านกว่าจะซื้อ DVD มาได้ หนังเรื่องนี้เป็นหนังฟอร์มเล็กๆ ไม่ค่อยดังเท่าไหร่ เล่าเรื่องราวของสังคมอเมริกันในยุคที่กฎหมายแบ่งแยกสีผิวยังใช้บังคับอยู่ ทำให้คนผิวดำมีสิทธิไม่เท่ากับคนผิวขาวที่อยู่ร่วมในสังคมเดียวกัน

หนังเล่าเรื่องของแม่บ้านผิวดำที่ทำงานรับใช้อยู่ในบ้านของคนผิวขาว ได้ค่าแรงค่อนข้างต่ำ ต้องปากกัดตีนถีบ ทำหน้าที่ทุกอย่างในบ้าน ตั้งแต่ทำอาหาร ทำความสะอาด และเลี้ยงลูกของคนผิวขาว แม่บ้านเหล่านี้โดนเหยียดผิวโดยนายจ้างตลอดเวลา เช่น คนผิวขาวรวมตัวกัน เสนอให้ออกกฎ ห้ามแม่บ้านผิวดำใช้ห้องส้วมร่วมกับนายจ้าง แม่บ้านผิวดำเหล่านี้จึงมีเรื่องคับแค้นใจอยู่เต็มไปหมด แต่ไม่สามารถแสดงออกได้เนื่องจากฎหมายห้ามเอาไว้

นางเอกของเรื่องนี้ชื่อ Skeeter เป็นสาวผิวขาวที่ได้เรียนหนังสือจนจบวิทยาลัย และสนใจอยากทำงานในสำนักพิมพ์ ด้วยความที่เธอถูกเลี้ยงมาโดยแม่บ้านผิวดำ โดยไม่ได้มีความรู้สึกเหยียดผิว เธอจึงสนใจที่จะเขียนหนังสือเกี่ยวกับเรื่องราวของแม่บ้านผิวดำ โดยจะต้องหลบๆ ซ่อนๆ และปกปิดตัวตนของแม่บ้านทั้งหมดไว้เป็นความลับ ไม่อย่างนั้นอาจจะถูกลงโทษ

ดูหนังเรื่องนี้แล้ว รู้สึกว่าหนังสะท้อนอะไรหลายๆ อย่างให้เราเห็น ทำให้รู้สึกเปรียบเทียบกลับมาที่สังคมไทย ซึ่งเราไม่มีสีผิวให้เหยียด แต่ก็มีอะไรให้เหยียดมากมาย อีกอย่างหนึ่งที่ได้จากหนังเรื่องนี้ คือ หนังทำให้รู้ว่า สำเนียงอเมริกันทางใต้นี่คล้ายกับสำเนียงอังกฤษอยู่พอควรเลย

26 April 2012

[C] จัดการ Source code หลายไฟล์ ตอนที่ 3

วันนี้มาเล่าต่อว่า จะทำยังไง ถ้าต้องการแลกเปลี่ยนข้อมูลระหว่างโปรแกรมที่เขียนแยกไว้หลายๆ ไฟล์ หรือต้องการมีตัวแปรแบบ global ที่สามารถเรียกค่าของตัวแปรจากฟังก์ชันหลายๆ ฟังก์ชันที่อยู่คนละไฟล์

ภาษา C ยอมให้ประกาศตัวแปรแบบ global โดยใช้ keyword "extern" เพื่อระบุว่ามีตัวแปรนี้อยู่แล้ว เพียงแต่อ้างถึงตัวแปรตัวเดียวกันนี้ที่ถูกประกาศไว้ที่อื่น ลองดูตัวอย่างโปรแกรมข้างล่างนี้

/* foo.c */
#include<stdio.h>
void func();
int i = 10;
main() {
 printf("i = %d\n", i);
 func();
 return 0;
}

/* bar.c */
#include<stdio.h>

extern int i;

void func() {
 printf("i = %d\n", i);
}

เมื่อคอมไพล์โปรแกรมนี้ gcc foo.c bar.c จะได้ผลเป็น

i = 10
i = 10

เพราะตัวแปร i ที่อ้างถึงทั้งในฟังก์ชัน main และ func เป็นตัวแปรเดียวกัน จึงแสดงค่า เท่ากับ 10 เหมือนกันทั้งสองบรรทัด มีข้อกำหนดเกี่ยวกับตัวแปร extern อีกเล็กน้อย คือ ตัวแปรที่ประกาศเป็น extern จะไม่สามารถกำหนดค่าเริ่มต้นให้ได้ เนื่องจากตัวแปรนั้นไม่ใช่ตัวแปรจริง เป็นแค่การอ้างถึงตัวแปรที่ประกาศไว้ที่อื่น

นอกจากนี้ถ้าประกาศตัวแปรแบบ extern นี้ไว้คนละไฟล์ โดยระบุ type ไม่เหมือนกัน คอมไพเลอร์จะไม่สามารถตรวจสอบ type ของตัวแปรว่าตรงกันได้ อาจจะทำให้การทำงานเพี้ยนไปได้ ซึ่งเป็นสิ่งที่ต้องระวัง ทางที่ดีเราจึงควรจะกำหนดตัวแปรแบบ extern ไว้ใน header file แล้วใช้แบบเดียวกันไปทุกที่

25 April 2012

[C] จัดการ Source code หลายไฟล์ ตอนที่ 2

ต่อจากตอนที่แล้ว ต้นเหตุที่ทำให้ได้ผลไม่ถูก ก็คือการไม่กำหนด function prototype ถ้าคอมไพล์โปรแกรมนี้ใหม่ แต่ใช้คำสั่งเป็น

$ gcc -Wall -o prog2 main2.c func2.c

จะมี warning มาเตือนว่าไม่ได้มีการกำหนด function prototype ของฟังก์ชัน sum

main2.c:7:2: warning: implicit declaration of function ‘sum’ [-Wimplicit-function-declaration]

เมื่อไม่ประกาศ function prototype เอาไว้ คอมไพเลอร์ก็จะไม่ตรวจสอบ type ของ argument ที่ส่งไปที่ฟังก์ชัน และไม่มีการแปลง type ให้ตรงกับที่ฟังก์ชันต้องการ ดังนั้นเมื่อเรียกใช้งานฟังก์ชัน sum โดยกำหนดค่า 5.0 และ 10.0 ซึ่งมี type เป็น double ให้ ก็จะเอา binary representation ของ double ส่งไปให้ฟังก์ชัน แต่ฟังก์ชันบวกเลขแบบ int และส่งค่ากลับเป็น int ผลที่ได้ก็จะประหลาดๆ แบบนี้ที่เห็น

ถ้าต้องการให้ถูกต้อง เราก็จะต้องประกาศ function prototype ของฟังก์ชัน sum เอาไว้ใน main2.c เพื่อให้คอมไพเลอร์รู้ว่าฟังก์ชัน sum รับ argument 2 ตัวเป็น int ทั้งคู่ และจะส่งค่ากลับมาเป็น int คอมไพเลอร์ก็จะแปลงค่า 5.0 และ 10.0 ให้เป็น binary representation แบบ int ก่อนแล้วค่อยส่งไปยังฟังก์ชัน ทำให้ได้ผลลัพธ์ตามต้องการ (จริงๆ ต้องใช้ว่าใกล้เคียงกับที่ต้องการ เพราะการแปลงจาก double ไปเป็น int อาจจะทำให้ค่าของข้อมูลหายไปได้)

Function prototype นี้จะเขียนแยกต่างหาก เป็น header file (.h) ก็ได้ เพื่อความสะดวกในการนำ func2.c ไปใช้กับโปรแกรมอื่นๆ ได้อีก ไม่จำเป็นต้องยึดติดกับ main2.c เลยกลายเป็น 3 ไฟล์ใหม่นี้

/* main3.c */
#include<stdio.h>
#include"func3.h"
main() {
 int i;

 i = sum(5.0, 10.0); 
 printf("sum = %d\n", i);
}

/* func3.c */

int sum(int a, int b) {
 return a+b;
}

/* func3.h */
int sum(int, int);

เติมอีกหน่อยว่าตัวอย่างแรกในตอนที่แล้วทำงานได้ถูกต้อง เพราะไม่มีการส่ง argument ไป และค่าส่งกลับที่เป็น int นั้น เป็น type ปกติอยู่แล้ว

วันนี้เอาแค่นี้ก่อนละกัน พรุ่งนี้ค่อยมาต่อเรื่อง extern