Ngôn ngữ lập trình

Ngôn ngữ lập trình rất quan trọng và rất đa dạng. Lập trình viên thường học một vài ngôn ngữ nhưng vẫn có riêng một ngôn ngữ thiết yếu để làm việc...

Cài đặt NodeJS và một số lỗi thường gặp

Cài đặt NodeJS trên Window và Mac OS

Có lẽ Window và Mac OS là hai nển tảng dễ cài đặt NodeJS nhất, bạn chỉ cần vào trang chủ của NodeJS

[[code]]czoyMDpcImh0dHBzOi8vbm9kZWpzLm9yZw0KXCI7e1smKiZdfQ==[[/code]]
Để tải về phiên bản mới nhất và cài đặt. Sau khi cài đặt thành công, bạn hãy mởi cmd (Window), terminal (Mac OS) để kiểm tra cài đặt đã thành công hay chưa, bằng cách gõ lệnh:
[[code]]czo5Olwibm9kZSAtdg0KXCI7e1smKiZdfQ==[[/code]]
Nếu xuất ra version của NodeJS tức là bạn đã cài đặt thành công. Tiếp theo là kiểm tra NPM – Công cụ quản lý package của NodeJS.
[[code]]czo4OlwibnBtIC12DQpcIjt7WyYqJl19[[/code]]
Nếu xuất ra version của NPM bạn đã cài đặt thành công NodeJS, giờ chỉ việc lên ý tưởng và bắt đầu một project. VD:

Cài đặt NodeJS trên Ubuntu (12.04, 16.00+)

Trên Ubuntu, chúng ta sẽ dùng apt để cài đặt NodeJS. Đầu tiên, bạn nên update tất cả package của hệ điều hành để đảm bảo việc cài đặt NodeJS không gặp vấn đề.

[[code]]czoyMjpcInN1ZG8gYXB0LWdldCB1cGRhdGUuDQpcIjt7WyYqJl19[[/code]]

Cài NodeJS

[[code]]czoyOTpcInN1ZG8gYXB0LWdldCBpbnN0YWxsIG5vZGVqcw0KXCI7e1smKiZdfQ==[[/code]]

Cài đặt NPM

[[code]]czoyNjpcInN1ZG8gYXB0LWdldCBpbnN0YWxsIG5wbQ0KXCI7e1smKiZdfQ==[[/code]]
Để kiểm tra NPM và NodeJS đã cài đặt được chưa:
[[code]]czoxOTpcIm5vZGVqcyAtdg0KbnBtIC12DQpcIjt7WyYqJl19[[/code]]
Đến đây bạn sẽ thắc mắc vì sao trên Window, Mac OS, ta dùng lệnh node -v nhưng sao trên Ubuntu lại là nodejs -v.

Lý do là vì Ubuntu có một thành phần của hệ thống “mang tên” node rồi, nên NodeJS sinh sau, đẻ muộn đành phải dùng “tên” mới.

Điều này gây ra một số lỗi khi bạn cài NodeJS modules làm cho việc cài đặt không thành công. Để khắc phục ta sẽ symlink biến môi trường node về nodejs bằng lệnh sau:

[[code]]czo0MjpcInN1ZG8gbG4gLXMgL3Vzci9iaW4vbm9kZWpzIC91c3IvYmluL25vZGUNClwiO3tbJiomXX0=[[/code]]
Bạn hãy kiểm tra lại version của NodeJS bằng cách:
[[code]]czo5Olwibm9kZSAtdg0KXCI7e1smKiZdfQ==[[/code]]

Cài đặt NodeJS trên CentOS

Đầu tiên bạn nên update các package của hệ điều hành bằng câu lệnh:

[[code]]czoyMDpcInN1ZG8geXVtIC15IHVwZGF0ZQ0KXCI7e1smKiZdfQ==[[/code]]
Trên CentOS, chúng ta ưu tiên cài đặt NodeJS bằng cách build source, để làm được điều này, ta cần cài đặt các công cụ cần thiết bằng lệnh:
[[code]]czo0ODpcInN1ZG8geXVtIC15IGdyb3VwaW5zdGFsbCBcXFwiRGV2ZWxvcG1lbnQgVG9vbHNcXFwiDQpcIjt7WyYqJl19[[/code]]
Sử dụng wget tải source NodeJS:
[[code]]czo1NzpcIndnZXQgaHR0cDovL25vZGVqcy5vcmcvZGlzdC92MC4xMC40L25vZGUtdjAuMTAuNC50YXIuZ3oNClwiO3tbJiomXX0=[[/code]]
Giải nén và cd vào thư mục source:
[[code]]czo0NjpcInRhciB6eGYgbm9kZS12MC4xMC40LnRhci5neg0KY2Qgbm9kZS12MC4xMC40DQpcIjt7WyYqJl19[[/code]]
Chạy file config để chuẩn bị build source: ./configure Và đây là bước quan trọng nhất, chúng ta sẽ bắt đầu build:
[[code]]czo2OlwibWFrZQ0KXCI7e1smKiZdfQ==[[/code]]
Khi quá trình này hoàn thành, ta chạy tiếp lệnh này:
[[code]]czoxNDpcIm1ha2UgaW5zdGFsbA0KXCI7e1smKiZdfQ==[[/code]]
Quá trình build source NodeJS đã hoàn thành, giờ bạn chỉ cần thực hiện bước kiểm tra xem NodeJS đã cài đặt thành công chưa như với Window, Mac OS, Ubuntu.

Một số lỗi thường gặp

Không cài đặt NodeJS module cho project được Nếu NPM đã cài đặt thành công nhưng khi chạy lệnh:

[[code]]czo3MjpcIm5wbSBpbnN0YWxsIHTDqm5fbW9kdWxlDQpIb+G6t2Mga2hpIGPDsyBmaWxlIHBhY2thZ2UuanNvbg0KbnBtIGluc3RhbGx7WyYqJl19DQpcIjt7WyYqJl19[[/code]]
Mà có lỗi xuất hiện, thì rất có thể NPM trên máy của bạn đang dùng là phiên bản cũ. Lệnh này sẽ update NPM với phiên bản mới nhất. Chỉ cần chạy lệnh:
[[code]]czoyMzpcInN1ZG8gbnBtIGluc3RhbGwgLWcgbnBtXCI7e1smKiZdfQ==[[/code]]

Giói thiệu về ngôn ngữ lập trình Go

Ở đây, tui sẽ giới thiệu một ngôn ngữ còn khá lạ lẫm với người Việt, đó là Go – một ngôn ngữ lập trình Server-side được phát triển bởi Google. Ngôn ngữ Go được phát triển từ năm 2007 bởi Robert Griesemer, Rob Pike, và Ken Thompson ở Google. Đến nay có thêm Ian Lance Taylor, Russ Cox và Andrew Gerrand tham gia với vai trò là một trong những thành viên trụ cột.

Tới thời điểm này, khá nhiều ngôn ngữ đã ra đời phục vụ việc lập trình cho phía Server-side như: PHP, Ruby on Rails, Python, NodeJs… Mỗi ngôn ngữ đều có những ưu khuyết điểm riêng. Những riêng Go thì khá là toàn diện.

Giới thiệu Go

Go là một ngôn ngữ lập trình đồng thời (Concurrent Program) được Google giới thiệu lần đầu tiên vào nằm 2009. Go được các thành viên phát triển nói đến về một ngôn ngữ cho server, được phát triển cho cộng đồng trên nền C.

Go được ví như C – rút gọn. Những gì bạn có thể viết được trên C, bạn có thể viết được trên Go với tốc độ nhanh hơn gấp 5 lần với khác biệt rất nhỏ. Có thể đối với những bạn thường lập trình trên C# hay Java thì Go nhìn có vẻ khá lạ lẫm, nhưng khi bạn đã làm quen dc với Go, bạn sẽ thấy Go khá thú vị và tốc độ lập trình rất nhanh (như tui đã đề cập trước đó)

Một trong những điểm tui thích nhất ở Go là tốc độ xử lý. Trong khi C được đánh giá có tốc độ xử lý cực nhanh, thì Go chỉ bị C bỏ lại với khoảng cách rất gần! Trước khi nhìn vào benchmark của Go, tui sẽ giởi thiệu với các bạn các cú pháp syntax Go chuẩn, các kiểu dữ liệu cơ bản, và so sánh nó với C.

Go, một ngôn ngữ server ngắn gọn

Nói đến đây, bạn có thấy Go thú vị và hấp dẫn hơn một tẹo rồi phải không? Mong là vậy! Dù rồi hay chưa, tui sẽ tăng tính thuyết phục và đặc sắc của Go bằng cách cho bạn xem những syntax đẹp và so sánh nó với C! Thứ nhất, khai báo biến (variable) trong Go vô cùng ngắn gọn. Thay vì khai báo cụ thể kiểu dữ liệu của biến, Go có bộ tham chiếu kiểu dữ liệu (type inference) thực hiện việc gán kiểu và khởi tạo biến cho chúng ta. Để khai báo một biến đơn giản… Trong C:

int myVar = 33;
Trong Go:
myVar := 33
Ngắn gọn hơn C, bạn có thể thấy như thế! Không chỉ có thế, Go không đòi hỏi kết thúc câu lệnh bằng dấu “;”, trả về nhiều kết quả trong function, và có thể trả về cặp (pair) kết quả và lỗi cho bạn (result, err). Pair cũng là cách chuẩn để xử lý lỗi trong Go. Tôi sẽ đề cập kỹ hơn ở các bài viết về syntax trong Go. Hơn vậy, bạn có thể định nghĩa một biến bằng utf-8, một điều khá mới mẻ trong Go, ví dụ: biếnSố := 33 Bây giờ, ta tiến hành xét một chương trình Hello World trong Go và C:

helloworld.c

#include <stdio.h>
 
int main ()
{
  printf ("Hello World!\n");
}
helloworld.go
package main
 
import (
    "fmt"
)
 
func main() {
    fmt.Println("Hello World!")
}
Chúng ta có thể thấy được sự tương đồng giữa Go và C qua đoạn code trên Bạn sẽ thấy được Go ngắn gọn hơn C rõ ràng hơn khi bạn viết các chương trình lớn, phức tạp và cần xử lý đồng thời (concurrency). Có một bài blog so sánh C và Go, cũng như các chi tiết về những lợi thế về syntax của Go so với C: http://www.syntax-k.de/projekte/go-review Tiếp theo. chúng ta sẽ so sánh khả năng chịu tải của Go để xem Go có thực sự chịu tải tốt đúng như tuyên bố của những lập trình viên hay không

Khả năng chịu tải của Go

Hãy nhìn cách Go chạy một loạt các chương trình đơn giản nhưng lặp đi lặp lại trong bảng dưới đây:

