c++ creating string using char array - c++

currently learning strings, i have the following cases :
string s;
s[0]='a'; s[1]='b';
cout<<s;
string s; s.clear();
s+='a'; s+='b';
cout<<s;
I get empty string as output from 1st example, and the 2nd works fine.
I get that the 1st is undef behavior and that we 'push' an element the second time instead of assigning a value.
Any more clarification will be appreciated.

The operator [] returns a reference to the character at position pos in the string, it does reading value rather than insert and resize std::string.
You cannot insert to null assigned value, thats why you get undefined behaviour. First resize the string and then try to insert using [] the operator.

Related

c++ string constructed as char array [duplicate]

This question already has answers here:
I can't double characters inside string with function
(3 answers)
Closed 2 years ago.
currently learning strings, i have the following:
string s;
s[0]='a'; s[1]='b';
cout<<s;
string s; s.clear();
s+='a'; s+='b';
cout<<s;
I get empty string as output from 1st example, and the 2nd works fine. I get that the 1st is undef behavior and that we 'push' an element the second time instead of assigning a value.
Any more clarification will be appreciated
string s;
creates empty string
s[0]='a'; s[1]='b';
this is undefined behavior, since empty string have size zero, so required buffer may not exists.
It "works" since all major compilers are using Small String Optimization (SSO). In this optimization size of string object, allows to keep small string inside that object not on a heap. As a result minimum capacity of std::string is none zero (15 in gcc if I remember correctly).
cout<<s;
Now deeding on how this stream operator is implemented it can print empty string (size size of string is zero) or "ab" or "ab<some thrash>".
On gcc it prints nothing.
To fix it you can:
resize string first s.resize(2)
use push_back API

string not copying correctly and showing error: cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}'

I was trying to make Substrings of exactly half the length of original string and then sorting them in order of their ASCII codes and finally checking their equality by using strcmp() library function.
(That is i was trying to check if the parent string can be divided in two equal halves.)
So here is what I did:
Took input of parent string from user by cin.
Then I used variable hlength to store the value of half of the length of original string.
Now I declared two strings of equal lengths (equal to hlength ) so that first half of string is copied to substring named "s1" and the rest half is copied to substring "s2". i used for loops to copy the elements of the string.
To check whether the strings are correctly copied or not I printed each element of string just after copying them by using cout<< as you can see in the attached code.
Till now everything seemed alright as the result of individual elements when being printed were correct.
But!! here comes a situation which I never faced before: When I tried to print complete string using cout<<
The output was blank.
Later instead of printing the strings I just tried comparing them with the strcmp() function but it resulted in error: cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string}' to 'const char' for argument '1' to 'int strcmp(const char*, const char*)'*
#include <bits/stdc++.h>
#define fastIO ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define llt long long int
using namespace std;
int main()
{
int length,hlength,i,result;
string s;
cin>>s;
length = s.length();
hlength = length/2;
string s1,s2;
for(i = 0; i< hlength;i++)
{
s1[i] = s[i];
cout<<s1[i]<<endl; //each element gets printed successfully
}
for(i = 0; i< hlength ; i++)
{
s2[i] = s[length -1 - i];
cout<<s2[i]<<endl; //the elements are printed successfully, but obviously in the reverse order( order not matters)
}
cout<<s1<<endl<<s2; // no strings printed
sort(s1.begin(),s1.end());
sort(s2.begin(),s2.end());
result = strcmp(s1 , s2); //ERROR
cout<<result<<endl;
return 0;
}
PS: The original string is even in length.
Please help me know why the string is not printed but individual elements are printed correctly.
And what does that error means?
strcmp expects char pointers - this is what your error message tells you.
There is string::compare or operator == which you can use without this error. See:
Stackexchange Topic and cppreference.
For completeness you could also convert your std::strings to char pointers with c_str() method of your strings, but this is kind of ugly.
You see the real values, but you experience undefined behaviour. s1 and s2 are intialized with zero length. Operator [pos] definition:
If pos is less than the string length, the function never throws exceptions (no-throw guarantee).
If pos is equal to the string length, the const-version never throws exceptions (no-throw guarantee).
Otherwise, it causes undefined behavior.
The last point is what you experience - Maybe you write to a part of memory which does not belong to the string, but can access it in the same scope still. But when you try to cout the string, there is nothing written in the strings memory block. But who knows, its undefined behavior, anything can happen.
Section Exception safety in:
http://www.cplusplus.com/reference/string/string/operator[]/

How do I take only numbers from a string?

I need to copy numbers from a string to another string in c++. I wrote this code but it only copies the first number in the string.
class Number{
private:
string value;
public:
void Print(){
cout<<value;
}
Number(string dgr){
int i = 0;
for(int j=0; j<dgr.length();j++){
if(isdigit(dgr[j])){
value[i]=dgr[j];
i++;
}
}
}
};
With the code you show, the string value is an empty string. That means all indexing into it will be out of bounds and you will have undefined behavior.
Instead append the characters to the string:
value += dgr[j];
operator [] in the string can be used to modify already existing characters. It does not extend the length of the string. So, if you pre-assign some value to 'value' you would see the characters modified there (up to the length of this string).
What you rally need is something like this:
value += dgr[j];
I am unable to comment but as a response to:
Wow thanks but still have a problem. when I input "a6s54da65sd4a" it returns "6546541877994624". What's that "1877994624" part? When I recompile and run it the number won't change.
I can't see the value being reset or initialized anywhere. What is the size of value?
I would use append instead of accessing various elements in "value". Something like value.append(1, dgr[j]);

Character Constant Array is empty, even though values has been assigned to it [C++]

I am facing problems while assigning string value in a character constant array. Every time when it assigns string value to a particular position of character array. That position value in an array become initialized to empty string, after getting a new value in string variable. I have tried hard to get it out but in vain. Following is the code that I am using:
const char *array[40];
string line="";
ifstream myfile( "text.txt");
if (myfile)
{
int in=0;
while (getline( myfile, line ))
{
array[in]=line.data();
in++;
}
myfile.close();
}
else return;
Now, array variable has all the empty string values. Please let me know how can I do it?
You are accessing the internal data buffer of string object line and let array[in] point to it. When reading the next line, this buffer is either overwritten or may point to a different memory location, such that the previously written array[in] points to a memory that has been overwritten with new content or is invalid at all.
If you want to use a const char*[...] array, copy the buffer first:
array[in]= strdup(line.c_str());
Note further, that line.data() gives you an array but without guarantee of a terminating 0x0 at the end. See documentation of string::data() at cppreference.com

Why assigning characters to C++ string results in string having 0 length?

I manually assigned characters from a string to another array of string. But why it results in having 0 length and cannot be directly printed? although the characters in the string can be printed by iterating.
Code:
#include <iostream>
#include <string.h>
using namespace std;
int main() {
string domain[100],text="google";
for(int i=0;i<6;i++){
domain[0][i] = text[i];
}
for(int k=0;k<6;k++){
cout<<domain[0][k];
}
cout<<endl;
cout<<"String length: "<<domain[0].length()<<endl;
cout<<"Output string directly from array : "<<domain[0]<<endl;
return 0;
}
Output :
google
String length: 0
Output string directly from array :
By writing
string domain[100]
you create an array of 100 empty strings then you try to access string characters by using [] operator, but the string has no characters, so setting them won't work. You shouldn't even try to access them this way. It causes Undefined Behavior.
EDIT.
In this line:
domain[0][i] = text[i];
you try to set the i-th character of the first string. But how many characters this string has? None.
It would be the same as if you'd try something like this:
domain[0] = "abc";
Then you can access domain[0][0] but can't access domain[0][3] because it has only 3 characters. Try to think of it as of an array. You cannot set 10-th element if the array has only 5 elements.
string domain[100];
You now have an array of 100 empty string objects.
(Why? You are only ever using the first one...)
for(int i=0;i<6;i++){
domain[0][i] = text[i];
}
On first iteration, string::operator[] will return a reference to CharT() (the null character). Modifying that character is undefined behaviour. (Since C++11; earlier versions would invoke undefined behaviour at the operator[] already.)
Note that, in C++, the null character is not really a part of the string. This is different from C's char[].
So your modifying the null character was undefined behaviour and did not actually add a character to the string object. On second iteration, there still is no character in the string, so domain[0][1] is an out-of-bounds access (which is also undefined behaviour).
You are probably looking for string::operator+=() or string::push_back()...
Unrelated:
#include <string.h>
That's the wrong header. C++ strings are in <strings>, <string.h> is the now-deprecated way of including the C string header (the one with strcpy() et al.). If you actually want that, include <cstring>, which introduces the names from <string.h> in the std:: namespace.