Это число?C ++ и через stringstream - PullRequest
0 голосов
/ 21 января 2019

Я новичок в StackOverflow и в C ++, это мой первый пост.Цель этой функции - получить строку типа:

1224435 1998-11-02 23:43:54 2514352842 00:01:22 01.25

callNumber, dateOfCall, hourOfCall numberCalled durationOfTalk costOfTalk

и затем введите его в правильных переменных.Строка оставлена ​​в числах. (Школьное задание) Я ищу правильный способ проверить, является ли поток строки, который вводится в long или short, числом.Вся помощь приветствуется.Вот что я имею в виду:

void lineCutter(string nameOfFile,sortedList * & pHead)
{
        ifstream telephones(nameOfFile);
        stringstream converter;        
        string Bcontainer ;



        long numC;

        short dateY;
        short dateM;
        short dateD;

        short talkH;       
        short talkM;
        short talkS;

        long numG;

        short durationH;
        short durationM;
        short durationS;

        short costZ;
        short costG;


        if(telephones)
        {
            int counter = 0;
            cout<< "I'm in"<<endl;
            while(getline(telephones,Bcontainer))

            {   
                for(int i = 0; i<Bcontainer.size(); i++)
                {
                 if(Bcontainer[i] == 32)
                 {
                            counter++;
                 }
                }

                if(counter == 5)
                {

                    replace (Bcontainer.begin(), Bcontainer.end(), ':', ' ');
                    replace (Bcontainer.begin(), Bcontainer.end(), '.', ' ');
                    replace (Bcontainer.begin(), Bcontainer.end(), '-', ' ');


                    converter << Bcontainer ;


                    converter >> numC >> dateY >> dateM >> dateD >> talkH >> talkM >> talkS >> numG >> durationH >> durationM >> durationS >> costZ >> costG;


                   if( all vars are in correct format  )// Are they numbers?

                    pHead =  new sortedList { numC , dateY , dateM , dateD , talkH , talkM , talkS , numG , durationH , durationM , durationS , costZ , costG, pHead};
                   } //pHead is a head pointer of a single linked list


                 }

                  counter = 0;
            } 

            telefony.close();


        }
        else{
            cout<<"Cannot open."<<endl;
        }
}

Ответы [ 3 ]

0 голосов
/ 21 января 2019

До того, как C ++ 11 не сможет прочитать числовое значение из входного потока, в результате будет установлен failbit потока, а значение останется неизменным.В C ++ 11 и более поздних версиях будет установлен failbit потока, и значение будет либо 0, если извлечение значения завершится неудачно, либо std::numeric_limits<T>::max() или std::numeric_limits<T>::min(), если значение будет большим / маленьким.

std::stringstream s("test");
long value;
s >> value;
if(s.fail()) 
  std::cout << "failed to read value" << std::endl;
else
  std::cout << "value is " << std::endl;

Вывод примера будет:

failed to read value
0 голосов
/ 21 января 2019

Я бы предложил использовать булеву функцию:

bool isNumber(std::string value){
   int limit = value.size();
   for(int i=0; i<limit; i++){
      if(value[i]<48 or value[i]>59){
         return false;
      }
   }
   return true;
}
0 голосов
/ 21 января 2019

Я бы предложил пойти с лексическими приведениями Boost, как это:

#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>

int main()
{
    std::string s = boost::lexical_cast<std::string>(123);  // converting number to a string
    std::cout << s << '\n';
    double d = boost::lexical_cast<double>(s); // convert to number from string
    std::cout << d << '\n';



    try
    {
        double d = boost::lexical_cast<double>("not a number");   /// is not a number and exception is thrown
    }
    catch (const boost::bad_lexical_cast &e)
    {
        std::cout << e.what() << std::endl;
    }

    try
    {
        short d = boost::lexical_cast<short>("123456789012345678901234567890");   /// type to small to hold number
    }
    catch (const boost::bad_lexical_cast &e)
    {
        std::cout << e.what() << std::endl;
    }
}

Boost - хорошо протестированная библиотека с небольшими сюрпризами. Если вы попытаетесь преобразовать строку, которая не может быть представлена ​​типом, к которому вы приводите, это вызовет исключение (которое, кстати, также можно настроить с помощью политик).

EDIT Если использование библиотеки boost слишком сложно, вы можете проверить, работает ли потоковая передача по переменным. Для этого рассмотрим следующий пример:

#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>

int main()
{
    std::stringstream s("1 2 3 4 5 6");
    int val1;
    int val2;
    int val3;
    int val4;
    int val5;
    int val6;

    s >> val1 >> val2 >> val3 >> val4 >> val5 >> val6;

    if (s.fail())
    {
        std::cout << "failed to read value" << std::endl;
    }
    else
    {
        std::cout << val1 << " " << val2 << " " << val3 << " " << val4 << " " << val5 << " " << val6 << std::endl;
    }
}

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

...