Linked List (1) – Basic
Lấy từ tài liệu tuyệt vời này về linked list của trường Stanford mà tôi muốn khái lược lại bằng những đoạn mã trong đó. Danh sách liên kết (linked list) là một kiến thức rất cơ bản của cấu trúc dữ liệu và giải thuật. Hiểu được những ưu và khuyết điểm của nó sẽ giúp chúng ta hiểu các vấn đề về thời gian, không gian bộ nhớ và cấu trúc dữ liệu nói chung. Hơn thế nữa học về linked list là một cách rất tốt để hiểu về pointer. Những bài toán về linked list là sự kết hợp rất “đẹp” giữa giải thuật (algorithms) và các phép toán với con trỏ (pointer manipulation). Linked list là cách các lập trình viên luyện tập để thực sự hiểu về pointer và bạn sẽ thấy ngôn ngữ C “đẹp” vô cùng
Hãy tham khảo thêm tài liệu của Stanford để hiểu kỹ thêm (Highly recommend!)
- Linked list basic
- Linked List Building
- Techniques
- Duyệt xuống (Iterate down)
- Đổi một pointer bằng một tham chiếu tới pointer (reference pointer)
- Build list sử dụng thêm node vào đầu bằng hàm Push
- Build list sử dụng con trỏ tail
- Build list sử dụng con trỏ tail có xử lý trường hợp đặc biệt
- Build list sử dụng dummy node
- Build list sử dụng tham chiếu cục bộ (local references)
- Các đoạn mã ví dụ
- Other implementations
StringTokenizer
StringTokenizer là một class thường được viết trong các dự án. Đó là một class dùng để xử lý chuỗi, chia tách chuỗi thành các chuỗi con (token) được phân cách bởi các ký tự định nghĩa trước (delimiter). Ví dụ:
“Hoang Tran:1982:Hanoi University of Technology” được phân cách bởi ký tự “:” để thu được thông tin tương ứng về tên, năm sinh và trường học.
Có rất nhiều cách thể hiện lớp StringTokenizer này ở các ngôn ngữ khác nhau (Java thì đã có trong JDK của nó rồi) Bạn có thể google để tìm tham khảo các cách viết đó. Dựa trên ý tưởng của java, chúng ta sẽ xây dựng một lớp StringTokenizer hữu dụng trong C++.
Trong nhiều cách viết lớp này ở trên mạng thì mình cũng nhận ra rằng cách viết ở dự án cũ là tối ưu, hay và dễ hiểu nhất
Sử dụng deque làm storage data cho lớp StringTokenizer sẽ làm cho quá trình insert cũng như delete các beginning và end của container rất nhanh.
Đây là lớp StringTokenizer đã được thêm bớt chút ít sau khi đi chôm
Viết daemon trên Linux (2)
Nguồn: http://www.enderunix.org/docs/eng/daemon.php
Bài viết này bổ xung một số vấn đề chưa được trình bày trong bài viết “Viết daemon trên Linux (1)” của anh Hoàng.
1- Logging
Chúng ta có thể lựa chọn một trong hai cách ghi log như sau:
- Tự viết hàm ghi log:
Một hàm ghi log có dạng như sau:
void log_message( const char *fname, const char *msg ) { FILE *logfile = fopen( fname, “a” ); if( ! logfile ) return; fprintf( logfile, “%s\n”, msg ); fclose( logfile ); }
- Dùng các hàm có sẵn trong thư viện: Standard C library có các hàm syslog(), openlog(), closelog() phục vụ việc ghi log.
2- Cơ chế loại trừ lẫn nhau
Tại một thời điểm thường chỉ có một thực thể của daemon đang chạy. Một thực thể của daemon sẽ cố gắng khóa một file (lock file). Nếu khóa thành công nghĩa là chưa có thực thể nào khác của daemon đó đang chạy. Khi đó, pid của thực thể sẽ được ghi vào lock file. Chúng ta sử dụng hàm chuẩn lockf() như sau:
lfp = open( "exampled.lock", O_RDWR | O_CREAT, 0640 ); if ( lfp < 0 ) /* không mở được lock file */ exit( EXIT_FAILURE ); if ( lockf( lfp, F_TLOCK, 0 ) < 0 ) /* không khóa được lock file, một thực thể khác đang chạy */ exit( EXIT_SUCCESS ); /* chưa có thực thể nào đang chạy, ghi pid vào lock file */ sprintf( str,"%d\n", getpid() ); write( lfp, str, strlen(str) );
3- Bắt các tín hiệu gửi đến
Sau các bước chuẩn bị nói trên, một daemon sẽ bắt đầu lắng nghe tín hiệu gửi đến từ người dùng hoặc từ các tiến trình khác. Chúng ta viết một hàm xử lí tín hiệu, sau đó gán hàm đó với các tín hiệu cụ thể nhờ hàm chuẩn signal(): (more…)