Перейти к содержанию
    

Задача А. Работа над ошибками так сказать..

В этой версии маленькие строки (меньше LEN_BUF байт) копируются в обратном порядке в буфер и возвращается указатель на голову, а если строки большие, то перестановками решаем. Во втором варианте проверям чтоб строка не слишком большой была (меньше MAX_LEN_STR)

#include <stdio.h>

#define  LEN_BUF        100
#define  MAX_LEN_STR    1000

#define  _LenStr        buf[LEN_BUF-1]    // для хранения длины строки
#define  _TmpChar       buf[LEN_BUF-2]    // для хранения временных значений


char * reverse ( char *s ) {

   static char buf[LEN_BUF];              // буфер данных
   char *buf_pointer = &buf[LEN_BUF-1];   // определяем указатель, инициализируем значением адреса 

   char *beg = s;                         // определяем указатель, инициализируем адресом начала строки
   char *end;

   while ( (*buf_pointer-- = *s++) ) {    // копипастим
      
      if (buf_pointer <= &buf[0]) {       // если строка больше, чем буфер, то:
              
         while (*++s)
        ;    
                 
         if (s - beg > MAX_LEN_STR) 
            return "Error, overflow!";

         _LenStr = s - beg;               // Вычисляем длинну строки
         end = s-1;                       // Указатель на конец строки 
         
         do {                             // Меняем местами данные:
            _TmpChar = *beg;
            *beg = *end;
            *end = _TmpChar;
         } while (++beg < --end);
         
         return s - _LenStr;
      }
   }   

   return buf_pointer+2;
}


int main() {
   char s[]= "http://www.youtube.com/watch?v=cZjx6ItATW4";
   printf("%s\n", reverse (s) );
}

 

 

Не ясно еще как все же быть с одновременным вызовом функций

char str1[] = "String 1";
char str2[] = "String 2";
printf("%s %s\n", reverse(str1), reverse(str2));

Вариант который предлагает ReAl требует введения второго аргумента, что не очень айс

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

О майн Готт! Вы на листинг этого чуда хоть смотрели?

 

неа, не смотрел. а что там такого страшного?

последний вариант лучше предыдущих тем. что небольшие строки перевернутся без вызова strlen ,ведь даже в вашем варианте нужно вызвать strlen, а потом до половины размера строки ворочать значения. При варианте с буфером я НЕ вызываю strlen и получаю строку в доп. буфере, однако при большой строке переворачиваю строку без буфера, но при этом strlen также не пользую.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

неа, не смотрел. а что там такого страшного?

последний вариант лучше предыдущих тем. что небольшие строки перевернутся без вызова strlen ,ведь даже в вашем варианте нужно вызвать strlen, а потом до половины размера строки ворочать значения. При варианте с буфером я НЕ вызываю strlen и получаю строку в доп. буфере, однако при большой строке переворачиваю строку без буфера, но при этом strlen также не пользую.

Ниасилил. Strlen() хоть вызывай, хоть делай сам - оно выглядит одинаково.

Чем, извините, это всё лучше, если оно жрет памяти вдвое больше, не заточено под ASCIIZ, в >3раза больше число итераций. О майн Готт! :crying:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

K&R всплакнули бы от умиления...

Есть такая прилада профайлер, которая позволяет оценить время выполнения кода. Сравните результаты Вашей программы и поминавшихся выше вариантов со strlen().

Про наглядность кода и разбазаривание памяти ... пусть будет Задачей №3.

 

И попробуйте

int main() {
   char s[]= "http://www.youtube.com/watch?v=cZjx6ItATW4";
   char s1[]= "Пачиму-то не работает";
   printf("%s\n", reverse (s) );
   printf("%s\n", reverse (s1) );
}

 

UPD: сделайте s1 > LEN_BUF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

_Pasha , функция работает в двух так сказать режимах:

а) когда входная строка меньше по длине чем LEN_BUF

б) когда входная строк больше, чем LEN_BUF

 

в варианте "а" strlen не вызывается, но при этом крутится вся строка

в варианте "б" strlen не вызывается, но выполняются действия аналогичные по смыслу. после этого строка перебирается и меняются местами данные, кол-во итераций длина строки/2. Вот как и у вас по сути.

 

последняя реализация лучше тем ,что если на входе функции будут разные данные ,то в общем итоге получается оптимальнее!

И обратите внимание - алгоритм "б" дополняет собой алгоритм "а" !

 

K&R всплакнули бы от умиления...

Есть такая прилада профайлер, которая позволяет оценить время выполнения кода. Сравните результаты Вашей программы и поминавшихся выше вариантов со strlen().

Про наглядность кода и разбазаривание памяти ... пусть будет Задачей №3.

 

Я согласен. Предлагаю обсудить условия проведения соревнования на скорость и денежные призы. Итак!?

 

 

 

 

 

И попробуйте

int main() {
   char s[]= "http://www.youtube.com/watch?v=cZjx6ItATW4";
   char s1[]= "Пачиму-то не работает";
   printf("%s\n", reverse (s) );
   printf("%s\n", reverse (s1) );
}

 

ну не знаю ,кажись работает:

 

  char s[]= "http://www.youtube.com/watch?v=cZjx6ItATW4";
   char s1[]= "http://www.ebay.com/sch/i.html?_from=R40&_sacat=0&_nkw=pl-660&_sop=15";
   printf("%s\n", reverse (s) );
   printf("%s\n", reverse (s1) );

 

stdout:
4WTAtI6xjZc=v?hctaw/moc.ebutuoy.www//:ptth
51=pos_&066-lp=wkn_&0=tacas_&04R=morf_?lmth.i/hcs/moc.yabe.www//:ptth

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

int main() {
   char s[]= "http://www.youtube.com/watch?v=cZjx6ItATW4";
   char s1[]= "Пачиму-то не работает 1234567890 1234567890 1234567890 1234567890  1234567890 1234567890 1234567890 1234567890 1234567890 1234567890";
   printf("%s\n", reverse (s) );
   printf("%s\n", reverse (s1) );
}

D:\Work\Soft\Test>a
4WTAtI6xjZc=v?hctaw/moc.ebutuoy.www//:ptth
,=

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

#define  LEN_BUF        10

stdout:
4WTAtI6xjZc=v?hctaw/moc.ebutuoy.www//:ptth
0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 1111111111111111111111

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть указатель на указатель на char:

char **argv;

Как и чем его можно инициализировать и как (для чего) можно потом использовать? Что будет если я буду инкрементировать такой указатель на указатель?

К сож. с языком знакомлюсь рывками и че та совершенно запутался:(

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

обычно это имя переменной, которую получает main. Это массив указателей на строки - аргументы командной строки. В паре к ней идет argc - количество элементов в массиве.

 

void foo1(int argc, char **argv)
{
    while (argc--)
        printf("\"%s\"\n", argv++);
}

void foo(void)
{
    char *my_argv[] = {"Hello", "World", "one", "two", "four"};

    foo1(5, my_argv);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да поправят меня, если не прав :)

Указатель передается обычно тогда, когда функция может менять какие-то данные за пределами себя

Указатель за пределами какой-то функции тоже можно менять, не так ли? вот и передается указатель на этот указатель

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да поправят меня, если не прав :)

Указатель передается обычно тогда, когда функция может менять какие-то данные за пределами себя

Указатель за пределами какой-то функции тоже можно менять, не так ли? вот и передается указатель на этот указатель

Вы правы - при реализации связных списков, например, именно для этих целей передают указатель на указатель.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да поправят меня, если не прав :)

Формально - прав. Фактически - нет. Поправляю.

Вопрос был о char **argv.

Есть такая штука, как code convention. Именем argv принято обозначать статический массив указателей на строки. Поэтому упаси бог использовать его по тому же принципу, как используют при работе со списками. Например, здесь переменную answer назвать argv нельзя из соображений личной безопасности:

 

void true_of_false(char **answer, int is_true)
{
    *answer = is_true ? "True" : "False";
}

void foo(void)
{
    char *b_char;

    true_of_false(&b_char, 2013);
    printf("He said %s %s %s!\n", b_char, b_char, b_char);
}

Изменено пользователем igorle

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То что вы написали тут формально и гарантированно работать не будет ИМХО.

Т.к. вы инициализируете указатель адресом локальной не статической строки и используете этот указатель вне области жизни этих строк (в другом стековом фрейме).

Вот так все формальности будут соблюдены:

 

void true_of_false(char **answer, int is_true)
{
    static char True[]  = "True";
    static char False[] = "False";

    *answer = is_true ? True : False;
}

Хотя набрёл тут на такое:

4. Строковой литерал во всех прочих случаях

Во всех прочих случаях строковой литерал трактуется как НЕявно заведённый статический константный объект типа массив char'ов, инициализированный символами данного строкового литерала с включением неявного завершающего нуля, и далее взятие адреса на нулевой элемент данного объекта.

и немного из другой плюсатой оперы
"Память под строковые литералы выделяется статически, поэтому их возврат из функций безопасен" Б. Страуструп

Захотелось найти это в первоисточнике....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То что вы написали тут формально и гарантированно работать не будет ИМХО....

 

Это таки будет работать гарантировано. Потому что моя функция возвращает указатели на read only строки из секции data

Ваша функция тоже будет работать, но в ней есть бесполезное копирование строк из read only секции data в read write секцию. Недостатки

- в два раза увеличился объем памяти

- нет защиты от случайного изменения текста (оно в данном случае не желательно)

 

Посмотрите здесь

 

Ну и посыпаю голову пеплом по поводу опечатки в названии функции. Должно было быть true_or_false. Хотя так даже прикольно получилось, многозначительно.

Изменено пользователем igorle

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...