Буратино 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба Задача А. Работа над ошибками так сказать.. В этой версии маленькие строки (меньше 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 требует введения второго аргумента, что не очень айс Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба О майн Готт! Вы на листинг этого чуда хоть смотрели? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Буратино 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба О майн Готт! Вы на листинг этого чуда хоть смотрели? неа, не смотрел. а что там такого страшного? последний вариант лучше предыдущих тем. что небольшие строки перевернутся без вызова strlen ,ведь даже в вашем варианте нужно вызвать strlen, а потом до половины размера строки ворочать значения. При варианте с буфером я НЕ вызываю strlen и получаю строку в доп. буфере, однако при большой строке переворачиваю строку без буфера, но при этом strlen также не пользую. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба неа, не смотрел. а что там такого страшного? последний вариант лучше предыдущих тем. что небольшие строки перевернутся без вызова strlen ,ведь даже в вашем варианте нужно вызвать strlen, а потом до половины размера строки ворочать значения. При варианте с буфером я НЕ вызываю strlen и получаю строку в доп. буфере, однако при большой строке переворачиваю строку без буфера, но при этом strlen также не пользую. Ниасилил. Strlen() хоть вызывай, хоть делай сам - оно выглядит одинаково. Чем, извините, это всё лучше, если оно жрет памяти вдвое больше, не заточено под ASCIIZ, в >3раза больше число итераций. О майн Готт! :crying: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xemul 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Буратино 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба _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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xemul 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба 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 ,= Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Буратино 0 29 января, 2013 Опубликовано 29 января, 2013 · Жалоба #define LEN_BUF 10 stdout: 4WTAtI6xjZc=v?hctaw/moc.ebutuoy.www//:ptth 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 1111111111111111111111 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Буратино 0 27 февраля, 2013 Опубликовано 27 февраля, 2013 · Жалоба Есть указатель на указатель на char: char **argv; Как и чем его можно инициализировать и как (для чего) можно потом использовать? Что будет если я буду инкрементировать такой указатель на указатель? К сож. с языком знакомлюсь рывками и че та совершенно запутался:( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 27 февраля, 2013 Опубликовано 27 февраля, 2013 · Жалоба обычно это имя переменной, которую получает 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); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
toweroff 1 27 февраля, 2013 Опубликовано 27 февраля, 2013 · Жалоба Да поправят меня, если не прав :) Указатель передается обычно тогда, когда функция может менять какие-то данные за пределами себя Указатель за пределами какой-то функции тоже можно менять, не так ли? вот и передается указатель на этот указатель Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lotor 0 28 февраля, 2013 Опубликовано 28 февраля, 2013 · Жалоба Да поправят меня, если не прав :) Указатель передается обычно тогда, когда функция может менять какие-то данные за пределами себя Указатель за пределами какой-то функции тоже можно менять, не так ли? вот и передается указатель на этот указатель Вы правы - при реализации связных списков, например, именно для этих целей передают указатель на указатель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 28 февраля, 2013 Опубликовано 28 февраля, 2013 (изменено) · Жалоба Да поправят меня, если не прав :) Формально - прав. Фактически - нет. Поправляю. Вопрос был о 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); } Изменено 28 февраля, 2013 пользователем igorle Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 28 февраля, 2013 Опубликовано 28 февраля, 2013 · Жалоба То что вы написали тут формально и гарантированно работать не будет ИМХО. Т.к. вы инициализируете указатель адресом локальной не статической строки и используете этот указатель вне области жизни этих строк (в другом стековом фрейме). Вот так все формальности будут соблюдены: void true_of_false(char **answer, int is_true) { static char True[] = "True"; static char False[] = "False"; *answer = is_true ? True : False; } Хотя набрёл тут на такое: 4. Строковой литерал во всех прочих случаях Во всех прочих случаях строковой литерал трактуется как НЕявно заведённый статический константный объект типа массив char'ов, инициализированный символами данного строкового литерала с включением неявного завершающего нуля, и далее взятие адреса на нулевой элемент данного объекта. и немного из другой плюсатой оперы"Память под строковые литералы выделяется статически, поэтому их возврат из функций безопасен" Б. Страуструп Захотелось найти это в первоисточнике.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 28 февраля, 2013 Опубликовано 28 февраля, 2013 (изменено) · Жалоба То что вы написали тут формально и гарантированно работать не будет ИМХО.... Это таки будет работать гарантировано. Потому что моя функция возвращает указатели на read only строки из секции data Ваша функция тоже будет работать, но в ней есть бесполезное копирование строк из read only секции data в read write секцию. Недостатки - в два раза увеличился объем памяти - нет защиты от случайного изменения текста (оно в данном случае не желательно) Посмотрите здесь Ну и посыпаю голову пеплом по поводу опечатки в названии функции. Должно было быть true_or_false. Хотя так даже прикольно получилось, многозначительно. Изменено 28 февраля, 2013 пользователем igorle Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться