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

 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 findsed

 #!/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  
   


Saturday, November 14, 2015

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.

Thursday, July 2, 2015

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;  
 }  
   


Sunday, June 28, 2015

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"

 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
+ Chữ thường, ngăn cách bằng dấu gạch dưới "_"

 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_"

 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.



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  
   



Wednesday, May 20, 2015

C/C++ Templates

C/C++ Templates
Saturday, May 2, 2015

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

- Copyright © Lập trình hệ thống nhúng Linux . Powered by Luong Duy Ninh -