Показаны сообщения с ярлыком code snippets. Показать все сообщения
Показаны сообщения с ярлыком code snippets. Показать все сообщения

понедельник, 9 ноября 2009 г.

Create argc+argv from string

очередной быстро сделаный велосипед. Такой себе переходничек из обычной С-шной строки в пару argc/argc. Понадобился когда по-быстрому переходил с использования коммандрой строки на конфиг файл.

input - исходная строка содержащая разделеный пробелами значения
buffer - память используемая под значения в output
char** output - собственно результат (argv, argc вернется как возвращаемое значение ф-ции)
+ константы максимального размера буфера
ф-ция возвращаес количество слов в output


1 /**
2 * create int arc + char** arv from a sting
3 */


4 int prepare_prog_options(const char* input,
5 char* buffer,

6 int buffer_size,
7 const char** output,

8 int output_buff_size)
9 {
10 int buffer_pos = 0;

11 int argc = 0;
12 char* word_start = buffer;

13 if(NULL == input){
14 output[0] = NULL;

15 return 0;
16 }
17 --buffer_size;//we need one cell for last zero

18 --output_buff_size;
19 while(buffer_size > buffer_pos &&

20 output_buff_size > argc){
21 if(isspace(*input) || 0 == *input){

22 if(word_start != buffer + buffer_pos){

23 //current word have symbols
24 buffer[buffer_pos] = 0;
25 buffer_pos++;

26 output[argc] = word_start;
27 output[argc+1] = NULL;

28 ++argc;
29 word_start = buffer + buffer_pos;

30 }
31 if(0 == *input)

32 break;
33 ++input;
34 continue;

35 }
36 buffer[buffer_pos] = *input;

37 buffer[buffer_pos+1] = 0;
38 ++buffer_pos;

39 ++input;
40 }
41 return argc;

42 }




Пример использования:
char* str = " --test --hname mainHost --t 125";

char
buffer[1024];
char
* argv2[15];
int
argc = prepare_prog_options(str, buffer, 1024,argv2,15);


зы: если кто надумет использовать - делать это вдумчиво, код писался ночью и еще не проверялся со всеми вариантами(и не будет, в моем случае строки очень простые)

ззы: проверил, поправил определение пробела, вообщем на всех моих кейсах оно работает нормально

вторник, 24 марта 2009 г.

Interview Question: implement itoa

see source code

относительно atoi на интервью, меня поправили, имелось в виду itoa, но назвали ее atoi.
Вопрос про itoa популярен, но реализация через деление не интересна, слишком скучно и просто. Поэтому реализовал без использования умножения и деления, только сложение и работа со строками.

ф-ция получилась короткой - табличка с уже подсчитаными степенями двойки и куча сложений. Почти половину в этом коде занимает реализация добавления первого символа в строку без использованя дополнительного буфера. А весь magic происходит в SymbolicAdd.

char* power_of_two[] =

