Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/25: Рейтинг темы: голосов - 25, средняя оценка - 4.76
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
1

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

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

Author24 — интернет-сервис помощи студентам
Имеется переменная строкового типа 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.10.2014, 18:33
Ответы с готовыми решениями:

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

Преобразование из строки в число
только начала программировать на С. то есть, буквально только что открыла 10й Билдер))) такой...

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

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

19
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,714
24.10.2014, 19:05 2
НЕ обязательно переносить число в res.
Примените atof прямо к строке, начиная с этого места
C++
1
 float x=atof(stroka+posstop+1);
0
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
24.10.2014, 19:12  [ТС] 3
Цитата Сообщение от zss Посмотреть сообщение
Примените atof прямо к строке, начиная с этого места
Если честно не очень понял.Вот мы получили позицию начала posstart,конца posstop.Ну и длину можем понятное дело можем получить.Что нужно дальше сделать все таки?Просто
Цитата Сообщение от zss Посмотреть сообщение
atof(stroka+posstop+1);
не очень понятно что такое.Ведь это получается мы складываем строку с позицией конца и потом преобразуем.И зачем это?
0
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,714
24.10.2014, 19:19 4
Получаем адрес первого символа (stroka+posstop+1), начиная с которого надо получить число.
atof сама отбросит лишние пробельные символы впереди числа и преобразует
во float число заканчивающееся последующим нечисловым символом.
0
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
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,285
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
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
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
Эксперт С++
3225 / 1752 / 436
Регистрация: 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
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
Вездепух
Эксперт CЭксперт С++
11696 / 6375 / 1724
Регистрация: 18.10.2014
Сообщений: 16,071
25.10.2014, 20:01 11
Цитата Сообщение от fizik777 Посмотреть сообщение
Вроде самому удалось сделать код получше.
Я Римский Папа, если это "получше"...

А если у вас в строке числа окажутся разделены группами пробелов (более одного побела подряд), то такие групповые пробелы как считать - как один "большой" пробел или индивидуально? Я смотрю вы их индивидуально считаете, но что-то меня мучают смутные сомнения на тему того, что такой вариант может быть кому-то нужен...
0
1 / 1 / 0
Регистрация: 23.10.2014
Сообщений: 18
27.10.2014, 19:18  [ТС] 12
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А если у вас в строке числа окажутся разделены группами пробелов (более одного побела подряд), то такие групповые пробелы как считать - как один "большой" пробел или индивидуально? Я смотрю вы их индивидуально считаете, но что-то меня мучают смутные сомнения на тему того, что такой вариант может быть кому-то нужен...
Ну как бы у меня точно вот прямо сто процентов должен быть один пробел и все тут.Эти файлы будут получаться тоже программой именно так.Так что критика тут получается без почвенная.
0
Эксперт С++
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
27.10.2014, 19:24 13
Цитата Сообщение от fizik777 Посмотреть сообщение
Так что критика тут получается без почвенная.
Действительно, к пробелам странно привязываться. Логичнее считывать n-e по счету число. Я вначале думал, что это глупый препод такую задачу задал. Если вы сами, то ошибочное решение.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.10.2014, 20:31 14
Цитата Сообщение от Mr.X Посмотреть сообщение
Действительно, к пробелам странно привязываться.
Если считать пробел разделителем, то вполне нормально.
0
Эксперт С++
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
27.10.2014, 21:09 15
Цитата Сообщение от Avazart Посмотреть сообщение
Если считать пробел разделителем, то вполне нормально.
Ничего нормального не вижу. Основной принцип программирования - не порождать лишних зависимостей. Если мы привязываемся к n-му по счету числу, то достаточно, чтобы в строке была последовательность чисел, разделенных какими угодно пробельными символами, хоть табуляцией, хоть переводом строки в каком угодно количестве. Если привязываться к пробелам, то нужно контролировать, чтобы это были именно пробелы, и по одному, и контролировать наличие пробела в начале строки. Т.е. куча совершенно ненужных зависимостей, которые всегда являются потенциальными источниками ошибок.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.10.2014, 21:30 16
Я привел пример где разделитель не пробел а ";" и при таком раскладе будет проигнорирована пустая строки при ;; подряд,
тоже самое с пробелом.
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
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
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
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
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,285
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
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.10.2014, 22:59
Помогаю со студенческими работами здесь

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru