Removing trailing zeros - c++ [duplicate] - c++

This question already has answers here:
C++11 std::to_string(double) - No trailing zeros
(10 answers)
Closed 2 years ago.
This code:
cout<< to_string(x) + "m ----> " + to_string(x *0.001)+ "km"<<endl;
with this outputting:
0.002000
However, I want to remove the trailing extra zeros, but it should be in a line of code as i have many lines like the above one.

try this snipet:
cout << "test zeros" << endl;
double x = 200;
cout << "before" << endl;
cout<< std::to_string(x) + "m ----> " + std::to_string(x *0.001)+ "km"<<endl;
std::string str = std::to_string(x * 0.001);
str.erase ( str.find_last_not_of('0') + 1, std::string::npos );
cout << "after" << endl;
cout<< std::to_string(x) + "m ----> " + str + "km"<<endl;
with output:
test zeros
before
200.000000m ----> 0.200000km
after
200.000000m ----> 0.2km
it is better then std::setprecision cause you don't need to decide how many num after period you want to keep, but let the implementation find it for you.
Here the documentation for some extra information.

Try using std::setprecsion()
Set decimal precision
Sets the decimal precision to be used to format floating-point values on output operations.
So in your case, you can use :
std::cout << std::setprecision(3)
This will remove the trailing zeroes from 0.0020000 to 0.002
Edit
The below code works when you want to use to_string in your code :
#include <iostream>
using namespace std;
int main(){
int x=1;
string str2 = to_string(x *0.001);
str2.erase ( str2.find_last_not_of('0') + 1, std::string::npos );;
std::cout<<to_string(x)+ "m ----> " + str2+ "km";
}

Related

How can I convert military time to regular time. the regular time must be a string [duplicate]

This question already has answers here:
how to zero pre-fill for std::to_string function?
(2 answers)
Closed 6 months ago.
I hope someone can help me. I keep getting one 0 on the minutes side. for example, for input 0000 I get 12:0 AM or for input 608 I get 6:8 AM. How can I get double 0 on the minutes side?
on main.cc I have:
#include "time_converter.h"
#include <iostream>
int main() {
int military_time;
std::cout << "Please enter the time in military time: ";
std::cin >> military_time;
// TODO: Call your function to convert from military time to regular time
// and assign its result to regular_time.
std::string regular_time;
regular_time = MilitaryToRegularTime(military_time);
std::cout << "The equivalent regular time is: " << regular_time << "\n";
return 0;
}
time_converter.h:
#include <iostream>
// Converts the time in military format to regular format.
std::string MilitaryToRegularTime(int military_time);
time_converter.cc:
#include <iostream>
std::string amorpm;
std::string MilitaryToRegularTime(int military_time) {
// TODO: convert military_time to regular time in string format.
// Hint: std::to_string() converts a given integer to a string.
int regular_hr = military_time / 100;
if (regular_hr >= 13){
regular_hr = (military_time / 100) - 12;
}
if (regular_hr == 0){
regular_hr = 12;
}
int regular_min = military_time % 100;
if (military_time >= 1200 && military_time <= 2359){
amorpm = " PM\n";
}
if (military_time >= 0000 && military_time <= 1159 ){
amorpm = " AM\n";
}
std::string regular_hr_str = std::to_string(regular_hr);
std::string regular_min_str = std::to_string(regular_min);
return regular_hr_str + ":" + regular_min_str + amorpm;
}
The function std::to_string does not have sufficient formatting options to do what you require.
However, if you instead use an object of type std::ostringstream as the target, you can use the std::setw and std::setfill I/O manipulators to accomplish what you want. You can use std::setw to set the minimum width to 2 and std::setfill to set the fill character to '0'.
After you are finished, you can convert the std::ostringstream object to a std::string using std::ostringstream::str.
#include <iostream>
#include <sstream>
#include <iomanip>
int main()
{
int hours = 6;
int minutes = 8;
std::ostringstream oss;
std::string str;
//write desired time to ostringstream object
oss <<
"The time is " <<
std::setw( 2 ) << std::setfill( '0' ) <<
hours <<
":" <<
std::setw( 2 ) << std::setfill( '0' ) <<
minutes <<
".\n";
//convert ostringstream to a string
str = oss.str();
//print the string
std::cout << "String content: " << str << '\n';
}
This program has the following output:
String content: The time is 06:08.

String not displaying all characters in c++ [duplicate]

