views:

631

answers:

5

I am trying to manipulate a string in C++. I am working with an Arduino board so I am limited on what I can use. I am also still learning C++ (Sorry for any stupid questions)

Here is what I need to do: I need to send miles per hour to a 7 segment display. So if I have a number such as 17.812345, I need to display 17.8 to the 7 segment display. What seems to be most efficient way is to first multiply by 10 (This is to shift the decimal point right one place), then cast 178.12345 to an int (to chop decimal points off). The part I am stuck on is how to break apart 178. In Python I could slice the string, but I can't find anything on how to do this in C++ (or at least, I can't find the right terms to search for)

There are four 7 segment displays and a 7 segment display controller. It will measure up to tenths of a mile per hour. Thank you very much for an assistance and information you can provide me.

+10  A: 

It would probably be easiest to not convert it to a string, but just use arithmetic to separate the digits, i.e.

float speed = 17.812345;
int display_speed = speed * 10 + 0.5;     // round to nearest 0.1 == 178
int digits[4];
digits[3] = display_speed % 10;           // == 8
digits[2] = (display_speed / 10) % 10;    // == 7
digits[1] = (display_speed / 100) % 10;   // == 1
digits[0] = (display_speed / 1000) % 10;  // == 0

and, as pointed out in the comments, if you need the ASCII value for each digit:

char ascii_digits[4];
ascii_digits[0] = digits[0] + '0';
ascii_digits[1] = digits[1] + '0';
ascii_digits[2] = digits[2] + '0';
ascii_digits[3] = digits[3] + '0';
cobbal
And of course it's trivial to take the individual elements of digits and get the ASCII code if he actually needs them as such.
imaginaryboy
+4  A: 

This a way you can do it in C++ without modulus math (either way seems fine to me):

#include "math.h"
#include <stdio.h>
#include <iostream.h>

int main( ) {

        float value = 3.1415;
        char buf[16]; 
        value = floor( value * 10.0f ) / 10.0f;
        sprintf( buf, "%0.1f", value );

        std::cout << "Value: " << value << std::endl;

        return 0;
}
Brock Woolf
`buf` should be larger than 4, as even "17.8" leaves no room for null terminator.
cobbal
Good point cobbal – You've caught me trying to over optimise, red handed. 2^4 should suffice :)
Brock Woolf
+2  A: 

If you actually want to be processing this stuff as strings, I would recommend looking into stringstream. It can be used much the same as any other stream, such as cin and cout, except instead of sending all output to the console you get an actual string out of the deal.

This will work with standard C++. Don't know much about Arduino, but some quick googling suggests it won't support stringstreams.

A quick example:

#include <sstream> // include this for stringstreams
#include <iostream>
#include <string>

using namespace std; // stringstream, like almost everything, is in std

string stringifyFloat(float f) {
  stringstream ss;
  ss.precision(1); // set decimal precision to one digit.
  ss << fixed;     // use fixed rather than scientific notation.
  ss << f;         // read in the value of f
  return ss.str(); // return the string associated with the stream.
}

int main() {
  cout << stringifyFloat(17.812345) << endl; // 17.8
  return 0;
}
goldPseudo
A: 

You can use a function such as this toString and work your way up from there, like you would in Python, or just use modulo 10,100,1000,etc to get it as numbers. I think manipulating it as a string might be easier for you, but its up to you.

You could also use boost::lexical_cast, but it will probably be hard to get boost working in an embedded system like yours.

rmn
A: 

A good idea would be to implement a stream for the display. That way the C++ stream syntax could be used and the rest of the application would remain generic. Although this may be overkill for an embedded system.

If you still want to use std::string you may want to use a reverse iterator. This way you can start at the right most digit (in the string) and work towards the left, one character at a time.

If you have access to the run-time library code, you could set up a C language I/O for the display. This is easier to implement than a C++ stream. You could then use fprint, fputs to write to the display. I implemented a debug port in this method, and it was easier for the rest of the developers to use.

Thomas Matthews