ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Так тогда strtol вам и нужна в чистом ее виде... У этой функции 3 параметра. Указатель, ползущий по строке, у меня в глобальной структуре имеется, его передавать не нужно. Если попалась строка "-300голов", то мне логично промотать его до space-символов, а не остановиться на "г". Не буду нарушать созданную логику, сделаю, как хотел. Правильно, указатель на локальную статическую переменную выдавать и использовать снаружи функции можно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба strtol опасна в плане RTOS, функции этого ряда могут внутри себя лезть в глобальный heap и в глобальные переменные. Это с какого перепуга то? Только errno, но это классика. _CODE_ACCESS long strtol(const char *st, char **endptr, int base) { register unsigned long result = 0; register unsigned int uns_base; register char cp; register const char *fst = st; int digits = 0; unsigned long sign = 0; unsigned long max_prev_result; unsigned long max_curr_addval; unsigned long range_limit; while (_isspace(*fst)) ++fst; /* SKIP WHITE SPACE */ if ((cp = *fst) == '-') { sign = 1; cp = *++fst; } else if (cp == '+') cp = *++fst; if (base > 36) base = 0; /*-------------------------------------------------------------------*/ /* DETERMINE BASE IF ZERO BASE ASKED FOR. */ /*-------------------------------------------------------------------*/ switch (base) { case 0 : if (cp != '0') base = 10; else if ((cp = *++fst) == 'x' || cp == 'X') if (_isxdigit(fst[1])) { base = 16; cp = *++fst; } else { base = 10; cp = *--fst; } else { base = 8; if (cp < '0' || cp > '7') cp = *--fst; } break; case 16 : if (cp == '0' && ((fst[1] == 'x') || (fst[1] == 'X')) && _isxdigit(fst[2])) cp = *(fst += 2); } /*-------------------------------------------------------------------*/ /* DETERMINE VALUES NEEDED TO DETECT RANGE ERROR. THE MAX UNSIGNED */ /* VALUE THAT IS IN RANGE IS BASED ON THE SIGN OF THE INPUT STRING: */ /* sign == 1 - RESULT WILL BE NEGATIVE, SO MUST BE <= LONG_MAX+1 */ /* sign == 0 - RESULT WILL BE POSITIVE, SO MUST BE <= LONG_MAX */ /* SO range_limit is LONG_MAX + sign. */ /* */ /* ALSO NEED max_prev_result AND max_curr_addval WHERE: */ /* max_prev_result * uns_base + max_curr_addval == range_limit */ /* */ /* THIS ALLOWS US TO TEST FOR RANGE ERROR BEFORE WE COMPUTE THE NEXT */ /* RESULT. WE HAVE TWO CASES: */ /* - PREVIOUS result IS GREATER THAN max_prev_result, SO NEXT */ /* RESULT MUST BE OUT OF RANGE. */ /* - PREVIOUS result IS EQUAL TO max_prev_result, SO NEXT RESULT */ /* IS OUT OF RANGE IF addval > max_curr_addval. */ /*-------------------------------------------------------------------*/ uns_base = (unsigned int) base; range_limit = (unsigned long)LONG_MAX + sign; max_prev_result = range_limit / uns_base; max_curr_addval = range_limit % uns_base; /*-------------------------------------------------------------------*/ /* CONVERT THE NUMBER USING THE SPECIFIED BASE. */ /*-------------------------------------------------------------------*/ for (;; cp = *++fst) { register unsigned long addval; if (!((_isdigit(cp) && (addval = cp - '0') < uns_base) || (_isupper(cp) && (addval = cp - 'A' + 10) < uns_base) || (_islower(cp) && (addval = cp - 'a' + 10) < uns_base))) break; /*--------------------------------------------------------------*/ /* CHECK OVERFLOW STATUS BEFORE COMPUTATION. */ /* result CONTAINS THE RESULT OF THE PREVIOUS COMPUTATION */ /*--------------------------------------------------------------*/ if (result > max_prev_result || (result == max_prev_result && addval > max_curr_addval)) { /* SET ERRNO */ errno = ERANGE; if (endptr) *endptr = (char *)st; return sign ? LONG_MIN : LONG_MAX; } /*--------------------------------------------------------------*/ /* COMPUTE NEXT RESULT. */ /*--------------------------------------------------------------*/ result = result * uns_base + addval; digits++; } /*-------------------------------------------------------------------*/ /* MARK THE END OF THE CONVERTED INPUT. NEGATE THE RESULT IF A */ /* MINUS SIGN WAS SEEN. */ /*-------------------------------------------------------------------*/ if (endptr) *endptr = (char *)(digits ? fst : st); if (sign) return (long)-result; return (long)result; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Но если до красоты, то на мой эстетский взгляд самое красивое все делать в глобальных структурах. Т.е. объединять глобальные переменные в глобальные структуры. Делаю так. :beer: Вот, запнулся на числе после atoi. Не гармонирует с остальными членами. :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Правильно, указатель на локальную статическую переменную выдавать и использовать снаружи функции можно? Теоретически, можно, но не нужно. Сделайте тогда статическую глобальную переменную, ее и видно никому не будет снаружи, и возвращать указатель на нее без проблем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Теоретически, можно, но не нужно. Сделайте тогда статическую глобальную переменную, ее и видно никому не будет снаружи, и возвращать указатель на нее без проблем. Ок! Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Ок! Спасибо. Только не забудьте, что если вдруг многопоточность... То кирдык. Надо будет крит. секцию ставить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Только не забудьте, что если вдруг многопоточность... То кирдык. Надо будет крит. секцию ставить. Запись в буфер и разбор с ответом идут по-очереди, типа пинг-понга. Над внеочередными событиями пока не задумывался, сделать бы хоть так. Разбор с ответом - один тред. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Разбор с ответом - один тред. Это сейчас :) А потом захотите в другом треде что-то сделать этой же ф-цией, и будете сильно удивлены странными глюками.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Кстати, как это слово правильно использовать, переводить - thread. Перевод найти легко - "нить", но что именно использовать? Это сейчас :) А потом захотите в другом треде что-то сделать этой же ф-цией, и будете сильно удивлены странными глюками.... Не захочу, она у меня с префиксом, однозначно определяющем принадлежность к данной задаче. Переменную int32_t тоже впихну в одну из структур, принадлежащих задаче. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Кстати, как это слово правильно использовать, переводить - thread. Перевод найти легко - "нить", но что именно использовать? Поток, это по-нашему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Поток, это по-нашему. Со stream'ом вступает в конфликт. Ок, поток так поток. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Возвращать результат из функции, храня его во внутреннем статическом объекте можно, но есть серьёзные недостатки: 1. Функция получается нереентерабельной. 2. Результат может быть не когерентен вызову даже в момент возврата из функции (опять же из-за возможности асинхронного вызова функции). 3. В случае возвращаемого целого обычный возврат по значению будет, скорее всего, эффективней. 4. Есть рабочий конкурент - strtol, про него уже сказали, ни разу не сложная функция, всяко проще, чем самому огороды городить. Не нравится она в таком виде, написать обёртку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Я же указатель возвращаю, не сам объект. И указатель может быть NULL, в случае ошибки. Мне так удобно. Вы правы! Я уже с этим статиком накололся. Не сбросил число от предыдущей обработки, увеличил прошлое. От "бреда" избавился. Работает глобальная переменная, как надо. Может, если статическую переменную каждый раз инициализировать при вызове функции, и сгодилось бы. Но красоты в этом я уже не вижу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Работает глобальная переменная, как надо.В чем ее отличие от статической внутри функции? Кроме того, что ее кто угодно поломать может и ему за это ничего не будет. Если функция возвращает указатель на свою статическую переменную как указатель на константу, то компилятор хоть по рукам даст при попытке эту переменную изменить извне. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Slash 0 5 декабря, 2014 Опубликовано 5 декабря, 2014 · Жалоба Указатель на переменную успеха/неудачи передавать в качестве параметра. Объявление: double toDouble(const char * str, bool * ok); Применение: const char * str = "0.252"; bool ok; double var = toDouble(str, &ok); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться