KevinShaffer
KevinShaffer

Reputation: 858

Parse a string into two double

I have a string that is in the format #########s###.## where #### is just a few numbers, and the second piece is usually a decimal, but not always.

I need to break the two number pieces apart, and set them as two doubles(or some other valid number type.

I can only use standard methods for this, as the server it's being run on only has standard modules.

I can currently grab the second piece using find and substr, but can't figure out how to get the first piece. I still haven't done anything that changes the second piece into a numerical type, but hopefully that is much easier.

here's what I have:

    string symbol,pieces;

    fin >> pieces; //pieces is a string of the type i mentioned #####s###.##
    unsigned pos;
    pos = pieces.find("s");
    string capitals = pieces.substr(pos+1);
    cout << "Price of stock " << symbol << " is " << capitals << endl;

Upvotes: 2

Views: 2577

Answers (6)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158449

This code will split the string as you desire and convert them to double, it could easily be changed to convert to float as well:

#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>

class BadConversion : public std::runtime_error {
public:
  BadConversion(std::string const& s)
    : std::runtime_error(s)
    { }
};

inline double convertToDouble(std::string const& s,
                              bool failIfLeftoverChars = true)
{
  std::istringstream i(s);
  double x;
  char c;
  if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
    throw BadConversion("convertToDouble(\"" + s + "\")");
  return x;
}

int main()
{
  std::string symbol,pieces;

    std::cin >> pieces; //pieces is a string of the type i mentioned #####s###.##
    unsigned pos;
    pos = pieces.find("s");
    std::string first = pieces.substr(0, pos);
    std::string second = pieces.substr(pos + 1);
    std::cout << "first: " << first << " second " << second << std::endl;
    double d1 = convertToDouble(first), d2 = convertToDouble(second) ;
    std::cout << d1 << " " << d2 << std::endl ;
}

Just for reference, I took the conversion code from one of my previous answers.

Upvotes: 1

frankc
frankc

Reputation: 11473

Some poeple will complain that this is not C++-y but this is valid C++


  char * in = "1234s23.93";
  char * endptr;
  double d1 = strtod(in,&endptr);
  in = endptr + 1;
  double d2 = strtod(in, &endptr); 

Upvotes: 0

HonkyTonk
HonkyTonk

Reputation: 2019

istringstream makes it easy.

#include <iostream>
#include <sstream>
#include <string>

int main(int argc, char* argv[]) {
  std::string input("123456789s123.45");

  std::istringstream output(input);

  double part1;
  double part2;

  output >> part1;

  char c;

  // Throw away the "s"
  output >> c;

  output >> part2;

  std::cout << part1 << ", " << part2 << std::endl;

  return 0;
}

Upvotes: 3

taocp
taocp

Reputation: 23624

You can do the same thing as you did for the second part:

 unsigned pos;
 pos = pieces.find("s");
 string firstPart = pieces.substr(0,pos);

Upvotes: 2

Remy Lebeau
Remy Lebeau

Reputation: 595349

Grabbing the first piece is easy:

string firstpiece = pieces.substr(0, pos);

As for converting to numeric types, I find sscanf() to be particularly useful for that:

#include <cstdio> 

std::string pieces;
fin >> pieces; //pieces is a string of the type i mentioned #####s###.##

double firstpiece = 0.0, capitals = 0.0;
std::sscanf(pieces.c_str() "%lfs%lf", &firstpiece, &capitals);
...

Upvotes: 1

user7116
user7116

Reputation: 64068

You can specify a count along with an offset when calling substr:

string first = pieces.substr(0, pos);
string second = pieces.substr(pos + 1);

Upvotes: 2

Related Questions