( Website test trực tuyến: http://benchmarksgame.alioth.debian.org/ )

Như chúng ta thấy từ số liệu thống kê, Golang hiệu quả hơn Ruby rất nhiều!!! Trong chương trình đầu tiên – ‘fasta-redux’, Ruby mất 110 giây để thực thi xong, nhưng Go chỉ mất 1.79 giây. Nhanh hơn gấp gần 100 lần! Quá ấn tượng phải không!!!

Go không chỉ ấn tượng về tốc độ xử lý, mà còn thuận lợi về xử lý đồng thời hơn hầu hết các ngôn ngữ server hiện giờ. Go sử dụng các Goroutines (tui sẽ nói rõ hơn về Goroutlines ở những bài viết sau).

Go đã cung cấp được chúng ta một ngôn ngữ lập trình ở server với tốc độ cực nhanh, một cú pháp ngắn gọn, hằng trăm package mặc định hữu dụng, cơ chế xử lý đa luồng đồng thời, và vô số thư viện được phát triển bởi các lập trình viên trên khắp thế giới. Tất cả giúp chúng ta xây dựng website, server bằng Go một cách nhanh và hiệu quả nhất.

Tóm tắt

Với tuổi đời còn khá non trẻ (từ 2009) so với những ngôn ngữ khác (C hơn 40 năm, C++ hơn 30 năm, Ruby khoảng 20 năm, Java cỡ 17 năm, C# tầm 10-12 năm…) thì 5 năm thực sự là khoảng thời gian không nhiều để ta so sánh những sản phẩm nổi bật được viết và phát hành bằng Go so với những ngôn ngữ khác. Tuy nhiên, Go đang được Google và cộng đồng lập trình viên tiếp tục phát triển và hoàn thiện. Tin vui là hiện nay, cộng đồng quan tâm đến Go trên thế giới không nhỏ!

Cộng đồng Go lớn nhất hiện nay trên thế giới là Gopherarcademy, bên cạnh đó còn cóGoMeetUp

Một trong những event lớn về Go trong thời gian gần đây là ngày 23 – 25/01/2015 vừa qua, GopherGala đã đứng ra tổ chức sự kiện Hackathon đầu tiên cho Go trên toàn thế giới

Go đang dần được chấp nhận và triển khai rộng rãi trên nhiều Startup và Công ty thương mại. Nhiều nhà cung cấp Saas/ Paas sử dụng Go trong dự án của họ. Dịch vụ gửi mail SendGrid cũng đang áp dụng Go để xây dựng hệ thống mạnh mẽ hơn, nhanh hơn và đáng tin cậy hơn!

Túm cái váy lại, nếu bạn đang tìm kiếm một ngôn ngữ lập trình đồng thời, song song, đơn giản, sexy và tuyệt vời, hãy đến với Go!

Tạo Makefile trên Go

Makefile thực hiện một số thao tác thường dùng trong Go

Khi làm project Go mình thường tạo một file Makefile có form như này:

Lưu ý nhớ thay &lt;tên-file-binary-muốn-build&gt; thành tên mà bạn muốn build ra.

Makefile

SRC = $(wildcard *.go)
OUT = <tên-file-binary-muốn-build>

CC = go
go = $(shell which go 2> /dev/null)

ifeq (, $(go))
    @printf "\e[91mGo not found!"
endif

$(OUT): clean $(SRC)
    @printf "\e[33mBuilding\e[90m %s\e[0m\n" $@
    @$(CC) build -o $@ $(SRC)
    @printf "\e[34mDone!\e[0m\n"

test: clean
    @printf "\e[33mTesting...\e[0m\n"
    go test ./...
    @printf "\e[34mDone!\e[0m\n"

clean:
    @rm -f $(OUT)
    @printf "\e[34mAll clear!\e[0m\n"

install: $(OUT)
    @printf "\e[33mInstalling\e[90m %s\e[0m\n" $(OUT)
    sudo rm -f /usr/local/bin/$(OUT)
    sudo ln -s $(PWD)/$(OUT) /usr/local/bin/$(OUT)
    @printf "\e[34mDone!\e[0m\n"

uninstall:
    @printf "\e[33mRemoving\e[90m %s\e[0m\n" $(OUT)
    sudo rm -f /usr/local/bin/$(OUT)
    @printf "\e[34mDone!\e[0m\n"
Chức năng gồm có:

Tự động build thành file binary với tên file được định sẵn

Chạy lệnh:

make
alt text

Chạy toàn bộ test của tất cả các packages trong project

Chạy lệnh:

make test

alt text

Build và install vào /usr/local/bin

Nếu viết các ứng dụng command line, thì chức năng này sẽ giúp bạn tiết kiệm thời gian và có thể test thực tế trên môi trường của máy bằng cách copy file binary được build ra vào thư mục /usr/local/bin. Khi đó bạn có thể chạy chương trình của mình ở bất kì thư mục nào trong máy tính.

make install

alt text
Khi không cần dùng nữa hoặc muốn gỡ nó ra thì chạy:

make uninstall

Hướng dẫn cài đặt và viết chương trình với Go

Mình khuyến khích các bạn sử dụng môi trường Unix như Linux hay Mac OS X cho việc dev. Mình không ghét Windows nhưng mà cài đặt môi trường dev trên win rất tốn thời gian và phiền phức (các bạn đã từng cài đặt môi trường Python hay Ruby chắc sẽ đồng ý).

Nếu không có điều kiện sử dụng các môi trường Unix, các bạn có thể dùng Docker hoặc Vagrant, sẽ tiện hơn là cài trực tiếp trên môi trường Windows.

 

Bước 1: Cài đặt Go runtime

 

Windows

Đối với các bạn dùng Windows, cài bằng bộ cài MSI sẽ tiện hơn, nó sẽ tự động config hết mọi thứ cần thiết.

Đầu tiên, tải bộ cài tại đây https://golang.org/dl và chạy file go<version>.windows-386.msi (32 bit) hoặc go<version>.windows-amd64.msi (64 bit), tuỳ vào hệ điều hành bạn đang sử dụng.

 

Linux và Mac OS X

Với các bạn xài môi trường Unix, chúng ta nên cài bằng dòng lệnh.

Chúng ta sẽ cài Go thông qua Homebrew (có thể bỏ qua nếu bạn đã cài trước rồi), khởi động Terminal lên và gõ:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Sau khi cài xong Homebrew, chúng ta bắt đầu cài Go với lệnh:
$ brew install go --cross-compile-common
Ngồi rung đùi vài phút (hoặc vài giây, hoặc vài tiếng, tuỳ vô đường truyền nhà bạn).

 

Mac OS X Installer

Trên Mac, nếu bạn không thích cài bằng dòng lệnh, có thể tải bộ cài từ trang chủ https://golang.org/dl/ và cài trực tiếp.

Go runtime sẽ được cài vào thư mục /usr/local/go và chúng ta cần setup biến môi trường (PATH) ở bước tiếp theo.

 

Bước 2: Cài đặt biến môi trường

 

Windows

Trên Windows, chúng ta sẽ cài đặt biến môi trường bằng cách click phải vào My Computer chọn Properties, chọn tab Advanced và click nút Environment Variables.

Nếu bạn cài đặt Go vào thư mục mặc định là C:\Go thì bạn cần cấu hình như sau:

  • Tạo một biến mới tên là GOROOT với giá trị là C:\Go
  • Chọn biến PATH có sẵn, thêm vào sau dấu chấm phẩy ; cuối dòng đường dẫn sau: C:\Go\bin;

 

Linux và Mac OS X

Trên các máy Unix, bạn cài đặt biến môi trường bằng cách chỉnh sửa file $HOME/.profile hoặc $HOME/.bash_profile.

Nếu không tìm thấy biến $HOME, có thể thay nó bằng /user/local

Hãy thêm nội dung sau:

export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin
Thế là xong rồi đấy! Đơn giản, phải không nào?

 

Bước 3: Chạy thử

Bây giờ, chúng ta có thể kiểm tra xem Go đã được cài hoàn chỉnh hay chưa, bằng cách gõ lệnh sau vào Terminal (hoặc Command Line trên Windows):

$ go version
Nếu Go được cài đặt đầy đủ thì nội dung output sẽ giống thế này:
go version go1.4.2 darwin/amd64
 

Viết chương trình đầu tiên bằng Go

OK, cài đặt xong rồi thì bắt tay vào code thôi. Chương trình đầu tiên, đoán ra rồi phải không? là chương trình huyền thoại mà bài nào cũng viết: Hello World =))

