Showing posts with label Programming techniques. Show all posts
Shell - Search và Replace trong file
1. Tìm kiếm file với lệnh find
2. Tìm kiếm và thay thế string trong một file với lệnh sed
3. Tìm kiếm file, search và thay thế nội dung file với sự kết hợp của find và sed
find <search dir> -type <file or dir> -name <pattern file name>
Ex:
find /home/user/Downloads -type f -name "*.rar"
Tìm kiếm tất cả các file nén .rar trong thư mục Downloads
2. Tìm kiếm và thay thế string trong một file với lệnh sed
sed -i "s:<string to search>:<string to replace>:" infile outfile
or
sed -i "s:<string to search>:<string to replace>:" filename
# tim, thay the va save filename
Ex:
sed -i "s:day:night:" testfile.txt
3. Tìm kiếm file, search và thay thế nội dung file với sự kết hợp của find và sed
#!/bin/sh
# Tao listfile.txt luu danh sach tat ca cac file trong thu muc Downloads
#find /home/ninhld/Downloads -type f -name '*' > /home/ninhld/Downloads/listfile.txt
#Duyet qua tat ca cac file trong thu muc Downloads, search va replace tat ca
#cac file ma noi dung co noi dung /home/ninhld/Downloads
FINDPATH="/home/ninhld/Downloads"
FILETYPE="*"
PATTERN="/home/ninhld/Downloads"
REPLACE=""
find $FINDPATH -type f -name "$FILETYPE" -exec sed -i "s:$PATTERN:$REPLACE:" {} +
#for FILE in $(find $FINDPATH -type f)
#do
# #echo $FILE
# sed -i "s:$FINDPATH::" $FILE
#done
C/C++ Giá trị khởi tạo ban đầu của biến
Giá trị khởi tạo ban đầu của biến tưởng chừng đơn giản nhưng nhiều khi để lại hậu quả nghiêm trọng, trong bài viết này đề cập đến một số trường hợp bạn phải khởi tạo giá trị bạn đầu cho biến một cách rõ ràng.
initial_value.c (vd chỉ có tính minh họa)
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main(int argc, char **argv){
int idata; /* default: 0 */
bool bdata; /* default: false */
float *pdata; /* default: NULL */
if(!idata){
/* code here */
printf("goto here 1\n");
}
if(!bdata){
/* code here */
printf("goto here 2\n");
}
if(!pdata){
/* code here */
printf("goto here 3\n");
pdata = (float*)malloc(sizeof(float));
}
*pdata = 10;
free(pdata);
return 1;
}
Theo suy luận thông thường, khi khai báo mà không khởi tạo giá trị mặc định cụ thể cho biến thì chúng vẫn được tự động gắn các giá trị default như trên ví dụ trên, và vì vậy bạn thấy ngay các biểu trức if sẽ trả về kết quả là true.
Tuy nhiên trong thực tế (kinh nghiệm người viết bài này đã từng gặp phải) thì các giá trị thực sự mà các biến trên có được không giống như giá trị default đáng ra chúng phải bằng; có thể là idata != 0, bdata = true và pdata != NULL dẫn đến các logic của chương trình bị sai, hoặc chương trình bị crash (thao tác với con trỏ không hợp lệ).
Vì vậy khi gặp ngữ cảnh kiểu như trong vd trên thì tốt nhất bạn phải khởi tạo giá trị tường minh cho các biến:
int idata = 0;
bool bdata = false;
float *pdata = NULL;
Đặc biệt quan trọng trong lập trình C++, bạn nên khởi tạo giá trị cho tất cả các biến thuộc class trong hàm Constructor, và giải phóng bộ nhớ (nếu là con trỏ) trong hàm Destructor.
Ring buffer
1. Cấu trúc
2. Nguyên lý làm việc
3. Cách sử dụng
A single process/thread to process/thread buffer use case
Multiple processes/thread to process/thread use case
Single process/thread to multiple processes/thread use case
Single process/thread to multiple process/thread use case using a dispatcher and multiple queues
4. Source code sample
ringbufer.h
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdbool.h>
/*
* ringbuffer.h - C ring buffer (FIFO) interface.
*/
typedef struct ringbuffer_t
{
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
} ringbuffer_t;
bool ring_init(ringbuffer_t *cb, size_t capacity, size_t sz);
bool ring_free(ringbuffer_t *cb);
bool ring_push_head(ringbuffer_t *cb, const void *item);
bool ring_pop_tail(ringbuffer_t *cb, void *item);
#ifdef __cplusplus
}
#endif
#endif /* RINGBUFFER_H */
ringbuffer.c
#include "ringbuffer.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
bool ring_init(ringbuffer_t *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if(cb->buffer == NULL){
printf("ring_init FAIL ! \n");
return false;
}
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
return true;
}
bool ring_free(ringbuffer_t *cb)
{
if(cb->buffer){
free(cb->buffer);
cb->buffer = NULL;
}else{
return false;
}
return true;
}
bool ring_push_head(ringbuffer_t *cb, const void *item)
{
if(cb->count == cb->capacity){
printf("Ringbuffer is Full ! \n");
return false;
}
memcpy(cb->head, item, cb->sz);
cb->head = (char*)cb->head + cb->sz;
if(cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
return true;
}
bool ring_pop_tail(ringbuffer_t *cb, void *item)
{
if(cb->count == 0){
printf("Ringbuffer is Empty ! \n");
return false;
}
memcpy(item, cb->tail, cb->sz);
cb->tail = (char*)cb->tail + cb->sz;
if(cb->tail == cb->buffer_end)
cb->tail = cb->buffer;
cb->count--;
return true;
}
ringbuffer_test.c
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "ringbuffer.h"
#define CAPACITY 10
typedef struct data_t{
int idata;
float fdata;
}data_t;
ringbuffer_t ringbf;
int main(int argc, char **argv)
{
ring_init(&ringbf, CAPACITY, sizeof(data_t));
int i;
data_t tmpdata;
for(i = 0; i < CAPACITY; i++){
tmpdata.idata = i;
tmpdata.fdata = i+1;
ring_push_head(&ringbf, (void*)&tmpdata);
printf("number of items: %d \n", ringbf.count);
}
for(i = 0; i < CAPACITY; i++){
ring_pop_tail(&ringbf, (void*)&tmpdata);
printf("number of items: %d, idata: %d, fdata: %f \n", ringbf.count, tmpdata.idata, tmpdata.fdata);
}
ring_free(&ringbf);
return 0;
}
C/C++ Cách đặt tên: hàm, biến, cấu trúc dữ liệu, file sourrce code
1. Tên cấu trúc dữ liệu tự định nghĩa
+ Tên được đặt bằng chữ thường, ngăn cách bằng dấu gạch dưới "_", kết thúc bằng "_t"
+ Tên được đặt có chữ in hoa
2. Tên hàm, con trỏ hàm
+ Chữ thường, ngăn cách bằng dấu gạch dưới "_"
Con trỏ hàm:
+ Tên được đặt có chữ in hoa
Con trỏ hàm:
3. Tên biến
4. Tên file source code
Tên file source code cũng đặt theo phong cách tương tự như với tên hàm
C source file
C++ source file
+ Tên được đặt bằng chữ thường, ngăn cách bằng dấu gạch dưới "_", kết thúc bằng "_t"
enum player_status_t{
ST_TOPPED = 0;
ST_PLAYING,
ST_PAUSED,
ST_FFW, /* fast forward */
ST_FBW, /* fast backward */
}
union myname_t{
char full_name[64];
char alias[32];
}
struct persion_t{
char name[32];
int age;
}
+ Tên được đặt có chữ in hoa
enum PlayerStatus_t{
ST_TOPPED = 0;
ST_PLAYING,
ST_PAUSED,
ST_FFW, /* fast forward */
ST_FBW, /* fast backward */
}
2. Tên hàm, con trỏ hàm
void set_value(int a){
/* code here */
}
int get_value(){
int ret_value = 0;
/* code here */
return ret_value;
}
Con trỏ hàm:
typedef int (*math_operator_t)(int a, int b);
+ Tên được đặt có chữ in hoa
void setValue(int a){
/* code here */
}
int getValue(){
int ret_value = 0;
/* code here */
return ret_value;
}
Con trỏ hàm:
typedef int (*MathOperator_t)(int a, int b);
3. Tên biến
Có rất nhiều cách đặt tên cho biến, tùy vào trường hợp; có thể dựa vào phạm vi biến hoạt động, dựa vào kiểu dữ liệu của biến, etc ..., dưới đây llà một vài ví dụ tham khảo:
+ Biến global
Bắt đầu bằng "m_" hoặc "g_"
+ Biến global
Bắt đầu bằng "m_" hoặc "g_"
player_status_t m_player_status = ST_TOPPED;
hoặc
player_status_t g_player_status = ST_TOPPED;
+ Biến local
player_status_t l_player_status = ST_TOPPED;
+ Kiểu dữ liệu
+ ...
int ndata;
float fdata;
string strdata;
+ ...
4. Tên file source code
Tên file source code cũng đặt theo phong cách tương tự như với tên hàm
C source file
user_controller.h
user_controller.c
C++ source file
user_controller.hpp
user_controller.cpp
C/C++ Signal-slot
Signal-slot là một cơ chế để thực hiện việc một object này thông báo một sự kiện đến một object khác theo cơ chế tương tự như interrupt.
Các đối tượng muốn signal-slot được với nhau cần có một đăng ký kết nối trước, một object có thể cùng lúc có nhiều kết nối đến nhiều object khác, lưu ý định dạng dữ liệu giữa bên phát và nhận phải giống nhau.
Các đối tượng muốn signal-slot được với nhau cần có một đăng ký kết nối trước, một object có thể cùng lúc có nhiều kết nối đến nhiều object khác, lưu ý định dạng dữ liệu giữa bên phát và nhận phải giống nhau.
Khai báo class signal:
class Button:public sigslot::has_signals<Button>
{
//attributes
//methods
public __signals:
sigslot::signal<char*> touchEvent;
};
Khai báo class slot:
class View:public sigslot::has_slots<> { //attributes //methods public __slots: void onUpdate(
char *msg
){ cout << "recvmsg: " << msg <<endl; } };
Khai báo class vừa phát vừa nhận
class TransRecv:public sigslot::has_signals<TransRecv> , sigslot::has_slots<>
{
//attributes
//methods
public __signals: //phat signal cho object A
sigslot::signal<char *> touchPoint;
public __slots: //nhan signal tu object B
void onUpdate(float fdata, int idata);
};
Duới đây là một ví dụ:
sigslot.h (định nghĩa cơ chế signal-slot của QT Framework)
main.cpp
#include <iostream>
#include "sigslot.h"
using namespace std;
class Button:public sigslot::has_signals<Button>
{
public:
Button(){ };
virtual ~Button(){ };
void onClick(){
touchEvent.emit((char*)"Hello, I am button");
}
public __signals:
sigslot::signal<char*> touchEvent;
};
class View:public sigslot::has_slots<>
{
public:
View(){ };
virtual ~View(){ };
public __slots:
void onUpdate(char *msg){
cout << "recvmsg: " << msg <<endl;
}
};
int main(int argc, char **argv){
Button btn;
View view;
btn.touchEvent.connect(&view, &View::onUpdate);
btn.onClick();
return 1;
}
Compile & Execute:
$ g++ sigslot.h main.cpp
$ ./a.out
recvmsg: Hello, I am button
C/C++ Quản lý dữ liệu bằng Linked List và C++ Containers
Trong bất cứ project nào việc quản lý dữ liệu (dưới dạng danh sách) cũng rất quan trọng, vì thế nên cần nắng chắc các kiểu cấu trúc dữ liệu đã được đề cập ở các bài viết trước
+ Linked List
+ list
+ vector
+ queue
+ stack
+ Linked List
+ list
+ vector
+ queue
+ stack