So basically I'm trying to add a character in the middle of a string. Normally in something like Python, this would be pretty straightforward, but I'm really not sure how to achieve this in C++. What I'm trying to achieve is something like this:
void converter(){
converted = ":regional_indicator_" + character + ":";
}
So basically, I'm trying to add the variable character of a type char in a string. Should I be storing character as a string instead?
For reference here's all of my code:
#include <iostream>
using namespace std;
string inputLine;
char character;
string converted;
void input(){
cout << "Please input the text in which you would like to be converted" << endl;
cin >> inputLine;
}
void converter(){
converted = ":regional_indicator_" + character + ":";
}
int main(){
input();
for (int i = 0; i < inputLine.length(); i++ ){
character = tolower(inputLine[i]);
}
return 0;
}
Append s behind the strings literals to treat them as std::strings instead of const char*s:
converted = ":regional_indicator_"s + character + ":"s;
You would need to do either using namespace std::literals or using namespace std::string_literals for it to work.
On a side note, in C++, it is strange to have a function converter() to modify a global variable using another global variable. You might want to consider passing character as a parameter to the function instead.
You can do it like this:
converted = ":regional_indicator_" + std::string(1, character) + ":";
This works because adding a string literal (const char *) to a string yields a string. But adding const char * and char results in pointer arithmetic. So, by constructing a std::string from "character" you end up with const char * + std::string yielding a string and then std::string + const char * again yields a string as the final result.
You can avoid invoking the std::string() constructor and memory allocation by using following. I have tested this before posting and it works:
void converter(){
converted = ":regional_indicator_";
converted.push_back(character);
converted.push_back(':');
}
It's better because "converted" already will have some extra memory reserved, so you will just be filling that extra memory with two more characters and won't be allocating new memory.
The wasy way to build strings is to use a std::ostringstream like this:
void converter(){
std::ostringstream oss;
oss << ":regional_indicator_" << character << ":";
converted = oss.str(); // copy the string out
// ... etc ...
}
The added advantage of that method is it converts numbers to string automatically too.
That's not the fastest way so if speed was important I would take advantage of the static nature of this concatenation like this:
std::string converter(){
static char* template = ":regional_indicator_X:";
template[20] = character; // replace the `X` with your character
converted.assign(template, 21); // assign your string all at once
// ... etc ...
}
That works because your string is of fixed length. If thread safety is required you can use thread_local static char* template....
Related
Consider a function
void foo(string s) {
...
}
I want to call the function as follows:
char ch = 'a';
foo(ch);
Of course it doesn't work as ch is a char and we need to convert it into a string.
I know I can do
char ch = 'a';
string str;
foo(str+ch);
I do not want to declare string str beforehand, I want to do something during the function call itself to convert ch into string, like:
char ch = 'a';
foo(some_operation_on_ch);
Is it possible to do so, if yes, how?
std::string has a constructor that takes a character and an integer for the number of times you what the character repeated. Using that you could do
foo(std::string(1, ch));
The class also has a constructor that takes c-style string and a integer denoting the number of characters to copy and you can use that constructor like
foo(std::string(&ch, 1));
You can use:
char ch = 'a';
foo(std::string(1, ch));
std::string has a "fill constructor" that creates a string with n copies (1 in the above example) of ch.
If you have a function:foo(std::string s) { std::cout << s << std::endl; } it will print 'a' and this should answer what you have asked for to do it inside the parenthesis.
I have a code that I'm trying to learn how to parse in C++. I understood everything I did, but I don't understand how to work with the likes of atoi(), atof (), strtod (). I know what it's supposed to do, but I don't understand why the compiler doesn't like it. My focus on the error is "scores[line_count] = strtod (score);"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <iomanip>
using namespace std;
int readScores(string inputFile, string name[], float scores[], int array_size)
{
//delcare variables
ifstream infile;
int line_count = 0;
string line;
string named;
float score;
char character;
int word_index;
string names[array_size];
// open input file
infile.open(inputFile);
//Check if file opens succesfully.
if(infile.fail())
{
cout << "File cannot open!!" << endl;
return -1;
}
while(getline(infile, line))
{
cout << line << endl;
// PARSING GOES HERE
word_index = 0;
for(int i=0; i < (int)line.length(); i++)
{
character = line[i];
if (character == ',')
{
names[line_count] = named;
named = "";
word_index++;
}
else
{
if(word_index == 0)
{
named += character;
}
else if (word_index == 1)
{
score += character;
cout << character << " " << endl;
}
}
}
scores[line_count] = strtod (score);
line_count++;
}
//close file
infile.close();
//return line count
return line_count;
cout << line_count << endl;
}
int main(void)
{
int array_size = 50;
string inputFile = "Test.txt";
string name [array_size];
float scores [array_size];
readScores(inputFile, name, scores, array_size);
}
The function strtod() takes the form
double strtod (const char* str, char** endptr);
But you only give it the string.
As you can see it takes two parameters, the string you wish to convert to a double, and an "endptr". The endptr is described here as a
Reference to an already allocated object of type char*, whose value is set by > the function to the next character in str after the numerical value.
This parameter can also be a null pointer, in which case it is not used.
So you need to declare a char pointer to save the next character after the decimal, even if there wont be one. This allows you to pull multiple doubles from a single string, much like a tokenizer.
char * endPtr;
scores[line_count] = strtod(score, &endPtr);
Edit
As Alex Lop pointed out, you aren't even passing a string to strtod, you're passing a float. It appears you would like to cast the float to a double?
Of course the compiler doesn't like it. Please read the description of strtod.
double strtod (const char* str, char** endptr);
Convert string to
double.
Parses the C-string str interpreting its content as a floating
point number (according to the current locale) and returns its value
as a double. If endptr is not a null pointer, the function also sets
the value of endptr to point to the first character after the number.
The function first discards as many whitespace characters (as in
isspace) as necessary until the first non-whitespace character is
found. Then, starting from this character, takes as many characters as
possible that are valid following a syntax resembling that of floating
point literals (see below), and interprets them as a numerical value.
A pointer to the rest of the string after the last valid character is
stored in the object pointed by endptr.
And in your code you pass to strtod only one parameter which is of type float and store the returned result of double into an array of floats. If you want to move the value of float from one variable to another, you don't need any "convertion" function:
scores[line_count] = score;
NOTE: I didn't really review your code as you asked specifically about scores[line_count] = strtod (score);. But after I looked how you modify score, maybe it should have been string and not float. If so, then it is the another point to fix.
I was wondering how I could convert an int to a string and then add it to an existin string. i.e.
std::string s = "Hello";
//convert 1 to string here
//add the string 1 to s
I hope I'm making sense. Thank you very much in advance for any answer.
If the number you want to append is an integer or floating point variable, then use std::to_string and simply "add" it:
int some_number = 123;
std::string some_string = "foo";
some_string += std::to_string(some_number);
std::cout << some_string << '\n';
Should output
foo123
The "modern" way is to use std::to_string(1). In fact, various overloads of std::to_string exist for different number types.
Putting this together you can write std::string s = "Hello" + std::to_string(1);
Alternatively you can use std::stringstream which can be faster due to fewer string concatenation operations which can be expensive:
std::stringstream s;
s << "Hello" << 1;
// s.str() extracts the string
I have a string which actually contains a number and a string, separated by ,, for instance "12,fooBar".
I would like to put it into separated variables, i.e. the number into unsigned int myNum and the string into std::string myStr.
I have the following snipped of code:
size_t pos1=value.find(',');
std::cout << value.substr(0, pos1) << " and "
<< (value.substr(0, pos1)).c_str() << std::endl;
This yields 12 and 1. Anything I missed here? What happend to the 2 in the second part?
Note: I isolated the problem to this snipped of code. I need c_str() to pass it to atoi to get the unsigend int. Here I don't want to print the second part.
Update: I actually get the string from levelDB Get. If I put a test string like I put here, it works.
The posted code produces the same substring: value.substr(0, pos1). Note that std::string::substr() does not modify the object, but returns a new std::string.
Example:
#include <iostream>
#include <string>
int main ()
{
std::string value ="12,fooBar";
unsigned int myNum;
std::string myStr;
const size_t pos1 = value.find(',');
if (std::string::npos != pos1)
{
myNum = atoi(value.substr(0, pos1).c_str());
myStr = value.substr(pos1 + 1);
}
std::cout << myNum << " and "
<< myStr << std::endl;
return 0;
}
Output:
12 and fooBar
EDIT:
If the unsigned int is the only piece required then the following will work:
unsigned int myNum = atoi(value.c_str());
as atoi() will stop at the first non-digit character (excluding optional leading - or +), in this case the ,.
The cleanest C++ style solution to this problem is to use a stringstream.
#include <sstream>
// ...
std::string value = "12,fooBar";
unsigned int myNum;
std::string myStr;
std::stringstream myStream(value);
myStream >> myNum;
myStream.ignore();
myStream >> myStr;
Your second substr should be value.substr(pos1+1,value.length())
One more option is using std::from_chars function from the 17th standard (< charconv > header):
int x;
from_chars(&s[i], &s.back(), x); // starting from character at index i parse
// the nearest interger till the second char pointer
There are different overloads for different types of value x (double etc.).
everybody I have problem with string concatenation in C++, here is my code
map<double, string> fracs;
for(int d=1; d<=N; d++)
for(int n=0; n<=d; n++)
if(gcd(n, d)==1){
string s = n+"/"+d;// this does not work in C++ but works in Java
fracs.insert(make_pair((double)(n/d), s));
}
How can I fix my code?
Try like this.
stringstream os;
os << n << "/" << d;
string s =os.str();
In C++ you have to convert an int to a string before you can concatenate it with another string using the + operator.
See Easiest way to convert int to string in C++.
Use streams, in your case, a stringstream:
#include <sstream>
...
std::stringstream ss;
ss << n << '/' << d;
Later, when done with your work, you can store it as an ordinary string:
const std::string s = ss.str();
Important (side-) note: Never do
const char *s = ss.str().c_str();
stringstream::str() produces a temporary std::string, and according to the standard, temporaries live until the end of the expression. Then, std::string::c_str() gives you a pointer to a null-terminated string, but according to The Holy Law, that C-style-string becomes invalid once the std::string (from which you receved it) changes.
It might work this time, and next time, and even on QA, but explodes right in the face of your most valuable customer.
The std::string must survive until the battle is over:
const std::string s = ss.str(); // must exist as long as sz is being used
const char *sz = s.c_str();
n and d are integers. Here is how you can convert integer to string:
std::string s;
std::stringstream out;
out << n << "/" << d;
s = out.str();
You could use a stringstream.
stringstream s;
s << n << "/" << d;
fracs.insert(make_pair((double)n/d, s.str()));
No one has suggested it yet but you can also take a look at boost::lexical_cast<>.
While this method is sometimes criticized because of performance issues, it might be ok in your situation, and it surely makes the code more readable.
Unlike in Java, in C++ there is no operator+ that explicitly converts a number to a string. What is usually done in C++ in cases like this is...
#include <sstream>
stringstream ss;
ss << n << '/' << d; // Just like you'd do with cout
string s = ss.str(); // Convert the stringstream to a string
I think sprintf(), which is a function used to send formatted data to strings, would be a much clearer way to do it. Just the way you would use printf, but with the c-style string type char* as a first(additional) argument:
char* temp;
sprint(temp, "%d/%d", n, d);
std::string g(temp);
You could check it out at http://www.cplusplus.com/reference/cstdio/sprintf/