2.60.

Раз уж речь зашла о функции strdup (кстати, это стандартная функция), приведем еще одну функцию для сохранения строк.


    char *savefromto(register char *from, char *upto)

    {

            char *ptr, *s;

            if((ptr = (char *) malloc(upto - from + 1)) == NULL)

                    return NULL;

            for(s = ptr; from < upto; from++)

                    *s++ = *from;

            *s = '\0';

            return ptr;

    }

Сам символ (*upto) не сохраняется, а заменяется на '\0'.

2.61.

Упрощенный аналог функции printf.

    /*

     * Машинно - независимый printf() (упрощенный вариант).

     * printf - Форматный Вывод.

     */

    #include <stdio.h>

    #include <ctype.h>

    #include <varargs.h>

    #include <errno.h>

    #include <string.h>

    extern int errno;       /* код системной ошибки, формат %m */

    /* чтение значения числа */

    #define GETN(n,fmt)                      \

            n = 0;                           \

            while(isdigit(*fmt)){            \

                    n = n*10 + (*fmt - '0'); \

                    fmt++;                   \

            }

    void myprintf(fmt, va_alist)

           register char *fmt; va_dcl

    {

      va_list ap;

      char c, *s; int i;

      int width, /* минимальная ширина поля */

          prec,  /* макс. длина данного */

          sign,  /* выравнивание: 1 - вправо, -1 - влево */

          zero,  /* ширина поля начинается с 0 */

          glong; /* требуется длинное целое */

      va_start(ap);

      for(;;){

         while((c = *fmt++) != '%'){

           if( c == '\0' ) goto out;

           putchar(c);

         }

         sign = 1; zero = 0; glong = 0;

         if(*fmt == '-'){ sign = (-1); fmt++; }

         if(*fmt == '0'){ zero = 1; fmt++; }

         if(*fmt == '*'){

             width = va_arg(ap, int);

             if(width < 0){ width = -width; sign = -sign; }

             fmt++;

         }else{

             GETN(width, fmt);

         }

         width *= sign;

         if(*fmt == '.'){

            if(*++fmt == '*'){

               prec = va_arg(ap, int); fmt++;

            }else{

               GETN(prec, fmt);

            }

         }else prec = (-1); /* произвольно */

         if( *fmt == 'l' ){

            glong = 1; fmt++;

         }

         switch(c = *fmt++){

         case 'c':

            putchar(va_arg(ap, int)); break;

         case 's':

            prStr(width, prec, va_arg(ap, char *)); break;

         case 'm':

            prStr(width, prec, strerror(errno));    break;

            /* strerror преобразует код ошибки в строку-расшифровку */

         case 'u':

            prUnsigned(width,

                      glong ? va_arg(ap, unsigned long) :

                              (unsigned long) va_arg(ap, unsigned int),

                      10 /* base */, zero); break;

         case 'd':

            prInteger(width,

                      glong ? va_arg(ap, long) : (long) va_arg(ap, int),

                      10 /* base */, zero);  break;

         case 'o':

            prUnsigned(width,

                      glong ? va_arg(ap, unsigned long) :

                              (unsigned long) va_arg(ap, unsigned int),

                      8 /* base */, zero);   break;

         case 'x':

            prUnsigned(width,

                      glong ? va_arg(ap, unsigned long) :

                              (unsigned long) va_arg(ap, unsigned int),

                      16 /* base */, zero);  break;

         case 'X':

            prUnsigned(width,

                      glong ? va_arg(ap, unsigned long) :

                              (unsigned long) va_arg(ap, unsigned int),

                      -16 /* base */, zero); break;

         case 'b':

            prUnsigned(width,

                      glong ? va_arg(ap, unsigned long) :

                              (unsigned long) va_arg(ap, unsigned int),

                      2 /* base */, zero);   break;

         case 'a':  /* address */

            prUnsigned(width,

                      (long) (char *) va_arg(ap, char *),

                      16 /* base */, zero);  break;

         case 'A':  /* address */

            prUnsigned(width,

                      (long) (char *) va_arg(ap, char *),

                      -16 /* base */, zero); break;

         case 'r':

            prRoman(width, prec, va_arg(ap, int)); break;

         case '%':

            putchar('%'); break;

         default:

            putchar(c);   break;

         }

      }

    out:

      va_end(ap);

    }

    /* --------------------------------------------------------- */

    int strnlen(s, maxlen) char *s;

    {

            register n;

            for( n=0; *s && n < maxlen; n++, s++ );

            return n;

    }

    /* Печать строки */

    static prStr(width, prec, s) char *s;

    {

      int ln;         /* сколько символов выводить */

      int toLeft = 0; /* к какому краю прижимать   */

      if(s == NULL){ pr( "(NULL)", 6); return; }

      /* Измерить длину и обрубить длинную строку.

       * Дело в том, что строка может не иметь \0 на конце, тогда

       * strlen(s) может привести к обращению в запрещенные адреса */

      ln = (prec > 0 ? strnlen(s, prec) : strlen(s));

      /* ширина поля */

      if( ! width ) width = (prec > 0 ? prec : ln);

      if( width < 0){ width = -width; toLeft = 1; }

      if( width > ln){

            /* дополнить поле пробелами */

            if(toLeft){ pr(s, ln); prSpace(width - ln, ' ');  }

            else      { prSpace(width - ln, ' '); pr(s, ln);  }

      }     else      { pr(s, ln);                            }

    }

    /* Печать строки длиной l */

    static pr(s, ln) register char *s; register ln;

    {

      for( ; ln > 0 ; ln-- )

        putchar( *s++ );

    }

    /* Печать n символов c */

    static prSpace(n, c) register n; char c;{

      for( ; n > 0 ; n-- )

        putchar( c );

    }

    /* --------------------------------------------------------- */

    static char *ds;

    /* Римские цифры */

    static prRoman(w,p,n){

            char bd[60];

            ds = bd;

            if( n < 0 ){ n = -n; *ds++ = '-'; }

            prRdig(n,6);

            *ds = '\0';

            prStr(w, p, bd);

    }

    static prRdig(n, d){

            if( !n ) return;

            if( d ) prRdig( n/10, d - 2);

            tack(n%10, d);

    }

    static tack(n, d){

            static char im[] = "  MDCLXVI";

                    /* ..1000 500 100 50 10 5 1 */

            if( !n ) return;

            if( 1 <= n && n <= 3 ){

                    repeat(n, im[d+2]); return;

            }

            if( n == 4 )

                    *ds++ = im[d+2];

            if( n == 4 || n == 5 ){

                    *ds++ = im[d+1]; return;

            }

            if( 6 <= n && n <= 8 ){

                    *ds++ = im[d+1];

                    repeat(n - 5, im[d+2] );

                    return;

            }

            /* n == 9 */

            *ds++ = im[d+2]; *ds++ = im[d];

    }

    static repeat(n, c) char c;

    {       while( n-- > 0 ) *ds++ = c;      }

    /* --------------------------------------------------------- */

    static char aChar = 'A';

    static prInteger(w, n, base, zero) long n;

    {

            /* преобразуем число в строку */

            char bd[128];

            int neg = 0;    /* < 0 */

            if( n < 0 ){ neg = 1; n = -n; }

            if( base < 0 ){ base = -base; aChar = 'A'; }

            else          {               aChar = 'a'; }

            ds = bd; prUDig( n, base ); *ds = '\0';

            /* Теперь печатаем строку */

            prIntStr( bd, w, zero, neg );

    }

    static prUnsigned(w, n, base, zero) unsigned long n;

    {

            char bd[128];

            if( base < 0 ){ base = -base; aChar = 'A'; }

            else          {               aChar = 'a'; }

            ds = bd; prUDig( n, base ); *ds = '\0';

            /* Теперь печатаем строку */

            prIntStr( bd, w, zero, 0 );

    }

    static prUDig( n, base ) unsigned long n;

    {

            unsigned long aSign;

            if((aSign = n/base ) > 0 )

                    prUDig( aSign, base );

            aSign = n % base;

            *ds++ = (aSign < 10 ? '0' + aSign : aChar + (aSign - 10));

    }

    static prIntStr( s, width, zero, neg ) char *s;

    {

      int ln;         /* сколько символов выводить */

      int toLeft = 0; /* к какому краю прижимать   */

      ln = strlen(s);            /* длина строки s */

      /* Ширина поля: вычислить, если не указано явно */

      if( ! width ){

            width = ln;  /* ширина поля    */

            if( neg )   width++;         /* 1 символ для минуса */

      }

      if( width < 0 ){ width = -width; toLeft = 1; }

      if( ! neg ){  /* Положительное число */

        if(width > ln){

            if(toLeft){ pr(s, ln);              prSpace(width - ln, ' ');  }

            else      { prSpace(width - ln, zero ? '0' : ' '); pr(s, ln);  }

        }   else      { pr(s, ln);                                         }

      }else{        /* Отрицательное число */

        if(width > ln){

            /* Надо заполнять оставшуюся часть поля */

            width -- ; /* width содержит одну позицию для минуса */

            if(toLeft){ putchar('-'); pr(s, ln); prSpace(width - ln, ' ');  }

            else{

                    if( ! zero ){

                            prSpace(width - ln, ' '); putchar('-'); pr(s,ln);

                    } else {

                            putchar('-'); prSpace(width - ln, '0'); pr(s, ln);

                    }

            }

        }   else    {       putchar('-'); pr(s, ln);   }

      }

    }

    /* --------------------------------------------------------- */

    main(){

            int i, n;

            static char s[] = "Hello, world!\n";

            static char p[] = "Hello, world";

            long t = 7654321L;

            myprintf( "%%abc%Y\n");

            myprintf( "%s\n",        "abs" );

            myprintf( "%5s|\n",       "abs" );

            myprintf( "%-5s|\n",      "abs" );

            myprintf( "%5s|\n",       "xyzXYZ" );

            myprintf( "%-5s|\n",      "xyzXYZ" );

            myprintf( "%5.5s|\n",     "xyzXYZ" );

            myprintf( "%-5.5s|\n",    "xyzXYZ" );

            myprintf( "%r\n",       444 );

            myprintf( "%r\n",       999 );

            myprintf( "%r\n",       16 );

            myprintf( "%r\n",       18 );

            myprintf( "%r\n",       479 );

            myprintf( "%d\n",  1234 );

            myprintf( "%d\n",  -1234 );

            myprintf( "%ld\n",  97487483 );

            myprintf( "%2d|%2d|\n",   1, -3 );

            myprintf( "%-2d|%-2d|\n", 1, -3 );

            myprintf( "%02d|%2d|\n",   1, -3 );

            myprintf( "%-02d|%-2d|\n", 1, -3 );

            myprintf( "%5d|\n",   -12 );

            myprintf( "%05d|\n",  -12 );

            myprintf( "%-5d|\n",  -12 );

            myprintf( "%-05d|\n", -12 );

            for( i = -6; i < 6; i++ )

                 myprintf( "width=%2d|%0*d|%0*d|%*d|%*d|\n", i,

                   i,  123,  i, -123, i,  123, i, -123);

            myprintf( "%s at location %a\n", s, s );

            myprintf( "%ld\n", t );

            n = 1; t = 1L;

            for( i=0; i < 34; i++ ){

         myprintf( "for %2d   |%016b|%d|%u|\n\t |%032lb|%ld|%lu|\n",

                          i,       n, n, n,           t,  t,  t );

                    n *= 2;

                    t *= 2;

            }

            myprintf( "%8x %8X\n", 7777, 7777 );

            myprintf( "|%s|\n", p );

            myprintf( "|%10s|\n", p );

            myprintf( "|%-10s|\n", p );

            myprintf( "|%20s|\n", p );

            myprintf( "|%-20s|\n", p );

            myprintf( "|%20.10s|\n", p );

            myprintf( "|%-20.10s|\n", p );

            myprintf( "|%.10s|\n", p );

    }

