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

Выдать из функции указатель на ее статическую переменную

Так тогда strtol вам и нужна в чистом ее виде...

У этой функции 3 параметра.

Указатель, ползущий по строке, у меня в глобальной структуре имеется, его передавать не нужно.

Если попалась строка "-300голов", то мне логично промотать его до space-символов, а не остановиться на "г".

Не буду нарушать созданную логику, сделаю, как хотел.

Правильно, указатель на локальную статическую переменную выдавать и использовать снаружи функции можно?

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


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

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;
}

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


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

Но если до красоты, то на мой эстетский взгляд самое красивое все делать в глобальных структурах. Т.е. объединять глобальные переменные в глобальные структуры.

Делаю так. :beer: Вот, запнулся на числе после atoi. Не гармонирует с остальными членами. :rolleyes:

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


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

Правильно, указатель на локальную статическую переменную выдавать и использовать снаружи функции можно?

Теоретически, можно, но не нужно. Сделайте тогда статическую глобальную переменную, ее и видно никому не будет снаружи, и возвращать указатель на нее без проблем.

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


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

Теоретически, можно, но не нужно. Сделайте тогда статическую глобальную переменную, ее и видно никому не будет снаружи, и возвращать указатель на нее без проблем.

Ок! Спасибо.

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


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

Ок! Спасибо.

Только не забудьте, что если вдруг многопоточность... То кирдык. Надо будет крит. секцию ставить.

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


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

Только не забудьте, что если вдруг многопоточность... То кирдык. Надо будет крит. секцию ставить.

Запись в буфер и разбор с ответом идут по-очереди, типа пинг-понга. Над внеочередными событиями пока не задумывался, сделать бы хоть так. Разбор с ответом - один тред.

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


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

Разбор с ответом - один тред.

Это сейчас :) А потом захотите в другом треде что-то сделать этой же ф-цией, и будете сильно удивлены странными глюками....

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


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

Кстати, как это слово правильно использовать, переводить - thread. Перевод найти легко - "нить", но что именно использовать?

 

Это сейчас :) А потом захотите в другом треде что-то сделать этой же ф-цией, и будете сильно удивлены странными глюками....

Не захочу, она у меня с префиксом, однозначно определяющем принадлежность к данной задаче.

Переменную int32_t тоже впихну в одну из структур, принадлежащих задаче. :)

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


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

Кстати, как это слово правильно использовать, переводить - thread. Перевод найти легко - "нить", но что именно использовать?

Поток, это по-нашему.

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


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

Поток, это по-нашему.

Со stream'ом вступает в конфликт. Ок, поток так поток. :biggrin:

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


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

Возвращать результат из функции, храня его во внутреннем статическом объекте можно, но есть серьёзные недостатки:

 

1. Функция получается нереентерабельной.

2. Результат может быть не когерентен вызову даже в момент возврата из функции (опять же из-за возможности асинхронного вызова функции).

3. В случае возвращаемого целого обычный возврат по значению будет, скорее всего, эффективней.

4. Есть рабочий конкурент - strtol, про него уже сказали, ни разу не сложная функция, всяко проще, чем самому огороды городить. Не нравится она в таком виде, написать обёртку.

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


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

Я же указатель возвращаю, не сам объект. И указатель может быть NULL, в случае ошибки. Мне так удобно.

Вы правы! Я уже с этим статиком накололся. Не сбросил число от предыдущей обработки, увеличил прошлое.

От "бреда" избавился. Работает глобальная переменная, как надо. Может, если статическую переменную каждый раз инициализировать при вызове функции, и сгодилось бы. Но красоты в этом я уже не вижу.

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


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

Работает глобальная переменная, как надо.
В чем ее отличие от статической внутри функции? Кроме того, что ее кто угодно поломать может и ему за это ничего не будет. Если функция возвращает указатель на свою статическую переменную как указатель на константу, то компилятор хоть по рукам даст при попытке эту переменную изменить извне.

 

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


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

Указатель на переменную успеха/неудачи передавать в качестве параметра.

 

Объявление:

double toDouble(const char * str, bool * ok);

 

Применение:

const char * str = "0.252";
bool ok;
double var = toDouble(str, &ok);

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


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

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

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

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

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

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

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

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

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

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