Chúng ta sẽ tạo một file mới, tên là hello.go và gõ đoạn chương trình sau vào. Nhưng hãy nhớ là: Gõ vào, đừng copy paste!. Phải tự gõ vào mới nhớ được!

package main

import "fmt"

func main() {
    fmt.Printf("Hello Gopher's World!")
}
Gõ xong rồi. Bạn có thấy code nó quái thế nào không?

Không có chấm phẩy cuối dòng, từ khoá func cứ như là Swift vậy, hao hao giống Javascript nữa. Còn cái gì nữa đây? fmt.Printf để in nội dung ra màn hình, có cần phải dài dòng vậy không?

Golang là thế đấy, nếu bạn không thích nó, thì phải tập thích nó đi thôi =))

Bây giờ hãy compile và chạy chương trình với lệnh:

$ go run hello.go
Output sẽ là:
Hello Gopher's World!
Xong rồi đó, chúc mừng, bạn đã viết được chương trình đầu tiên của mình bằng Go rồi đấy =))

Nhập, xuất dữ liệu từ file trong C++

Tất cả các chương trình mà ta đã gặp trong cuốn sách này đều lấy dữ liệu vào từ bàn phím và in ra màn hình. Nếu chỉ dùng bàn phím và màn hình là các thiết bị vào ra dữ liệu thì chương trình của ta khó có thể xử lý được khối lượng lớn dữ liệu, và kết quả chạy chương trình sẽ bị mất ngay khi ta đóng cửa sổ màn hình output hoặc tắt máy. Để cải thiện tình trạng này, ta có thể lưu dữ liệu  tại  các thiết bị lưu trữ thứ cấp mà thông dụng nhất thường là ổ đĩa cứng. Khi đó dữ liệu tạo bởi một chương trình có thể được lưu lại để sau này được sử dụng bởi chính nó hoặc các chương trình khác. Dữ liệu lưu trữ như vậy được đóng gói tại các thiết bị lưu trữ thành các cấu trúc dữ liệu gọi là tp (file).

Chương này sẽ giới thiệu về cách viết các chương trình lấy dữ liệu vào (từ bàn phím hoặc từ một tệp) và ghi dữ liệu ra (ra màn hình hoặc một  tệp).

Khái niệm dòng dữ liệu

Trong một số ngôn ngữ lập trình như C++ và Java, dữ liệu vào ra từ tệp, cũng  như từ bàn phím và màn hình, đều được vận hành thông qua các dòng dliu (stream). Ta có thể coi dòng dữ liệu là một kênh hoặc mạch dẫn  mà  dữ  liệu được truyền qua đó để chuyển từ nơi gửi đến nơi nhận.

Dữ liệu được truyền từ chương trình ra ngoài theo một dòng ra (output stream). Đó có thể là dòng ra chuẩn nối và đưa dữ liệu ra màn hình, hoặc dòng ra nối với một tệp và đẩy dữ liệu ra tệp đó.

Chương trình nhận dữ liệu vào qua một dòng vào (input stream). Dòng vào thì có thể là dòng vào chuẩn nối và đưa dữ liệu vào từ màn hình, hoặc dòng vào nối với một tệp và nhận dữ liệu vào từ tệp đó.

Dữ liệu vào và ra có thể là các kí tự, số, hoặc các byte chứa các chữ số nhị  phân.

Trong C++, các dòng vào ra được cài đặt bằng các đối tượng của các lớp dòng vào ra đặc biệt. Ví dụ, cout mà ta vẫn dùng để ghi ra màn hình chính là dòng ra chuẩn, còn cin là dòng vào chuẩn nối với bàn phím. Cả hai đều là các đối tượng dòng dữ liệu (khái niệm “đối tượng” này có liên quan đến tính năng hướng đối tượng của C++, khi nói về các dòng vào/ra của C++, ta sẽ phải đề cập nhiều đến tính năng này).

Tp văn bn và tp nhphân

Về bản chất, tất cả dữ liệu trong các tệp đều được lưu trữ dưới dạng một chuỗi các bit nhị phân 0 và 1. Tuy nhiên, trong một số hoàn cảnh, ta không  coi nội dung của một tệp là một chuỗi 0 và 1 mà coi tệp đó là một chuỗi các kí tự. Một   số tệp được xem như là các chuỗi kí tự và được xử lý bằng các dòng và hàm cho phép chương trình và hệ soạn thảo văn bản của bạn nhìn các chuỗi nhị phân như là các chuỗi kí tự. Chúng được gọi là các tp văn bn (text file). Những tệp không phải tệp văn bản là tp nhphân (binary file). Mỗi loại tệp được xử lý   bởi các dòng và hàm riêng.

Chương trình C++ của bạn được lưu trữ trong tệp văn bản. Các tệp ảnh và nhạc  là các tệp nhị phân. Do tệp văn bản là chuỗi kí tự, chúng thường trông giống nhau tại các máy khác nhau, nên ta có thể chép chúng  từ  máy này sang  máy khác mà không gặp hoặc gặp phải rất ít rắc rối. Nội dung của các tệp nhị phân thường lấy cơ sở là các giá trị số, nên việc sao chép chúng giữa các máy có thể gặp rắc rối do các máy khác nhau có thể dùng các quy cách lưu trữ số không giống nhau. Cấu trúc của một số dạng tệp nhị phân đã được chuẩn hóa để chúng có thể được sử dụng thống nhất tại các platform khác nhau. Nhiều dạng tệp ảnh và âm thanh thuộc diện này.

Mỗi kí tự trong một tệp văn bản được biểu diễn bằng 1 hoặc 2 byte, tùy theo đó  là kí tự ASCII hay Unicode. Khi một chương trình viết một giá trị vào một tệp văn bản, các kí tự được ghi ra tệp giống hệt như khi chúng được ghi ra màn hình bằng cách sử dụng cout. Ví dụ, hành động viết số 1 vào một tệp sẽ dẫn đến kết quả là 1 kí tự được ghi vào tệp, còn với số 1039582 là 7 kí tự được ghi vào  tệp.

Các tệp nhị phân lưu tất cả các giá trị thuộc một kiểu dữ liệu cơ bản theo cùng một cách, giống như cách dữ liệu được lưu trong bộ nhớ máy tính. Ví dụ, mỗi  giá trị int bất kì, 1 hay 1039582 đều chiếm một chuỗi 4 byte.

 Vào ra tệp

C++ cung cấp các lớp sau để thực hiện nhập và xuất dữ liệu đối với  tệp:

  • ofstream: lớp dành cho các dòng ghi dữ liệu ra tệp
  • ifstream: lớp dành cho các dòng đọc dữ liệu từ tệp
  • fstream: lớp dành cho các dòng vừa đọc vừa ghi dữ liệu ra tệp.

Đối tượng thuộc các lớp này do quan hệ thừa kế nên cách sử dụng chúng khá giống với cin và cout – các đối tượng thuộc lớp istream và ostream – mà chúng ta đã dùng. Khác biệt chỉ là ở chỗ ta phải nối các dòng đó với các  tệp.

c-p-yeulaptrinh.pw

Hình 8.1: Các thao tác cơ bn vi tp văn bn.

Chương trình trong Hình 8.1 tạo một tệp có tên hello.txt và ghi vào đó một câu “Hello!” theo cách mà ta thường làm đối với cout, chỉ khác ở chỗ thay cout bằng đối tượng dòng myfile đã được nối với một tệp. Sau đây là các bước thao tác với tệp.

  • Mở tệp

Việc đầu tiên là nối đối tượng dòng với một tệp, hay nói cách khác là mở một  tệp. Kết quả là đối tượng dòng sẽ đại diện cho tệp, bất kì hoạt động đọc và ghi  đối với đối tượng đó sẽ được thực hiện đối với tệp mà nó đại diện. Để mở một  tệp từ một đối tượng dòng, ta dùng hàm open của nó:

open (fileName, mode);


Trong đó, fileName là một xâu kí tự thuộc loại const char * với kết thúc là kí tự null (hằng xâu kí tự cũng thuộc dạng này), là tên của tệp cần mở, và mode là tham số không bắt buộc và là một tổ hợp của các cờ  sau:

ios::in     mở để đọc

ios::out    mở để ghi

ios::binary  mở ở dạng tệp nhị  phân

ios::ate    đặt ví trí bắt đầu đọc/ghi tại cuối tệp. Nếu cờ này không được đặt giá trị gì, vị trí khởi đầu sẽ là đầu tệp.

ios::app    mở để ghi tiếp vào cuối tệp. Cờ này chỉ được dùng  cho dòng mở tệp chỉ để ghi.

ios::trunc   nếu tệp được mở để ghi đã có từ trước, nội dung cũ sẽ bị  xóa

để ghi nội dung mới.
Các cờ trên có thể được kết hợp với nhau bằng toán tử bit OR (|). Ví dụ, nếu ta muốn mở tệp people.dat theo dạng nhị phân để ghi bổ sung dữ liệu vào cuối tệp, ta dùng lời gọi hàm sau:

ofstream myfile;
myfile.open ("people.dat",
   ios::out | ios::app | ios::binary);
Trong trường hợp lời gọi hàm open không cung cấp tham số mode, chẳng hạn Hình 8.1, chế độ mặc định cho dòng loại ostream là ios::out, cho dòng loại istream là ios::in, và cho dòng loại fstream là ios::in | ios::out.

Cách thứ hai để nối một dòng với một tệp là khai báo tên tệp và kiểu mở tệp  ngay khi khai báo dòng, hàm open sẽ được gọi với các đối số tương ứng. Ví dụ:

ofstream myfile ("hello.txt",
   ios::out | ios::app | ios::binary);

Để kiểm tra xem một tệp có được mở thành công hay không, ta dùng hàm thành viên is_open(), hàm này không yêu cầu đối số và trả về một giá trị kiểu bool bằng true nếu thành công và bằng false nếu xảy ra trường hợp ngược lại


if (myfile.is_open()) { /* file now open and ready */ }
  • Đóng tệp

Khi ta hoàn thành các công việc đọc dữ liệu và ghi kết quả, ta cần đóng tệp để

tài nguyên của nó trở về trạng thái sẵn sàng được sử dụng. Hàm thành viên này

 

không có tham số, công việc của nó là xả các vùng bộ nhớ có liên quan và đóng tệp:

 

Sau khi tệp được đóng, ta lại có thể dùng dòng myfile để mở tệp khác, còn tệp vừa đóng lại có thể được mở bởi các tiến trình  khác.

Hàm close cũng được gọi tự động khi một đối tượng dòng bị hủy trong khi    nó

đang nối với một tệp.

 

  • Xlý tp văn bn

Chế độ dòng tệp văn bản được thiết lập nếu ta không dùng cờ ios::binary khi mở tệp. Các thao tác xuất và nhập dữ liệu đối với tệp văn bản được thực hiện tương tự như cách ta làm với cout và cin.

#include <iostream>
#include <fstream>
 
using namespace std; 
 
int main ()
{
  ofstream courseFile (“courses.txt); if (courseFile.is_open())
  {
    courseFile <<1 Introduction to Programming\n”; courseFile <<2 Mathematics for Computer Science\n”; courseFile.close();
  }
  else cout << “Error: Cannot open file”;
  return 0;
}

Kết quả chạy chương trình [tệp courses.txt]

  • Introduction to Programming

 

  • Mathematics for Computer Science
Hình 8.2: Ghi dliu ra tp văn bn.
#include <iostream>
#include <fstream>
#include <string>
 
using namespace std; 
 
int main ()
{
  ifstream file (“courses.txt); 
  if (file.is_open())
  {
    while (! file.eof())
    {
      string  line; getline (file,line);
      cout << line << endl;
    }
    file.close();
  }
  else cout << “Error! Cannot open file”;
  return 0;
}

Kết quả chạy chương trình

  • Introduction to Programming
  • Mathematics for Computer Science

c-p-2-yeulaptrinh.pw

Hình 8.3: Đọc dliu ttp văn bn.

 

Chương trình ví dụ trong Hình 8.2 ghi hai dòng văn bản vào một tệp. Chương trình trong Hình 8.3 đọc nội dung tệp đó và ghi ra màn hình. Để ý rằng trong chương trình thứ hai, ta dùng một vòng lặp để đọc cho đến cuối tệp. Trong đó, myfile.eof() là hàm trả về giá trị true khi chạm đến cuối tệp, giá trị true mà myfile.eof() trả về đã được dùng làm điều kiện kết thúc vòng lặp đọc tệp.

Kiểm tra trạng thái của dòng

Bên cạnh hàm eof() có nhiệm vụ kiểm tra cuối tệp, còn có các hàm thành viên khác dùng để kiểm tra trạng thái của dòng:

bad()  trả về true nếu một thao tác đọc hoặc ghi bị thất bại. Ví dụ khi ta cố viết vào một tệp không được  mở  để ghi hoặc khi thiết bị lưu  trữ không còn chỗ trống để ghi.

fail() trả về true trong những trường hợp bad() trả về true và khi có lỗi định dạng, chẳng hạn như khi ta đang định đọc một số nguyên nhưng lại gặp phải dữ liệu là các chữ cái.

eof()   trả về true nếu chạm đến cuối tệp

good()    trả về false nếu xảy tình huống mà  một trong các hàm trên nếu được gọi thì sẽ trả về true.

Để đặt lại cờ trạng thái mà một hàm thành viên nào đó đã đánh dấu trước đó, ta dùng hàm thành viên clear.

Nhập, xuất dữ liệu trong C++

Trong bài này, chúng ta sẽ học cách nhập vào từ bàn phím (stdin standard input device) và ghi ra màn hình (stdout standard output device).

Ta cũng cần dùng đến thư viện iostream namespace std để hỗ trợ nhập xuất. Khi muốn dùng lệnh nào nằm trong namespace std, ta có 2 cách:

  • Khai báo using namespace std ở đầu chương trình, sau đó có thể dùng các lệnh này bình thường.
  • Thêm std:: vào trước lệnh ta muốn dùng. Ví dụ như std::cin, std::endl.

Từ đây trở đi, khi gặp std:: trước một lệnh, chúng ta sẽ tự hiểu lệnh sau đó nằm trong namespace std và có 2 cách như trên để viết.

std::cin

Để nhập dữ liệu cho biến, ta dùng lệnh cin

cin >> biến;

Nếu có nhiều biến cần nhập vào, ta có thể viết liên tiếp như sau

cin >> biến 1 >> biến 2 >> … >> biến n;

Khi chạy đến lệnh cin, chương trình sẽ chờ người dùng nhập dữ liệu vào các biến tương ứng. Dữ liệu nhập vào được phân cách nhau bởi dấu cách hoặc tab hoặc enter, và luôn được hiển thị ra màn hình.

Ví dụ

int a, b;
cin >> a >> b;

Lệnh cin ở dòng 2 sẽ yêu cầu người dùng nhập vào 2 giá trị tương ứng với 2 biến số nguyên a và b.

Lưu ý

Khi nhập vào, các giá trị được phân tách nhau bởi space (dấu cách), tab (dấu tab) hay enter (dấu xuống dòng). Nếu không, mặc dù trong một số trường hợp chương trình vẫn chạy nhưng rất khó kiểm soát được giá trị các biến nhập vào.
Ví dụ: đoạn mã sau

int a,b,c;  
cin>>a>>b>>c;  
hoặc
int a,b,c;
cin>>a; cin>>b; cin>>c;
khi thực hiện, ta nhập dữ liệu từ bàn phím: 3 4 5<enter> hoặc nhập:
3<enter>
4<enter>
5<enter>
Sau khi nhập xong biến a=3, b=4 và c=5.

std::cout

Để in dữ liệu ra màn hình, ta dùng lệnh cout

cout << biểu thức;

Ta cũng có thể in hàng loạt nhiều biểu thức liên tiếp nhau

cout << biểu thức 1 << biểu thức 2 << … << biểu thức n;

Biểu thức ở đây có thể hiểu là biểu thức toán học chứa biến, hằng, hay kết quả trả về của một hàm, …

Ví dụ

int a, b;
cin >> a >> b;
cout << a << ” + ” << b << ” = ” << a + b;

Lệnh cout ở dòng 3 in ra lần lượt: giá trị biến a, chuỗi ” + “, giá trị biến b, chuỗi ” = ” và giá trị biểu thức a + b.

Một số ký tự điều khiển

  • \a’ : tiếng chuông
  • \b’ : lùi lại một bước
  • \n’ : xuống dòng
  • \t’ : dấu tab
  • \\’ : dấu \
  • \?’ : dấu ?
  • \”‘ : dấu “

Lưu ý

std::endl cũng có chức năng tương tự ‘\n’ nhưng ngoài ra endl còn làm rỗng bộ đệm đầu ra.

Ví dụ

cout << ‘\t’ << “Hello World !\n” << 0;

Kết quả:

Hello World!
0

Lưu ý

cin dùng toán tử >> còn cout dùng toán tử <<. Đừng nhầm lẫn!

cout, cin nằm trong thư viện iostream

Định dạng in

Để dùng những lệnh định sau, ngoài thư viện iostream, ta còn phải dùng thư viện iomanip để định dạng. Các định dạng này cần được cout mới có tác dụng.

std::setw(n): quy định khoảng không gian cho dữ liệu được in ra màn hình là n. Nếu dữ liệu chiếm ít không gian hơn, dữ liệu sẽ được căn  lề phải khi in ra. Ngược lại , lệnh này không có ảnh hưởng, tức dữ liệu vẫn in ra như bình thường.

std::setprecision(n): quy định số chữ số được làm tròn khi in ra là n. Số chữ số được tính từ trái qua phải.

std::fixed: lệnh này đi kèm với setprecision sẽ xác định chỉ làm tròn các chữ số ở phần thập phân.

Ví dụ

cout << 12.345 << ‘ ‘;
cout << setprecision(2) << 12.345 << ‘ ‘;
cout << fixed << setprecision(2) << 12.345;

Kết quả:

12.345 12 12.35

Một số hàm khác liên quan đến nhập xuất

std::cin.get(c): nhập 1 ký tự vào biến c.

std::cin.getline(s, n): nhập tối đa n – 1 ký tự vào xâu s (ký tự thứ n là NULL).
std::getline (cin,str): đọc xâu kí tự str, str kiểu dữ liệu string.
std::cin.ignore(n): xóa n ký tự trong bộ đệm đầu vào.

fflush(stdin): xóa toàn bộ bộ đệm đầu vào.

Có thể bạn thích:
Nhập, xuất dữ liệu từ file trong C++

Bài tập mẫu

Viết chương trình nhập vào 3 số a, b, c. In ra trung bình cộng của 3 số đó với giá trị làm tròn đến chữ số thập phân thứ 5.

Code:

#include <iostream>
#include <iomanip>
 
using namespace std;
 
int main()
{
     cout << "Nhap 3 so a, b, c: ";
     float a, b, c;
     cin >> a >> b >> c;
     float avr = (a + b + c) / 3;
     cout << fixed << setprecision(5) << avr << endl;
     system("pause"); // Tạm dừng màn hình chờ nhấn Enter
     return 0;
}

Hướng dẫn cài đặt và sử dụng Dev-C++

Dev-C++ là một môi trường phát triển tích hợp tự do (IDE) được phân phối dưới hình thức giấy phép Công cộng GNU hỗ trợ việc lập trình bằng C/C++. Nó cũng nằm trong bộ trình dịch mã nguồn mở MinGW. Chương trình IDE này được viết bằng ngôn ngữ Delphi.  Dùng để soạn thảo và biên dịch chương trình viết bằng NNLT C/ C++.

dev-c-yeulaptrinh.pw

Mình khuyên các bạn nên dùng phiên bản: Dev-Cpp 5.11 TDM-GCC 4.9.2 Setup.exe

Link tải trực tiếp từ server Vietnam: Download here

Link tải từ trang chủ:  https://sourceforge.net/projects/orwelldevcpp/files/Setup%20Releases/

Link tải các phiên bản khác: http://www.bloodshed.net/dev/devcpp.html

Thực hiện chương trình

B1. Tạo tệp mới và soạn thảo mã nguồn

  • Vào File > New > Source File (Hoặc Project nếu chương trình gồm nhiều file > Chọn “Console Application” > Chọn C project hoặc C++ Project) hoặc nhấn Ctrl+N
  • Soạn thảo mã nguồn
  • Lưu: File/Save/ đặt tên (chọn đường dẫn nếu có) > OK

dev-c-1-yeulaptrinh.pw

B2. Dịch chương trình

Kích Menu Execute > Compile (Ctrl+ F9)

dev-c-2-yeulaptrinh.pw

Nếu xuất hiện lỗi cú pháp, hãy quan sát dòng lệnh được đánh dấu màu nâu trong mã nguồn và các dòng gợi ý nội dung lỗi. Ta xác định lỗi và tự sửa lại, sau đó Cltr+F9 để biên dịch lại đến khi chương trình hết lỗi.

dev-c-3-yeulaptrinh.pw

Một số lỗi hay gặp: thiếu dấu chấm phảy ;, ngoặc tròng (,), ngoặc móc {,}, các phép quan hệ, các lệnh if, for, while không đúng cú pháp …

B3. Chạy chương trình

Kích menu Execute > Run (Ctrl+ F10)

dev-c-4-yeulaptrinh.pw

Nếu không dừng màn hình để xem kết quả ta thêm vào lệnh system(“pause”) trước lệnh return 0; trong hàm main(); hoặc kích menu tools/Enviroment options/ General/ chọn Pause console programs after return

I.7.3. Debug chương trình

Để theo dõi quá trình thực hiện của máy trên từng dòng lệnh và các giá trị thay đổi của biến ta sử dụng chức năng debug của phần mềm DevC++ theo hướng dẫn sau:

Bước 1:  Giả sử ta có chương trình sau:

dev-c-5-yeulaptrinh.pw

  • Tạo Breakpoint để chỉ nơi bắt đầu theo dõi chương trình bằng cách kích chuột vào số thứ tự dòng, xuất hiện nền của dòng đó có màu đỏ, sau đó kích menu

Execute/ Debug (hoặc nhấn phím F5)

  • Để theo dõi máy thực hiện từng dòng lệnh ta nhấn phím F7 hoặc kích nút Next line (dòng có nền xanh là dòng máy đang thực hiện đến đó)
  • Để xem giá trị của biến nào, ta kích nút Add wacth, gõ tên biến vào hộp thoại mới xuất hiện/ OK … như hình dưới đây.

dev-c-6-yeulaptrinh.pw

Giải thích thêm cho hình trên:

  • Đầu tiên tạo Breakpoint tại dòng 11, nhấn F5. Nền xanh tại dòng này x=8, y=3, z là giá trị chưa xácđịnh cụ thể. Nhấn phím F7, dòng xanh nhảy xuống dòng 12. Lệnh z = ++x + y–; được thực hiện:
  • Lệnh ++x thực hiện nên x=9 đến lệnh z = x+y và z=12 sau đó đến y –, khi đó y=2 như kết quả hiện thời trên khung debug.
  • Bằng cách nhấn F7 tiếp cho đến khi kết thúc hoặc kích nút Stop Execute để ngừng debug chương trình.

Lưu ý:

  • Để soạn theo nhanh một tệp C++, tao có thể mở cửa sổ Codeblocks và kích menu File/ New/ Empty file, một file trắng xuất hiện và ta bắt đầu soạn thảo mã nguồn tại đây, lưu, dịch và thực hiện chương trình một cách bình thường và nhanh. Chỉ có tồn tại là làm theo cách này không Debug được mã nguồn. Nếu muốn debug thì phải thêm tệp này vào một project nào đó và debug như cách hướng dẫn ban đầu.
  • Hai trình biên dịch DevC++ và Codeblocks đểu có thể biên soạn, lưu trữ, dịch, debug và thực hiện tốt những chương trình soạn thảo bằng C++. Vậy ta sẽ chọn chương trình nào để thực hành các bài tập trên máy? Điều này có lẽ tùy thuộc vào người sử dụng yêu thích biên dịch nào… Nếu bạn là người bắt đầu cho cả hai loại trên, theo ý tác giả bạn nên chọn Codeblocks vì chỉ một lý do DEBUG!!! Bạn có thể tìm hiểu qua các phương tiện thông tin khác và chọn cho mình một trình biên dịch để bắt đầu ngay.