This question already has answers here:
Print leading zeros with C++ output operator?
(6 answers)
Closed 2 years ago.
I want cout to output an int with leading zeros, so the value 1 would be printed as 001 and the value 25 printed as 025. How can I do this?
With the following,
#include <iomanip>
#include <iostream>
int main()
{
std::cout << std::setfill('0') << std::setw(5) << 25;
}
the output will be
00025
setfill is set to the space character (' ') by default. setw sets the width of the field to be printed, and that's it.
If you are interested in knowing how the to format output streams in general, I wrote an answer for another question, hope it is useful:
Formatting C++ Console Output.
Another way to achieve this is using old printf() function of C language
You can use this like
int dd = 1, mm = 9, yy = 1;
printf("%02d - %02d - %04d", mm, dd, yy);
This will print 09 - 01 - 0001 on the console.
You can also use another function sprintf() to write formatted output to a string like below:
int dd = 1, mm = 9, yy = 1;
char s[25];
sprintf(s, "%02d - %02d - %04d", mm, dd, yy);
cout << s;
Don't forget to include stdio.h header file in your program for both of these functions
Thing to be noted:
You can fill blank space either by 0 or by another char (not number).
If you do write something like %24d format specifier than this will not fill 2 in blank spaces. This will set pad to 24 and will fill blank spaces.
cout.fill('*');
cout << -12345 << endl; // print default value with no field width
cout << setw(10) << -12345 << endl; // print default with field width
cout << setw(10) << left << -12345 << endl; // print left justified
cout << setw(10) << right << -12345 << endl; // print right justified
cout << setw(10) << internal << -12345 << endl; // print internally justified
This produces the output:
-12345
****-12345
-12345****
****-12345
-****12345
In C++20 you'll be able to do:
std::cout << std::format("{:03}", 25); // prints 025
In the meantime you can use the {fmt} library, std::format is based on.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
cout.fill( '0' );
cout.width( 3 );
cout << value;
Another example to output date and time using zero as a fill character on instances of single digit values: 2017-06-04 18:13:02
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <ctime>
using namespace std;
int main()
{
time_t t = time(0); // Get time now
struct tm * now = localtime(&t);
cout.fill('0');
cout << (now->tm_year + 1900) << '-'
<< setw(2) << (now->tm_mon + 1) << '-'
<< setw(2) << now->tm_mday << ' '
<< setw(2) << now->tm_hour << ':'
<< setw(2) << now->tm_min << ':'
<< setw(2) << now->tm_sec
<< endl;
return 0;
}
I would use the following function. I don't like sprintf; it doesn't do what I want!!
#define hexchar(x) ((((x)&0x0F)>9)?((x)+'A'-10):((x)+'0'))
typedef signed long long Int64;
// Special printf for numbers only
// See formatting information below.
//
// Print the number "n" in the given "base"
// using exactly "numDigits".
// Print +/- if signed flag "isSigned" is TRUE.
// Use the character specified in "padchar" to pad extra characters.
//
// Examples:
// sprintfNum(pszBuffer, 6, 10, 6, TRUE, ' ', 1234); --> " +1234"
// sprintfNum(pszBuffer, 6, 10, 6, FALSE, '0', 1234); --> "001234"
// sprintfNum(pszBuffer, 6, 16, 6, FALSE, '.', 0x5AA5); --> "..5AA5"
void sprintfNum(char *pszBuffer, int size, char base, char numDigits, char isSigned, char padchar, Int64 n)
{
char *ptr = pszBuffer;
if (!pszBuffer)
{
return;
}
char *p, buf[32];
unsigned long long x;
unsigned char count;
// Prepare negative number
if (isSigned && (n < 0))
{
x = -n;
}
else
{
x = n;
}
// Set up small string buffer
count = (numDigits-1) - (isSigned?1:0);
p = buf + sizeof (buf);
*--p = '\0';
// Force calculation of first digit
// (to prevent zero from not printing at all!!!)
*--p = (char)hexchar(x%base);
x = x / base;
// Calculate remaining digits
while(count--)
{
if(x != 0)
{
// Calculate next digit
*--p = (char)hexchar(x%base);
x /= base;
}
else
{
// No more digits left, pad out to desired length
*--p = padchar;
}
}
// Apply signed notation if requested
if (isSigned)
{
if (n < 0)
{
*--p = '-';
}
else if (n > 0)
{
*--p = '+';
}
else
{
*--p = ' ';
}
}
// Print the string right-justified
count = numDigits;
while (count--)
{
*ptr++ = *p++;
}
return;
}

How to align numbers after decimal in C++ output [duplicate]

This question already has answers here:
Print leading zeros with C++ output operator?
(6 answers)
Closed 2 years ago.
I want cout to output an int with leading zeros, so the value 1 would be printed as 001 and the value 25 printed as 025. How can I do this?
With the following,
#include <iomanip>
#include <iostream>
int main()
{
std::cout << std::setfill('0') << std::setw(5) << 25;
}
the output will be
00025
setfill is set to the space character (' ') by default. setw sets the width of the field to be printed, and that's it.
If you are interested in knowing how the to format output streams in general, I wrote an answer for another question, hope it is useful:
Formatting C++ Console Output.
Another way to achieve this is using old printf() function of C language
You can use this like
int dd = 1, mm = 9, yy = 1;
printf("%02d - %02d - %04d", mm, dd, yy);
This will print 09 - 01 - 0001 on the console.
You can also use another function sprintf() to write formatted output to a string like below:
int dd = 1, mm = 9, yy = 1;
char s[25];
sprintf(s, "%02d - %02d - %04d", mm, dd, yy);
cout << s;
Don't forget to include stdio.h header file in your program for both of these functions
Thing to be noted:
You can fill blank space either by 0 or by another char (not number).
If you do write something like %24d format specifier than this will not fill 2 in blank spaces. This will set pad to 24 and will fill blank spaces.
cout.fill('*');
cout << -12345 << endl; // print default value with no field width
cout << setw(10) << -12345 << endl; // print default with field width
cout << setw(10) << left << -12345 << endl; // print left justified
cout << setw(10) << right << -12345 << endl; // print right justified
cout << setw(10) << internal << -12345 << endl; // print internally justified
This produces the output:
-12345
****-12345
-12345****
****-12345
-****12345
In C++20 you'll be able to do:
std::cout << std::format("{:03}", 25); // prints 025
In the meantime you can use the {fmt} library, std::format is based on.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
cout.fill( '0' );
cout.width( 3 );
cout << value;
Another example to output date and time using zero as a fill character on instances of single digit values: 2017-06-04 18:13:02
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <ctime>
using namespace std;
int main()
{
time_t t = time(0); // Get time now
struct tm * now = localtime(&t);
cout.fill('0');
cout << (now->tm_year + 1900) << '-'
<< setw(2) << (now->tm_mon + 1) << '-'
<< setw(2) << now->tm_mday << ' '
<< setw(2) << now->tm_hour << ':'
<< setw(2) << now->tm_min << ':'
<< setw(2) << now->tm_sec
<< endl;
return 0;
}
I would use the following function. I don't like sprintf; it doesn't do what I want!!
#define hexchar(x) ((((x)&0x0F)>9)?((x)+'A'-10):((x)+'0'))
typedef signed long long Int64;
// Special printf for numbers only
// See formatting information below.
//
// Print the number "n" in the given "base"
// using exactly "numDigits".
// Print +/- if signed flag "isSigned" is TRUE.
// Use the character specified in "padchar" to pad extra characters.
//
// Examples:
// sprintfNum(pszBuffer, 6, 10, 6, TRUE, ' ', 1234); --> " +1234"
// sprintfNum(pszBuffer, 6, 10, 6, FALSE, '0', 1234); --> "001234"
// sprintfNum(pszBuffer, 6, 16, 6, FALSE, '.', 0x5AA5); --> "..5AA5"
void sprintfNum(char *pszBuffer, int size, char base, char numDigits, char isSigned, char padchar, Int64 n)
{
char *ptr = pszBuffer;
if (!pszBuffer)
{
return;
}
char *p, buf[32];
unsigned long long x;
unsigned char count;
// Prepare negative number
if (isSigned && (n < 0))
{
x = -n;
}
else
{
x = n;
}
// Set up small string buffer
count = (numDigits-1) - (isSigned?1:0);
p = buf + sizeof (buf);
*--p = '\0';
// Force calculation of first digit
// (to prevent zero from not printing at all!!!)
*--p = (char)hexchar(x%base);
x = x / base;
// Calculate remaining digits
while(count--)
{
if(x != 0)
{
// Calculate next digit
*--p = (char)hexchar(x%base);
x /= base;
}
else
{
// No more digits left, pad out to desired length
*--p = padchar;
}
}
// Apply signed notation if requested
if (isSigned)
{
if (n < 0)
{
*--p = '-';
}
else if (n > 0)
{
*--p = '+';
}
else
{
*--p = ' ';
}
}
// Print the string right-justified
count = numDigits;
while (count--)
{
*ptr++ = *p++;
}
return;
}

Number of digits for an int to use in a file name in c++ [duplicate]

