Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
fizik777
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
1

Преобразование строки в число

24.10.2014, 18:33. Просмотров 1344. Ответов 19
Метки нет (Все метки)

Имеется переменная строкового типа string. У нее такой формат:
1561 1 6.87208 4.52665 0.10226 2.16762
Нужно написать такую функцию, чтобы вытаскивать число после определенного пробела, при этом чтобы функция возвращала это число в типе float. По сути эту функцию я написал.Однако мне кажется что данную задачу можно решить более лаконично что ли.Приведу код.Если не сложно подскажите как лучше исправить код, чтобы он был по короче(лаконичнее,проще). Заранее прошу извинения за некоторую тупость кода, т.к. на си пишу только неделю.


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//функция читает из строки число после N пробела
float readnumber(string text,int N)
{
int dlina,pos,probel;
//задаем переменную типа char stroka той же длинны что и исходная строка text типа string
dlina=text.length(); 
char stroka[dlina];
//копируем посимвольно text в stroka
pos=0;
while (pos<dlina) 
  {
  stroka[pos]=text[pos];
  pos=pos+1;
  }
//ищем такую позицию, после которой будет пробел с номером N
pos=0;probel=0;
while (probel<N )
  {
  if (int(stroka[pos])==32) probel=probel+1;
  pos=pos+1;
  }
//в конце цикла имеем позицию на первом числе после пробела запомним ее в posstar.
int posstart=pos;
//ищем или следующий пробел или конец строки.флагом покажем что нашли это в дальнейшем цикле(32-ANSI код пробела)     
bool flag;
flag=0;
while (flag!=1)
  {
  pos=pos+1;
  if (pos>=dlina) flag=true;else  {if (int(stroka[pos])==32) flag=true;}
  }
//позицию последнеий цифры в числе присваиваем на одну меньше так так выход из цикла произошел в тот момент когда 
//позция была или концом строки или символом пробел
int posstop=pos-1;
//определяем длину числа
dlina=posstop-posstart+1;
//сложим полученное число в res
char res[dlina];
pos=0;
int i;
for (i = posstart; i <=posstop; ++i)
  {
  res[pos]=stroka[i];
  pos=pos+1;  
  }
//переводим в число 
float x=atof(res);
//выводим результат
return x;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.10.2014, 18:33
Ответы с готовыми решениями:

Преобразование строки в число
какой аналог есть в c++ на strtoint inttostr?

Преобразование строки в число
Есть строка с цифрами разделенная точкой с запятой: 1, 2, 3 string s = &quot;1, 2,...

Преобразование строки в число
Здравствуйте. Преобразовываю строку в число с помощью функции atoi(), но...

Преобразование строки в число
задача : реализовать деление двух целых чисел, передаваемых функции в виде...

Преобразование строки в число?
Написал функцию, которая введенную преобразует в число. Но при выводе пишет,...

19
zss
Модератор
Эксперт С++
7258 / 6703 / 4244
Регистрация: 18.12.2011
Сообщений: 17,692
Завершенные тесты: 1
24.10.2014, 19:05 2
НЕ обязательно переносить число в res.
Примените atof прямо к строке, начиная с этого места
C++
1
 float x=atof(stroka+posstop+1);
0
fizik777
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
24.10.2014, 19:12  [ТС] 3
Цитата Сообщение от zss Посмотреть сообщение
Примените atof прямо к строке, начиная с этого места
Если честно не очень понял.Вот мы получили позицию начала posstart,конца posstop.Ну и длину можем понятное дело можем получить.Что нужно дальше сделать все таки?Просто
Цитата Сообщение от zss Посмотреть сообщение
atof(stroka+posstop+1);
не очень понятно что такое.Ведь это получается мы складываем строку с позицией конца и потом преобразуем.И зачем это?
0
zss
Модератор
Эксперт С++
7258 / 6703 / 4244
Регистрация: 18.12.2011
Сообщений: 17,692
Завершенные тесты: 1
24.10.2014, 19:19 4
Получаем адрес первого символа (stroka+posstop+1), начиная с которого надо получить число.
atof сама отбросит лишние пробельные символы впереди числа и преобразует
во float число заканчивающееся последующим нечисловым символом.
0
fizik777
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
24.10.2014, 19:40  [ТС] 5
Цитата Сообщение от zss Посмотреть сообщение
stroka+posstop+1
Ну я говорю о том, что данная операция какая-то странная.Это char(stroka) складывается с int(posstop+1).Позицию с которой надо получить число мы знаем.Она фактически определяется в posstart.Тогда как имея ее преобразовать число начинаяя с него до пробела с помощью atof?Как конкретно она должна выглядеть команда эта тогда с atof?

Добавлено через 10 минут
Да и можно такой еще вопрос.А можно вообще обойтись без преобразования string в char преобазовать сразу в число.Если такая функция?
0
DrOffset
8464 / 4741 / 1161
Регистрация: 30.01.2014
Сообщений: 7,727
24.10.2014, 20:21 6
Цитата Сообщение от fizik777 Посмотреть сообщение
А можно вообще обойтись без преобразования string в char.
Можно. std::string::c_str()
Цитата Сообщение от fizik777 Посмотреть сообщение
Нужно написать такую функцию, чтобы вытаскивать число после определенного пробела, при этом чтобы функция возвращала это число в типе float.
Вот как-то так в первом приближении:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
float extract_float(std::string const & str, size_t num)
{
    char const * start = str.c_str();
    char const * it = start;
    size_t i = 1;
    while(*it != '\0')
    {
        if(std::isspace(*it) && i++ == num)
        {
            start = it;
            break;
        }
        ++it;
    }
    char * endp = 0;
    return strtof(start, &endp);
}
Правда из твоего описания не очень понятно что делать, если ввели слишком большой номер. Пока просто решил выводить первое число в строке.

Добавлено через 7 минут
Вот вариант, когда при слишком большом номере выводится последнее число (если есть):
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <string>
#include <cstdlib>
 
float extract_float(std::string const & str, size_t num)
{
    char const * start = str.c_str();
    char const * it = start;
    char const * prevspace = start;
    size_t i = 0;
    while(*it != '\0')
    {
        if(std::isspace(*it++))
        {
            if(++i == num)
            {
                start = it;
                break;
            }
            prevspace = it;
        }
    }
    char * endp = 0;
    return strtof(i < num ? prevspace : start, &endp);
}

Ну или так:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
float extract_float(std::string const & str, size_t num)
{
    char const * start = str.c_str();
    char const * it = start;
    size_t i = 0;
    if(num)
    {
        while(*it != '\0')
        {
            if(std::isspace(*it++))
            {
                start = it;
                if(++i == num)
                {
                    break;
                }
            }
        }
    }
    char * endp = 0;
    return strtof(start, &endp);
}
0
Avazart
Эксперт С++
7725 / 5634 / 549
Регистрация: 10.12.2010
Сообщений: 25,412
Записей в блоге: 17
24.10.2014, 20:53 7
Можно так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
 
#include <string>
#include <sstream>
 
template<typename T,typename charT>
bool getValue(int pos,const std::basic_string<charT>& line,/*out*/T& value,charT delim)
{
    std::basic_stringstream<charT> stream(line);
    std::basic_string<charT> s;
    for(;pos;pos--)
        std::getline(stream,s,delim);
    return stream>>value;
}
 
int main()
{
    // test 1
    const std::string line1="1561 some 1 6.87208 4.52665 0.10226 2.16762";
    std::cout<< line1<< std::endl;
 
    float value1=0;
 
    for(int i=0; i<8; ++i)
    if( getValue(i,line1,value1,' '))
        std::cout<< value1<< std::endl;
    else
        std::cerr<<"Error!"<< std::endl;
 
    // test 2
    const std::wstring line2=L"1561;some;1;6.87208;4.52665;0.10226;2.16762";
    std::wcout<< line2<< std::endl;
 
    float value2=0;
 
    for(int i=0; i<8; ++i)
    if( getValue(i,line2,value2,L';'))
        std::wcout<< value2<< std::endl;
    else
        std::wcerr<<"Error!"<< std::endl;
 
    getchar();
    return 0;
}

Вывод:
1561 some 1 6.87208 4.52665 0.10226 2.16762
1561
Error!
1
6.87208
4.52665
0.10226
2.16762
Error!

1561;some;1;6.87208;4.52665;0.10226;2.16762
1561
Error!
1
6.87208
4.52665
0.10226
2.16762
Error!
1
Mr.X
Эксперт С++
3180 / 1707 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
24.10.2014, 21:19 8
Цитата Сообщение от fizik777 Посмотреть сообщение
А можно вообще обойтись без преобразования string в char преобазовать сразу в число.Если такая функция?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
/////////////////////////////////////////////////////////////////////////////////////////
typedef std::string         T_str;
typedef T_str::size_type    T_pos;
/////////////////////////////////////////////////////////////////////////////////////////
int main ()
{
    T_str   s("1561 1 6.87208 4.52665 0.10226 2.16762");
    T_pos   next_pos   =   0;
 
    while   (
                !s.empty()
            )
    {
        std::cout       <<  std::stof( s, &next_pos )
                        <<  std::endl;
 
        s   =   s.substr( next_pos );
    }
 
    system("pause");
}
0
Avazart
24.10.2014, 21:33
  #9

Не по теме:

C++
1
std::stof()
В C++11 все таки сделали отдельные функции конвертирования, но опять локаль не учли (
Таже фигня что и lexical_cast<> блин

0
fizik777
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
25.10.2014, 19:51  [ТС] 10
Вроде самому удалось сделать код получше.Вот что получилось:
float readnumber(string text,int N)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
{
int pos,flag;
pos=0;flag=0;
     while (flag<N)  
     {
     if (int(text[pos])==32) flag=flag+1;
     pos=pos+1;
     } 
     std::istringstream str(text.substr(pos-1));
     float number;
     str >> number;
return number;
}
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
4772 / 2429 / 679
Регистрация: 18.10.2014
Сообщений: 4,153
25.10.2014, 20:01 11
Цитата Сообщение от fizik777 Посмотреть сообщение
Вроде самому удалось сделать код получше.
Я Римский Папа, если это "получше"...

А если у вас в строке числа окажутся разделены группами пробелов (более одного побела подряд), то такие групповые пробелы как считать - как один "большой" пробел или индивидуально? Я смотрю вы их индивидуально считаете, но что-то меня мучают смутные сомнения на тему того, что такой вариант может быть кому-то нужен...
0
fizik777
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
27.10.2014, 19:18  [ТС] 12
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А если у вас в строке числа окажутся разделены группами пробелов (более одного побела подряд), то такие групповые пробелы как считать - как один "большой" пробел или индивидуально? Я смотрю вы их индивидуально считаете, но что-то меня мучают смутные сомнения на тему того, что такой вариант может быть кому-то нужен...
Ну как бы у меня точно вот прямо сто процентов должен быть один пробел и все тут.Эти файлы будут получаться тоже программой именно так.Так что критика тут получается без почвенная.
0
Mr.X
Эксперт С++
3180 / 1707 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
27.10.2014, 19:24 13
Цитата Сообщение от fizik777 Посмотреть сообщение
Так что критика тут получается без почвенная.
Действительно, к пробелам странно привязываться. Логичнее считывать n-e по счету число. Я вначале думал, что это глупый препод такую задачу задал. Если вы сами, то ошибочное решение.
0
Avazart
Эксперт С++
7725 / 5634 / 549
Регистрация: 10.12.2010
Сообщений: 25,412
Записей в блоге: 17
27.10.2014, 20:31 14
Цитата Сообщение от Mr.X Посмотреть сообщение
Действительно, к пробелам странно привязываться.
Если считать пробел разделителем, то вполне нормально.
0
Mr.X
Эксперт С++
3180 / 1707 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
27.10.2014, 21:09 15
Цитата Сообщение от Avazart Посмотреть сообщение
Если считать пробел разделителем, то вполне нормально.
Ничего нормального не вижу. Основной принцип программирования - не порождать лишних зависимостей. Если мы привязываемся к n-му по счету числу, то достаточно, чтобы в строке была последовательность чисел, разделенных какими угодно пробельными символами, хоть табуляцией, хоть переводом строки в каком угодно количестве. Если привязываться к пробелам, то нужно контролировать, чтобы это были именно пробелы, и по одному, и контролировать наличие пробела в начале строки. Т.е. куча совершенно ненужных зависимостей, которые всегда являются потенциальными источниками ошибок.
0
Avazart
Эксперт С++
7725 / 5634 / 549
Регистрация: 10.12.2010
Сообщений: 25,412
Записей в блоге: 17
27.10.2014, 21:30 16
Я привел пример где разделитель не пробел а ";" и при таком раскладе будет проигнорирована пустая строки при ;; подряд,
тоже самое с пробелом.
0
8Observer8
2271 / 1439 / 227
Регистрация: 05.10.2013
Сообщений: 4,414
Записей в блоге: 56
27.10.2014, 21:49 17
Цитата Сообщение от fizik777 Посмотреть сообщение
1561 1 6.87208 4.52665 0.10226 2.16762
Допустим у нас есть строка с таким содержимым:

C++
1
std::string str = "1561 1 6.87208 4.52665 0.10226 2.16762";
Можно написать функцию, которая принимает эту строку возвращает массив чисел:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <vector>
#include <sstream>
 
std::vector<float> getNumbers( const std::string &str );
void showArray( const std::vector<float> &arr );
 
int main()
{
    // Input string
    std::string str = "1561 1 6.87208 4.52665 0.10226 2.16762";
 
    // Get array of numbers
    std::vector<float> arr = getNumbers( str );
 
    // Show array
    showArray( arr );
 
    return 0;
}
 
std::vector<float> getNumbers( const std::string &str )
{
    std::stringstream ss( str );
    float number;
    std::vector<float> arr;
    while( ss >> number ) {
        arr.push_back( number );
    }
    return arr;
}
 
void showArray( const std::vector<float> &arr )
{
    for ( std::size_t i = 0 ; i < arr.size(); ++i ) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}
0
Avazart
Эксперт С++
7725 / 5634 / 549
Регистрация: 10.12.2010
Сообщений: 25,412
Записей в блоге: 17
27.10.2014, 21:57 18
8Observer8,
C++
1
2
3
    std::vector<float> arr;
    while( ss >> number ) {
        arr.push_back( number );
Для таких вещей есть std::copy + std::back_inserter
1
DrOffset
8464 / 4741 / 1161
Регистрация: 30.01.2014
Сообщений: 7,727
27.10.2014, 22:35 19
8Observer8,
Цитата Сообщение от Avazart Посмотреть сообщение
Для таких вещей есть std::copy + std::back_inserter
А можно и так:
C++
1
2
3
4
5
std::vector<float> getNumbers(const std::string &str)
{
    std::stringstream ss(str);
    return std::vector<float>((std::istream_iterator<float>(ss)), std::istream_iterator<float>());
}
1
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
27.10.2014, 22:59 20
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdlib.h>
#include <iostream>
#include <string.h>
 
using namespace std;
 
//Функция вытаскивает число из строки по номеру
bool get_num(string &Arr,const int N,bool &flag,double &x){
   char* pEnd=(char*)&Arr.c_str()[0];
 
    if (N<1) return false;   //нулевого числа в строке нет меньше чем нулевого тоже
 
      for (int i=0;i<N;i++){
        if (*pEnd==0)  return false; //если указатель достиг конца строки, то значит номер уехал за количество чисел
        else x=strtod(pEnd, &pEnd); //если все в порядке, вытаскиваю очередное число
      }
      return true;
 }
 
int main ()
{
  bool flag=true;
  string s = "0 0 1561 1    6.87208 4.52665     0.10226     2.16762";
  double x=0;
 
 
  int N;
  cout<<"Введи номер числа:\n";
  cin>>N;
   flag=get_num(s,N,flag,x);  //параметры: строка, номер цифры, признак ошибки, получаемое число.
   if (flag) cout<<x<<"\n";
   else cout<<"Ошибка ввода\n";
 
 
  return 0;
}
0
27.10.2014, 22:59
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.10.2014, 22:59

Преобразование строки в число
А как многоразрядные числа из строки преобразовать? Если я использую string?

Преобразование строки в число
Почему не работает функция StrToInt, хоть библиотеку подключил stdlib.h

Преобразование строки в число
Вот код из учебника #include&lt;iostream&gt; using std::cout;using std::endl; int...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru