Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Из строки - массив double'ов ?


Автор: Liner 28.1.2005, 17:57
Здравствуйте!

Есть такая задача. Есть строка вида "*f*f*f*f...", где:
f - например, "-1234.567"
* - набор символов не являющихся '-', '.', цифрой.
Нужно вернуть массив чисел.

Сейчас double *getDoubles(char *source, int &numcount) работает в лоб: узнает, сколько подстрок-чисел, где они начинаются, где кончаются, и эти "числа" уже atoi-тятся в элементы возвращаемого функцией массива.

А как-то красивее и, наверно, быстрее это сделать можно, может через sscanf как-нибудь?

Спасибо.

Автор: Dov 29.1.2005, 01:00
А если так попробовать
Код
double* getDoubles(char* source, int& numcount)
{
   char* str;
   double* num = (double*)malloc(sizeof(double));
   numcount = 0;

   while(*source)
   {
       while(!isdigit(*source) && *source != '-' && *source)
           source++;

       if(*source)
       {
           num = (double*)realloc(num, sizeof(double) * (numcount + 1));
           num[numcount++] = strtod(source, &str);
           source = str;
       }
   }

   return num;
}


p.s. На быстроту не проверял.
p.p.s На красоту тем более.

Автор: Liner 29.1.2005, 15:27
Спасибо!
Но т.к. мне нельзя терять source, я изменил вашу ф-ю так:

Код

double *getDoubles2(char *source, int &numcount)
{
 char *str;
 double *result = (double*)malloc(sizeof(double));
 numcount = 0;

 char *s = strdup(source); // мне source нельзя терять
 while(*s)
   {
     while (!isDigit(*s) && *s) // (isdigit || '.' || '-')
       s++;

     if(*s)
       {
         result = (double*)realloc(result, sizeof(double) * (numcount + 1));
         result[numcount++] = strtod(s, &str);
         s = str;
       }
   }
 free(s); // здесь выдает ошибку?  
 return result;
}


Почитал немного о sscanf, придумал такой вариант:

Код

double *getDoubles(char *source, int &result_count)
{
 if (!source)
   return NULL;
 result_count = getNumbersCount(source); // она ниже
 if (result_count == 0)
   return NULL;
 double *result = new double[result_count];
 int len = strlen(source);
 int index = 0;
 for (int i = 0; i < len; i++)
   {
     if (isDigit(source[i]))
       {
         sscanf(source + i, "%lf", &result[index]);
         index++;
         for (int j = i; j < len; j++)
           {
             if(!isDigit(source[j]) || j == len - 1)
               {
                 i = j;
                 break;
               }
           }
       }
   }
 return result;
}

int getNumbersCount(char *source)
{
 int result = 0;
 int len = strlen(source);
 if (len == 0) return 0;
 for (int i = 0; i < len; i++)
   {
     if (isDigit(source[i]))
       {
         result++;
         for (int j = i; j < len; j++)
           {
             if(!isDigit(source[j]) || j == len - 1)
               {
                 i = j;
                 break;
               }
           }
       }
   }
 return result;
}


Но ваш, без моих добавлений, работает за 60 сек. миллион вызовов, а мой - за 80 сек. А со strdup, без free, работает также за 80 секунд, но, естесственно, идут resource leak'и. Мне время очень важно, можно ли как-то по-другому не убивать source? Или у меня чего-нибудь можно оптимизировать?



Спасибо.

Автор: sergejzr 29.1.2005, 15:34
А в чём проблема?
(Мои комментары с SZ)
Код

double *getDoubles2(char *source, int &numcount)
{
 char *str;
 double *result = (double*)malloc(sizeof(double));
 numcount = 0;

 char *s = source; // мне source нельзя терять
//SZ Ничего не теряем :)
 while(*s)
   {
     while (!isDigit(*s) && *s) // (isdigit || '.' || '-')
       s++;

     if(*s)
       {
         result = (double*)realloc(result, sizeof(double) * (numcount + 1));
         result[numcount++] = strtod(s, &str);
         s = str;
       }
   }
// free(s); // здесь выдает ошибку?
//SZ И деструктировать ничего не надо
 return result;
}

Автор: Liner 29.1.2005, 16:36
Понял, спасибо smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)