{

    "1","2","4","8", "16","32","64","128",

    "256","512","1024","2048","4096","8192","16384","32768",


//custom itoa implementation limited to radix 10

//idea is: each digit in position N in binary value means

//"add Digit(1 or 0) * 2^N to common sum" 

//lets do it, but use symbol strings instead of binary values

char* CustomITOA(int value, char *dst)

{

    bool below_zero = value < 0;

    if(below_zero)

        value *= -1;

 

    *dst = '0';

    *(dst+1) = 0;

    int nbins = sizeof(int) * 8 - 1;

    for(int i=0; i < nbins; i++)

    {

        if(value & 0x1)

        {

            SymbolicAdd(dst, dst, power_of_two[i]);

        }

        value = value >> 1;

    }

    if(below_zero)

    {

        //add leading "-" to result string

        char cbuffer_first = '-';

        char cbuffer_second = cbuffer_first;

        char* str_cursor = dst;

        do

        {

            cbuffer_second = *str_cursor;

            *str_cursor = cbuffer_first;

            if(0 == cbuffer_first)

                break;

            cbuffer_first = cbuffer_second;

            ++str_cursor;

        }

        while(true);

    }

    return dst;

}



Получилось просто, но SymbolicAdd намного сложнее(детали в сырцах). Что она делает: берет две строки вида "125", "236" и возвращает строку "361", а всередини реализован своеобразный алгоритм сложения в столбик.

понедельник, 23 марта 2009 г.

реализовать atoi на интервью

на developers.org.ua заметил впечатления от проходжения интервью в R&D центр самсунга в Киеве, если опустить общее негативное впечатление програмера от самого процесса, и то что судя по цифрам набрать они пытаються по-дешевле,то из интересного там упоминание одного из вопросов - написать atoi на бумажке,
Вот мой вариант сделаный на коленках (проверка на переполнение опущена) в основном из спортивного интереса(своеобразная разминка от багфиксинга). Алгоритм - первое что пришло в голову, возможно есть и более эфективные:

#define SPACE_SYM ' '
#define MINUS_SYM '-'
 
int atoi_custom(char* src)
{
    int result = 0; //really returns int value
    char* current_symbol = src;
    int digit_indx = 1;
 
    if (!src)
        return 0;
    //let`s treat first word in string as a decimal number
    bool first_symb_found = false;
    // second part of the IF expression can be optimized, 
    //but it is more human readable as is 
    while(*current_symbol != 0 && 
           (SPACE_SYM != *current_symbol || !first_symb_found))
    {
            //ignore leading spaces
        if(!first_symb_found && *current_symbol != SPACE_SYM)
            first_symb_found = true;
        current_symbol++;
    }
      //string not found, exit
    if(current_symbol == src)
        return 0;
 
    for(current_symbol--; 
          current_symbol >= src && SPACE_SYM != *current_symbol;
          digit_indx*=10, current_symbol--)    
    {
        //process negative integers, leading '-' is symbol of it.
        if(MINUS_SYM == *current_symbol)
        {
            if(src == current_symbol ||
                     SPACE_SYM == *(current_symbol - 1))
                return (int)(-1 * result);
            else
                return 0;//incorrect syntax
        }
        //convert symbol into integer, 0 is 0x30, 1 is 0x31, etc
        int val = (int)*current_symbol - 0x30; 
        if(val <0 || val >9)//it is not a number
            return 0;        
        result += val * digit_indx;
    }
    return result;
}

пятница, 25 июля 2008 г.

Save blob from database into a file

Програмисту часто приходиться писать достаточно тривиальные куски кода, на которые и время жалко тратить(а там могут быть последовательные вызовы к редко используемому/слабознакомому API ) и в отдельные библиотечки выделять не хочеться. Повторное использование такого кода возможно на основе code snippets.
Code snippet - кусок повторно используемого кода, функция, или несколько взаимосвязаных ф-ций. Он относительно небольшого размера, самодостаточен, выполняет одну задачу и легко интегрируется в проект с помощью минимальный работы напильником. Основное преимущество подхода - код очень просто интегрировать в проект, нету лишнего кода и зависимостей, можно быстро подправить форматирование и code convention. В визул студии есть даже поддержка для библиотек таких Code snippets
Под тегом "code snippets" буде выкладывать такой код.

Как не странно, учитывая что с++ основной язык програмирования, первый сниппет будет на c# и описывает работу с базой данных и BLOB полями в ней. Этот код был написан пару недель назад для автоматизации рутины, шарп и языка типа питона тут более применимы.

Получить BLOB поле (небольшой файл) из базы данных (MSSQL) и сохранить его в файл.
для использования заменить параметры в connection string, SQL и путь к файлу с результатом. Данный код предпологает, что sql вернет только один файл за раз, но переделать на обработку нескольких файлов его очень просто.
   1:  public void BLOB2File()
   2:  {            
   3:      SqlConnection Conn = new SqlConnection("server=SERVERNAME;uid=USERNAME;pwd=PWD;database=DB_NAME");
   4:      SqlCommand Cmd = new SqlCommand("SELECT FileName, FileImage FROM TARGET_TABLE WHERE (FILE_ID = NUMBER", Conn);
   5:      Cmd.CommandType = CommandType.Text;
   6:      Conn.Open();
   7:      SqlDataReader Reader = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
   8:   
   9:      bool rdSatte = Reader.Read();
  10:   
  11:      FileStream FStream = null;
  12:      string str = Reader["FileName"].ToString();
  13:      FStream = new FileStream(@"c:\temp\" + str, FileMode.OpenOrCreate, FileAccess.Write);
  14:      byte[] Binary = null;
  15:      
  16:      Binary = (Reader["FileImage"]) as byte[];
  17:   
  18:      MemoryStream MStream = new MemoryStream(Binary);
  19:      BinaryWriter BWriter = new BinaryWriter(FStream);
  20:      const int ChunkSize = 100;
  21:      int SizeToWrite = ChunkSize;
  22:      for (int i = 0; i < Binary.GetUpperBound(0) - 1; i = i + ChunkSize)
  23:      {
  24:          if (i + ChunkSize >= Binary.Length)
  25:              SizeToWrite = Binary.Length - i;
  26:          byte[] Chunk = new byte[SizeToWrite];
  27:          MStream.Read(Chunk, 0, SizeToWrite);
  28:          BWriter.Write(Chunk);
  29:          BWriter.Flush();
  30:      }
  31:      BWriter.Close();
  32:      FStream.Close();
  33:      FStream.Dispose();
  34:  }