This question already has answers here:
Print leading zeros with C++ output operator?
(6 answers)
Closed 8 years ago.
I need to use some integer values as a part of some file names I create as outputs in a c++ program. For this I use the code above. The thing is my int values ( named n_irrad in the code) goes from 1 to 20000 for example, so I need the file names to be MC_Interface00001.txt, MC_Interface00002.txt, ..., MC_Interface20000.txt. So, ¿how can I set the number of digits in the file name? With the code I'm using I obviously get MC_Interface1.txt, MC_Interface2.txt, ..., MC_Interface20000.txt.
Thanks in advance.
ofstream MC_Interface;
string Irrad = static_cast<ostringstream*>( &(ostringstream() << n_irrad) )->str();
string MC_Interface_FileName = "MC_Interface" + Irrad + ".txt";
MC_Interface.open(MC_Interface_FileName.c_str());
Try the following
#include <iostream>
#include <iomanip>
#include <sstream>
int main()
{
std::ostringstream os;
os << std::setw( 5 ) << std::setfill( '0' ) << 10;
std::string s = "MC_Interface" + os.str();
std::cout << s << std::endl;
return 0;
}
The output is
MC_Interface00010
ofstream MC_Interface;
std::stringstream ss("MC_Interface");
ss << std::setw(5) << std::setfill('0') << n_irrad;
ss << ".txt";
MC_Interface.open(ss.str());

Anything like substr but instead of stopping at the byte you specified, it stops at a specific string [duplicate]

