C++: insert char to a string - c++

so I am trying to insert the character, which i got from a string, to another string.
Here I my actions:
1. I want to use simple:
someString.insert(somePosition, myChar);
2. I got an error, because insert requires(in my case) char* or string
3. I am converting char to char* via stringstream:
stringstream conversion;
char* myCharInsert;
conversion << myChar //That is actually someAnotherString.at(someOtherPosition) if that matters;
conversion >> myCharInsert;
someString.insert(somePosition, myCharInsert);
4. Everything seems to be compiling successfully, but program crashes the gets to
conversion >> myCharInsert;
line.
5.I am trying to replace char* with string:
stringstream conversion;
char* myCharInsert;
conversion << myChar //That is actually someAnotherString.at(someOtherPosition) if that matters;
conversion >> myCharInsert;
someString.insert(somePosition, myCharInsert);
Everything seems to be OK, but when someAnotherString.at(someOtherPosition) becomes space, program crashes.
So how do I correctly do this?

There are a number of overloads of std::string::insert. The overload for inserting a single character actually has three parameters:
string& insert(size_type pos, size_type n, char c);
The second parameter, n, is the number of times to insert c into the string at position pos (i.e., the number of times to repeat the character. If you only want to insert one instance of the character, simply pass it one, e.g.,
someString.insert(somePosition, 1, myChar);

Simplest is to provide yourself with a function that turns a character into a string. There are lots of ways of doing this, such as
string ToStr( char c ) {
return string( 1, c );
}
Then you can simply say:
someString.insert(somePosition, ToStr(myChar) );
and use the function in other cases where you want a string but have a char.

Everything seems to be compiling successfully, but program crashes the gets to
conversion >> myCharInsert;
The problem is that you are trying to dereference(access) myCharInsert(declared as a char* ) which is pointing to a random location in memory(which might not be inside the user's address space) and doing so is Undefined Behavior (crash on most implementations).
EDIT
To insert a char into a string use string& insert ( size_t pos1, size_t n, char c ); overload.
Extra
To convert char into a std::string read this answer

You can try:
std::string someString{"abc"};
someString.push_back('d');

Related

google tests: can not create string from char array?

I run this test:
TEST_F(CHAR_TESTS, wtf){
char letter[3] = {'A','B','C'};
char types[2] = {'o','s'};
char tmp[3];
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
for(int k=0;k<2;k++){
tmp[0]=letter[i];
tmp[1]=letter[j];
tmp[2]=types[k];
std::string combination(tmp);
std::cout << combination << std::endl;
}
}
}
}
For some reason, this print this:
AAo~
AAs~
ABo~
ABs~
ACo~
ACs~
BAo~
BAs~
BBo~
BBs~
BCo~
BCs~
CAo~
CAs~
CBo~
CBs~
CCo~
CCs~
I do not think it is an issue with the printing itself, as I ended up doing this after noticing some tests comparing strings generated from char arrays were not passing, and I could not figure out why. So it feels like indeed the "combination" strings do not end up having the expected content.
The same code in a "regular" executable (not a gtest) print out what is expected (the 3 chars without the weird supplementary chars).
Unfortunately std::string does not have a constructor that takes a reference to array of char. So you end up invoking the const char* constructor, and this one requires the pointer to point to the first element of a null terminated string. Your char arrays aren't null-terminated, so you end up with undefined behaviour.
You should null-terminate tmp, which you can do by declaring it with one extra character, and setting it to '\0'. You can achieve that like this
char tmp[4] = {};
The constructor in std::string combination(tmp); only works if tmp is nul terminated. Otherwise the constructor cannot find the length of the string.
However, you can help std::string by explicitly providing the size of the buffer:
std::string combination(tmp, sizeof(tmp));
This constructor is primarilly intended to construct a std::string from a part of a C-style string, but also works if given the full length.
char tmp[3]; is not null-terminated use char tmp[4] = {0};

How can I convert const char* to string and then back to char*?

I'm just starting c++ and am having difficulty understanding const char*. I'm trying to convert the input in the method to string, and then change the strings to add hyphens where I want and ultimately take that string and convert it back to char* to return. So far when I try this it gives me a bus error 10.
char* getHyphen(const char* input){
string vowels [12] = {"A","E","I","O","U","Y","a","e","i","o","u","y"};
//convert char* to string
string a;
int i = 0;
while(input != '\0'){
a += input[i];
input++;
i++;
}
//convert a string to char*
return NULL;
}
A: The std::string class has a constructor that takes a char const*, so you simply create an instance to do your conversion.
B: Instances of std::string have a c_str() member function that returns a char const* that you can use to convert back to char const*.
auto my_cstr = "Hello"; // A
std::string s(my_cstr); // A
// ... modify 's' ...
auto back_to_cstr = s.c_str(); // B
First of all, you don't need all of that code to construct a std::string from the input. You can just use:
string a(input);
As far as returning a new char*, you can use:
return strdup(a.c_str()); // strdup is a non-standard function but it
// can be easily implemented if necessary.
Make sure to deallocate the returned value.
It will be better to just return a std::string so the users of your function don't have to worry about memory allocation/deallocation.
std::string getHyphen(const char* input){
Don't use char*. Use std::string, like all other here are telling you. This will eliminate all such problems.
However, for the sake of completeness and because you want to understand the background, let's analyse what is going on.
while(input != '\0'){
You probably mean:
while(*input != '\0') {
Your code compares the input pointer itself to \0, i.e. it checks for a null-pointer, which is due to the unfortunate automatic conversion from a \0 char. If you tried to compare with, say, 'x' or 'a', then you would get a compilation error instead of runtime crashes.
You want to dereference the pointer via *input to get to the char pointed to.
a += input[i];
input++;
i++;
This will also not work. You increment the input pointer, yet with [i] you advance even further. For example, if input has been incremented three times, then input[3] will be the 7th character of the original array passed into the function, not the 4th one. This eventually results in undefined behaviour when you leave the bounds of the array. Undefined behaviour can also be the "bus error 10" you mention.
Replace with:
a += *input;
input++;
i++;
(Actually, now that i is not used any longer, you can remove it altogether.)
And let me repeat it once again: Do not use char*. Use std::string.
Change your function declaration from
char* getHyphen(const char* input)
to
auto hyphenated( string const& input )
-> string
and avoid all the problems of conversion to char const* and back.
That said, you can construct a std::string from a char_const* as follows:
string( "Blah" )
and you get back a temporary char const* by using the c_str method.
Do note that the result of c_str is only valid as long as the original string instance exists and is not modified. For example, applying c_str to a local string and returning that result, yields Undefined Behavior and is not a good idea. If you absolutely must return a char* or char const*, allocate an array with new and copy the string data over with strcpy, like this: return strcpy( new char[s.length()+1], s.c_str() ), where the +1 is to accomodate a terminating zero-byte.

String made from the first char of another string - why is it also printing the full original string?

Learning C++. I just want to grab the first character in a string, then make a new string based on such character, and then print it out:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
string name = "Jerry";
char firstCharacter = name.at(0);
string stringOfFirstCharacter = string(&firstCharacter);
cout << stringOfFirstCharacter;
return 0;
}
The output is:
J
Jerry
I don't really know why is it also printing Jerry. Why is that?
Your code has undefined behavior. The signature of the constructor that takes a pointer to char requires that it is a pointer to a null terminated string, which it is not in your case since it is a single character.
My guess is that the implementation you have uses the small object optimization, and that "Jerry" is small enough that it is stored inside the std::string object rather than dynamically allocated. The layout of the two objects in the stack happens to be first firstCharacter, then name. When you call std::string(&firstCharacter) it reads until it hits the first null character (inside the std::string buffer) and stops there.
You are constructing an std::string object from a char* (because you are taking the address of firstCharacter). A pointer to a character is not interpreted as a character itself by the constructor of std::string, but rather as a null-terminated string.
In this case, your program has Undefined Behavior, because the address of firstCharacter is not the address of the first character of a null-terminated string.
What you should be doing is:
string stringOfFirstCharacter(1, firstCharacter);
cout << stringOfFirstCharacter;
If you really want to create a one-character string. However, notice that in order to print the character to the standard output, you could have simply written:
cout << firstCharacter;
Or even:
cout << name.at(0);
With string(&firstCharacter), you are using the std::string constructor of the form
std::string( const char* s, const Allocator& alloc = Allocator() );
That form expects a pointer to a null-terminated array of characters. It is incorrect to pass a pointer to character(s) that are not null-terminated.
With your intention of initializing the string with 1 char, you should use the form:
string( 1, firstCharacter )
The string constructor you're using (the one that takes a char * argument), is intended to convert a C-style string into a C++ string object - not a single character. By passing it a single character you cause undefined behaviour.
In your specific case, there appears to not be a zero byte in memory after firstCharacter, so the constructor runs through and includes all of name along with it!

cin.getline() equivalent when getting a char from a function.

From what I understand cin.getLine gets the first char(which I think it a pointer) and then gets that the length. I have used it when cin for a char. I have a function that is returning a pointer to the first char in an array. Is there an equivalent to get the rest of the array into a char that I can use the entire array. I explained below what I am trying to do. The function works fine, but if it would help I could post the function.
cmd_str[0]=infile();// get the pointer from a function
cout<<"pp1>";
cout<< "test1"<<endl;
// cin.getline(cmd_str,500);something like this with the array from the function
cout<<cmd_str<<endl; this would print out the entire array
cout<<"test2"<<endl;
length=0;
length= shell(cmd_str);// so I could pass it to this function
You could use a string stream:
char const * p = get_data(); // assume null-terminated
std::istringstream iss(std::string(p));
for (std::string line; std::getline(iss, line); )
{
// process "line"
}
If the character array is not null-terminated but has a given size N, say std::string(p, N) instead.
First, if cmd_str is an array of char and infile returns a pointer to a string, that first assignment will give you an error. It tries to assign a pointer to a single char.
What you seem to want is strncpy:
strncpy(cmd_str, infile() ARRAY_LENGTH - 1);
cmd_str[ARRAY_LENGTH - 1] = '\0';
I make sure to add the string terminator to the array, because if strncpy copies all ARRAY_LENGTH - 1 characters, it will not append the terminator.
If cmd_str is a proper array (i.e. declared like char cmd_str[ARRAY_LENGTH];) then you can use sizeof(cmd_str) - 1 instead of ARRAY_LENGTH - 1 in my example. However, if cmd_str is passed as a pointer to a function, this will not work.

Different results using atoi

Could someone explain why those calls are not returning the same expected result?
unsigned int GetDigit(const string& s, unsigned int pos)
{
// Works as intended
char c = s[pos];
return atoi(&c);
// doesn't give expected results
return atoi(&s[pos]);
return atoi(&static_cast<char>(s[pos]));
return atoi(&char(s[pos]));
}
Remark: I'm not looking for the best way to convert a char to an int.
None of your attempts are correct, including the "works as intended" one (it just happened to work by accident). For starters, atoi() requires a NUL-terminated string, which you are not providing.
How about the following:
unsigned int GetDigit(const string& s, unsigned int pos)
{
return s[pos] - '0';
}
This assumes that you know that s[pos] is a valid decimal digit. If you don't, some error checking is in order.
What you are doing is use a std::string, get one character from its internal representation and feed a pointer to it into atoi, which expects a const char* that points to a NULL-terminated string. A std::string is not guaranteed to store characters so that there is a terminating zero, it's just luck that your C++ implementation seems to do this.
The correct way would be to ask std::string for a zero terminated version of it's contents using s.c_str(), then call atoi using a pointer to it.
Your code contains another problem, you are casting the result of atoi to an unsigned int, while atoi returns a signed int. What if your string is "-123"?
Since int atoi(const char* s) accepts a pointer to a field of characters, your last three uses return a number corresponding to the consecutive digits beginning with &s[pos], e.g. it can give 123 for a string like "123", starting at position 0. Since the data inside a std::string are not required to be null-terminated, the answer can be anything else on some implementation, i.e. undefined behaviour.
Your "working" approach also uses undefined behaviour.
It's different from the other attempts since it copies the value of s[pos]to another location.
It seems to work only as long as the adjacent byte in memory next to character c accidentally happens to be a zero or a non-digit character, which is not guaranteed. So follow the advice given by #aix.
To make it work really you could do the following:
char c[2] = { s[pos], '\0' };
return atoi(c);
if you want to access the data as a C string - use s.c_str(), and then pass it to atoi.
atoi expects a C-style string, std::string is a C++ class with different behavior and characteristics. For starters - it doesn't have to be NULL terminated.
atoi takes pointer to char for it's argument. In the first try when you are using the char c it takes pointer to only one character hence you get the answer you want. However in the other attempts what you get is pointer to a char which has happened to be beginning of a string of chars, therefore I assume what you are getting after atoi in the later attempts is a number converted from the chars in positions pos, pos+1, pos+2 and up to the end of the s string.
If you really want to convert just a single char in the string at the position (as opposed to a substring starting at that position and ending at the end of the string), you can do it these ways:
int GetDigit(const string& s, const size_t& pos) {
return atoi(string(1, s[pos]).c_str());
}
int GetDigit2(const string& s, const size_t& pos) {
const char n[2] = {s[pos], '\0'};
return atoi(n);
}
for example.