Выдача этой программы:

    %abcY

    abs

      abs|

    abs  |

    xyzXYZ|

    xyzXYZ|

    xyzXY|

    xyzXY|

    CDXLIV

    CMXCIX

    XVI

    XVIII

    CDLXXIX

    1234

    -1234

    97487483

     1|-3|

    1 |-3|

    01|-3|

    1 |-3|

      -12|

    -0012|

    -12  |

    -12  |

    width=-6|123   |-123  |123   |-123  |

    width=-5|123  |-123 |123  |-123 |

    width=-4|123 |-123|123 |-123|

    width=-3|123|-123|123|-123|

    width=-2|123|-123|123|-123|

    width=-1|123|-123|123|-123|

    width= 0|123|-123|123|-123|

    width= 1|123|-123|123|-123|

    width= 2|123|-123|123|-123|

    width= 3|123|-123|123|-123|

    width= 4|0123|-123| 123|-123|

    width= 5|00123|-0123|  123| -123|

    Hello, world!

     at location 400980

    7654321

    for  0   |0000000000000001|1|1|

             |00000000000000000000000000000001|1|1|

    for  1   |0000000000000010|2|2|

             |00000000000000000000000000000010|2|2|

    for  2   |0000000000000100|4|4|

             |00000000000000000000000000000100|4|4|

    for  3   |0000000000001000|8|8|

             |00000000000000000000000000001000|8|8|

    for  4   |0000000000010000|16|16|

             |00000000000000000000000000010000|16|16|

    for  5   |0000000000100000|32|32|

             |00000000000000000000000000100000|32|32|

    for  6   |0000000001000000|64|64|

             |00000000000000000000000001000000|64|64|

    for  7   |0000000010000000|128|128|

             |00000000000000000000000010000000|128|128|

    for  8   |0000000100000000|256|256|

             |00000000000000000000000100000000|256|256|

    for  9   |0000001000000000|512|512|

             |00000000000000000000001000000000|512|512|

    for 10   |0000010000000000|1024|1024|

             |00000000000000000000010000000000|1024|1024|

    for 11   |0000100000000000|2048|2048|

             |00000000000000000000100000000000|2048|2048|

    for 12   |0001000000000000|4096|4096|

             |00000000000000000001000000000000|4096|4096|

    for 13   |0010000000000000|8192|8192|

             |00000000000000000010000000000000|8192|8192|

    for 14   |0100000000000000|16384|16384|

             |00000000000000000100000000000000|16384|16384|

    for 15   |1000000000000000|32768|32768|

             |00000000000000001000000000000000|32768|32768|

    for 16   |10000000000000000|65536|65536|

             |00000000000000010000000000000000|65536|65536|

    for 17   |100000000000000000|131072|131072|

             |00000000000000100000000000000000|131072|131072|

    for 18   |1000000000000000000|262144|262144|

             |00000000000001000000000000000000|262144|262144|

    for 19   |10000000000000000000|524288|524288|

             |00000000000010000000000000000000|524288|524288|

    for 20   |100000000000000000000|1048576|1048576|

             |00000000000100000000000000000000|1048576|1048576|

    for 21   |1000000000000000000000|2097152|2097152|

             |00000000001000000000000000000000|2097152|2097152|

    for 22   |10000000000000000000000|4194304|4194304|

             |00000000010000000000000000000000|4194304|4194304|

    for 23   |100000000000000000000000|8388608|8388608|

             |00000000100000000000000000000000|8388608|8388608|

    for 24   |1000000000000000000000000|16777216|16777216|

             |00000001000000000000000000000000|16777216|16777216|

    for 25   |10000000000000000000000000|33554432|33554432|

             |00000010000000000000000000000000|33554432|33554432|

    for 26   |100000000000000000000000000|67108864|67108864|

             |00000100000000000000000000000000|67108864|67108864|

    for 27   |1000000000000000000000000000|134217728|134217728|

             |00001000000000000000000000000000|134217728|134217728|

    for 28   |10000000000000000000000000000|268435456|268435456|

             |00010000000000000000000000000000|268435456|268435456|

    for 29   |100000000000000000000000000000|536870912|536870912|

             |00100000000000000000000000000000|536870912|536870912|

    for 30   |1000000000000000000000000000000|1073741824|1073741824|

             |01000000000000000000000000000000|1073741824|1073741824|

    for 31   |10000000000000000000000000000000|-2147483648|2147483648|

             |10000000000000000000000000000000|-2147483648|2147483648|

    for 32   |0000000000000000|0|0|

             |00000000000000000000000000000000|0|0|

    for 33   |0000000000000000|0|0|

             |00000000000000000000000000000000|0|0|

        1e61     1E61

    |Hello, world|

    |Hello, world|

    |Hello, world|

    |        Hello, world|

    |Hello, world        |

    |          Hello, wor|

    |Hello, wor          |

    |Hello, wor|

2.62.

Рассмотрим программу суммирования векторов:

    int A[1024], B[1024], C[1024];

            ...

    for(i=0; i < 1024; i++) C[i] = A[i] + B[i];

А почему бы не

    for(i=1024-1; i >=0 ; --i) ...;

А почему бы не в произвольном порядке?

    foreach i in (0..1023) ...;

Данный пример показывает, что некоторые операции обладают врожденным паралеллизмом, ведь все 1024 сложений можно было бы выполнять параллельно! Однако тупой компилятор будет складывать их именно в том порядке, в котором вы ему велели. Только самые современные компиляторы на многопроцессорных системах умеют автоматически распараллеливать такие циклы. Сам язык Си не содержит средств указания параллельности (разве что снова - библиотеки и системные вызовы для этого).

[Назад][Содержание][Вперед]

Используются технологии uCoz