This question already has answers here:
How do you search a std::string for a substring in C++?
(6 answers)
Closed 8 years ago.
I have a client for a pre-existing server. Let's say I get some packets "MC123, 456!##".
I store these packets in a char called message. To print out a specific part of them, in this case the numbers part of them, I would do something like "cout << message.substr(3, 7) << endl;".
But what if I receive another message "MC123, 456, 789!##". "cout << message.substr(3,7)" would only print out "123, 456", whereas I want "123, 456, 789". How would I do this assuming I know that every message ends with "!##".
First - Sketch out the indexing.
std::string packet1 = "MC123, 456!##";
// 0123456789012345678
// ^------^ desired text
std::string packet2 = "MC123, 456, 789!##";
// 0123456789012345678
// ^-----------^ desired text
The others answers are ok. If you wish to use std::string find,
consider rfind and find_first_not_of, as in the following code:
// forward
void messageShow(std::string packet,
size_t startIndx = 2);
// /////////////////////////////////////////////////////////////////////////////
int main (int, char** )
{
// 012345678901234567
// |
messageShow("MC123, 456!##");
messageShow("MC123, 456, 789!##");
messageShow("MC123, 456, 789, 987, 654!##");
// error test cases
messageShow("MC123, 456, 789##!"); // missing !##
messageShow("MC123x 456, 789!##"); // extraneous char in packet
return(0);
}
void messageShow(std::string packet,
size_t startIndx) // default value 2
{
static size_t seq = 0;
seq += 1;
std::cout << packet.size() << " packet" << seq << ": '"
<< packet << "'" << std::endl;
do
{
size_t bangAtPound_Indx = packet.rfind("!##");
if(bangAtPound_Indx == std::string::npos){ // not found, can't do anything more
std::cerr << " '!##' not found in packet " << seq << std::endl;
break;
}
size_t printLength = bangAtPound_Indx - startIndx;
const std::string DIGIT_SPACE = "0123456789, ";
size_t allDigitSpace = packet.find_first_not_of(DIGIT_SPACE, startIndx);
if(allDigitSpace != bangAtPound_Indx) {
std::cerr << " extraneous char found in packet " << seq << std::endl;
break; // something extraneous in string
}
std::cout << bangAtPound_Indx << " message" << seq << ": '"
<< packet.substr(startIndx, printLength) << "'" << std::endl;
}while(0);
std::cout << std::endl;
}
This outputs
13 packet1: 'MC123, 456!##'
10 message1: '123, 456'
18 packet2: 'MC123, 456, 789!##'
15 message2: '123, 456, 789'
28 packet3: 'MC123, 456, 789, 987, 654!##'
25 message3: '123, 456, 789, 987, 654'
18 packet4: 'MC123, 456, 789##!'
'!##' not found in packet 4
18 packet5: 'MC123x 456, 789!##'
extraneous char found in packet 5
Note: String indexes start at 0. The index of the digit '1' is 2.
The correct approach is to look for existence / location of the "known termination" string, then take the substring up to (but not including) that substring.
Something like
str::string termination = "!#$";
std::size_t position = inputstring.find(termination);
std::string importantBit = message.substr(0, position);
You could check the front of the string separately as well. Combining these, you could use regular expressions to make your code more robust, using a regex like
MC([0-9,]+)!#\$
This will return the bit between MC and !#$ but only if it consists entirely of numbers and commas. Obviously you can adapt this as needed.
UPDATE you asked in your comment how to use the regular expression. Here is a very simple program. Note - this is using C++11: you need to make sure our compiler supports it.
#include <iostream>
#include <regex>
int main(void) {
std::string s ("ABC123,456,789!#$");
std::smatch m;
std::regex e ("ABC([0-9,]+)!#\\$"); // matches the kind of pattern you are looking for
if (std::regex_search (s,m,e)) {
std::cout << "match[0] = " << m[0] << std::endl;
std::cout << "match[1] = " << m[1] << std::endl;
}
}
On my Mac, I can compile the above program with
clang++ -std=c++0x -stdlib=libc++ match.cpp -o match
If instead of just digits and commas you want "anything" in your expression (but it's still got fixed characters in front and behind) you can simply do
std::regex e ("ABC(.*)!#\\$");
Here, .+ means "zero or more of 'anything'" - but followed by !#$. The double backslash has to be there to "escape" the dollar sign, which has special meaning in regular expressions (it means "the end of the string").
The more accurately your regular expression reflects exactly what you expect, the better you will be able to trap any errors. This is usually a very good thing in programming. "Always check your inputs".
One more thing - I just noticed you mentioned that you might have "more stuff" in your string. This is where using regular expressions quickly becomes the best. You mentioned a string
MC123, 456!##*USRChester.
and wanted to extract 123, 456 and Chester. That is - stuff between MC and !#$, and more stuff after USR (if that is even there). Here is the code that shows how that is done:
#include <iostream>
#include <regex>
int main(void) {
std::string s1 ("MC123, 456!#$");
std::string s2 ("MC123, 456!#$USRChester");
std::smatch m;
std::regex e ("MC([0-9, ]+)!#\\$(?:USR)?(.*)$"); // matches the kind of pattern you are looking for
if (std::regex_search (s1,m,e)) {
std::cout << "match[0] = " << m[0] << std::endl;
std::cout << "match[1] = " << m[1] << std::endl;
std::cout << "match[2] = " << m[2] << std::endl;
}
if (std::regex_search (s2,m,e)) {
std::cout << "match[0] = " << m[0] << std::endl;
std::cout << "match[1] = " << m[1] << std::endl;
std::cout << "match[2] = " << m[2] << std::endl;
if (match[2].length() > 0) {
std::cout << m[2] << ": " << m[1] << std::endl;
}
}
}
Output:
match[0] = MC123, 456!#$
match[1] = 123, 456
match[2] =
match[0] = MC123, 456!#$USRChester
match[1] = 123, 456
match[2] = Chester
Chester: 123, 456
The matches are:
match[0] : "everything in the input string that was consumed by the Regex"
match[1] : "the thing in the first set of parentheses"
match[2] : "The thing in the second set of parentheses"
Note the use of the slightly tricky (?:USR)? expression. This says "This might (that's the ()? ) be followed by the characters USR. If it is, skip them (that's the ?: part) and match what follows.
As you can see, simply testing whether m[2] is empty will tell you whether you have just numbers, or number plus "the thing after the USR". I hope this gives you an inkling of the power of regular expressions for chomping through strings like yours.
If you are sure about the ending of the message, message.substr(3, message.size()-6) will do the trick.
However, it is good practice to check everything, just to avoid surprises.
Something like this:
if (message.size() < 6)
throw error;
if (message.substr(0,3) != "MCX") //the exact numbers do not match in your example, but you get the point...
throw error;
if (message.substr(message.size()-3) != "!##")
throw error;
string data = message.substr(3, message.size()-6);
Just calculate the offset first.
string str = ...;
size_t start = 3;
size_t end = str.find("!##");
assert(end != string::npos);
return str.substr(start, end - start);
You can get the index of "!##" by using:
message.find("!##")
Then use that answer instead of 7. You should also check for it equalling std::string::npos which indicates that the substring was not found, and take some different action.
string msg = "MC4,512,541,3123!##";
for (int i = 2; i < msg.length() - 3; i++) {
if (msg[i] != '!' && msg[i + 1] != '#' && msg[i + 2] != '#')
cout << msg[i];
}
or use char[]
char msg[] = "MC4,123,54!##";
sizeof(msg -1 ); //instead of msg.length()
// -1 for the null byte at the end (each char takes 1 byte so the size -1 == number of chars)