I am trying to create a string by accessing its individual index positions and trying to print it.
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s="";
s[0]='a';
s[1]='b';
s[2]='c';
s[3]='d';
cout << s << endl;
for(int i = 0; i < 4; i++)
cout << s[i] << endl;
return 0;
}
This doesn't print a entire string but does print its individual characters.
Following code prints both the strings and its individual characters.
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s=" ";
s[0]='a';
s[1]='b';
s[2]='c';
s[3]='d';
cout << s << endl;
for(int i = 0; i < 4; i++)
cout << s[i] << endl;
return 0;
}
Why does this happen. Links to any further reading are appreciated.
Strings don't grow automatically
This string has zero size
string s="";
This code is an error because s[0] does not exist (since the string has zero size).
s[0]='a';
Because this is an error your program has undefined behaviour, which means any output is possible, including the strange behaviour you see.
If you want to add a character to a string use push_back (or +=)
s.push_back('a');
s.push_back('b');
s.push_back('c');
s.push_back('d');
Now that the string has some characters you can use [] to access them (or change them).
String, similarly to some other STL(Standard template library) classes is a dynamic template class.
What you're doing in your code is creating an empty string and then trying to insert elements into non-existing indices, which in an STL type class means you try to access a memory which was not allocated.
What you want to do when inserting elements into your string is use the push_back method, which will insert elements to the end of your string (and handle the memory allocation automatically).
If you know how many elements will be inserted before performing those actions, you can minimize the number of memory allocations by using the reserve method before using push_back.
For example, in your code we could opt to something like this:
s.reserve(5);
s.push_back('a');
s.push_back('b');
s.push_back('c');
s.push_back('d');
If we do not reserve memory ahead there could be more allocations and de-allocations as the string increases in size which can be expensive.
Related
In this program,I store integer values from 0 to 4 in a string and I want to print this string.
CODE:
int main()
{
string str=" ";
for(int i=0;i<5;i++)
str[i]=i+'0';
cout<<str;
return 0;
}
But when i run this program,it just shows first element(means '0') of string.
Can anybody tell me the reason,Why this program does not print whole string in output?
Actually, when you are using for loop, it is accessing position in string changing it. Since when you have initialized string as string str = " " this means our string is of single whitespace. After which for loop access that string and look for the index str[i] and changes its value to i+'0'.
So, when we are writing code as
for(int i=0; i< 5; i++){
str[i]=i+'0';
cout<<str[i];
}
it seems, like for that block, str[i] value is i+'0', which is printed, but str doesn't update. Due to which when you do cout<<str; it again shows 0 as the answer.
To solve this issue we can use property of concatenation, refer the below code
#include <iostream>
using namespace std;
int main()
{
string str;
for(int i=0;i<5;i++)
str+=i+'0';
cout<<str;
return 0;
}
This gives the required result as 01234.
Hope this helps you.
The code doesn't work as expected because you exceeded the string greatest index which is 0 because the size of your string is 1 as the previous answer say.
This is a modification
int main()
{
std::string str=" ";
for(int i=0;i<5;i++)
str[i]=i+'0';
std::cout<<str;
return 0;
}
You are exceeding array boundaries, because you initialized the string as containing only one space. If you give it more spaces, the code works:
string str = " ";
int main()
{
string str=" "; // str.size() == 1
for(int i=0;i<5;i++)
str[i]=i+'0'; // str.size() is still 1
cout<<str; // str.size() is still 1
}
In str[i], if ...
i>str.size() you are accessing the array out of bounds and get undefined behaviour.
i==str.size() (where the null terminator is) and you change that value, you also get undefined behaviour.
But when i am printing this string with the help of for loop,this program prints whole string.e.g:
for(int i=0; i<5; i++) {
cout<<str[i]<<" ";
}
Why this loop print whole string, but not cout<<str?
You've made changes out of bounds and have undefined behaviour. It's possible that you can read the values back one-by-one (instead of getting a program crash) due to short string optimization - but the size() of str is still 1 since you haven't changed the size.
If your loop had gone further, outside the area used by short string optimization, like this:
for(int i=0; i<25; i++) {
cout<<str[i]<<" ";
}
it would be even more likely to result in a crash.
when we are assigning
string str = " ";
here " " is of type const char[2];size is 2: 1 lenght of character and 1 length for '\0' (Null Terminated) character.
This gets copied into string str by calling operator= overloaded function.
When We are trying to access str[] with more than 0,1 index of subscript[] say 2 its doing memory violation and that is causing the exception "string subscript out of range",
if you try to access [0] and [1] it will work fine or instead of accessing particular location using array subscript, concatenation (+=) will help.
I cannot print the string str2[i].a even though I can print the same in str1[i].a
I am getting the individual characters in the string as I print them by the index values
I can also print the str1[i].a string that I had entered before
Thanks!!
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class st
{
public:
string a;
int col;
}str1[200],str2[200];
int main()
{
int i=0,j=0,num,l=0,len=0;
string str;
for(i=0;;i++)
{
cin>>num;
str1[i].col=num;
if(str1[i].col==0)
break;
cin>>str1[i].a;
cout<<str1[i].a; // I get string entered before
}
for(i=0;;i++)
{
if(str1[i].col==0)
break;
len = str1[i].a.size()-1;
//cout << len << endl;
l=0,j=0;
for(;;)
{
str2[i].a[l]=str1[i].a[j];
l++;
j=((j+str1[i].col)%len);
if(j==0)
{
str2[i].a[l]=str1[i].a[len];
cout << str2[i].a[l];//I get the char assigned above
l++;
str2[i].a[l]='\n';
break;
}
}
cout << str2[i].a; // I get nothing after I print
cout << str2[i].a[0];// I get the required character of string
cout << str2[i].a[5];//I get the required character of string
cout << str2[i].a[8];//I get the required character of string
}
return 0;
}
What you forget to do is to preallocate the buffer for your second string. It is only safe to assign a value to a character in an std::string if that string has at least that many characters (in other words, str2.a[2] = 'a' is safe is std2.a has a length of at least three, but is not safe if it has any smaller length). In your case none of the str2s is ever assigned anything, so they are all empty and have length of 0.
One solution would be to preallocate your string in advance, but even better, since you only write characters to the end, use push_back instead of square brackets, as in
str2[i].push_back(str1[i].a[j]);
instead of
str2[i].a[l]=str1[i].a[j];
To explain why you can print individual characters, but not the entire string, note that what you do is technically an undefined behavior [1], I would assume that what it does is when you print the entire string, it looks at its length, sees that it is zero, and skips printing anything, but when you print individual characters, it looks at the buffer it allocated for the string (which is probably of non-zero size, to make early push_backs effective), and sees the changes you made to them.
[1] http://www.cplusplus.com/reference/string/string/operator%5B%5D/, see in particular:
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.
I have the below piece of code and I'm very confused by it. I'm trying to figure out how much memory (bytes of memory/space is actually being taken up by my partially filled array). I've got the below piece of code but I'm a bit confused.
If I declare a string array of 8 elements, and partially fill the elements with the two strings. The for loop will start at 0 and go until size of my array 32 possible bytes (assuming I need 4 bytes per string) divided by size of the first element in the array. That is returns 4 - the size of the element of the first string in the array. But that still doesn't tell me how many letters/characters are in that string.
I understand inside the loop we increment count when the value in the array doesn't equal a blank/null value. Giving us the total filled (non empty) positions in our array. However I still don't have a value for our actual amount of characters.
How does this tell us how many characters are in my strings?
#include <iostream>
#include <string>
using namespace std;
int main()
{
string test_array[8] = {"henry", "henry2"};
size_t count = 0;
for (size_t i = 0; i < sizeof(test_array)/sizeof(*test_array); i++)
{
cout << "NOT THE POINTER: "<<sizeof(test_array) << endl;
cout << "POINTER: "<<sizeof(*test_array) << endl;
if(test_array[i] != "")
count ++;
}
int num_elem = sizeof(test_array)/sizeof(test_array[0]);
cout << num_elem << endl;
cout << count << endl;
return 0;
}
To know how many characters are in a std::string use the size() method.
I am creating a dynamic array inside a function. The code (posted below) runs without any problem. I am wondering if the way I have written is the right way to do it or if it will create problems in more complicated codes in the future. I am aware that the specific task my program (below) is trying to achieve is better effected with strings or vectors. But I created this artificial example to get my question across. however, if you strongly feel that dynamic arrays should be avoided, please feel free to share your opinion and the reasoning for it.
Result of my prior research: I was unable to find a coherent discussion on legality and morality of creating dynamic arrays using new [] and later deleting them in a different scope.
Thanks for your thoughts and insights.
My example code follows:
==========================
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
void getNonPunct(string _str, char* &_npcarr, int &_npsize);
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
// Now return the memory allocated with 'new' to heap
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void getNonPunct(string _str, char* &_npcarr, int &_npsize)
//This void function takes an input array of strings containing arbitrary
//characters and returns a pointer to an array of characters containing only
//the non-punctuation characters in the input string. The number of
//non-punctuation characters are stored in size. Prior to the function call,
//int_arr and size are undefined. After the function call, char_arr points to
//the first location of an array of the non-punctuation character array.
//'size' is equal to the number of non-punctuation characters in the input
//string.
{
// First get the number of non-punctuation characters in the string
int str_len, npcount = 0;
str_len = static_cast<int>( _str.length() );
_npsize = 0;
for (int i = 0; i <= str_len - 1; i++)
{
if ( !ispunct(_str[i]) )
_npsize++;
}
// Now that you know how many non-punctuation characters are in the string,
// create a (dynamic) character array of _npsize.
_npcarr = new char [_npsize];
for (int k = 0; k <= str_len - 1; k++)
{
if ( !ispunct(_str[k]) )
_npcarr[npcount++] = _str[k];
}
return;
}
Is it valid? Yes. The array pointed to by npchar_arr exists until you destroy it and it is okay to destroy it using a delete[] expression in another function.
Is it a good idea? No. You would be much better off using a smart pointer that manages the lifetime of the object automatically, releasing you from the responsibility of delete[]ing the pointer manually yourself.
Consider using a std::unique_ptr<char[]> if your compiler and Standard Library support unique_ptr, or std::auto_ptr or std::shared_ptr if you cannot use unique_ptr (shared_ptr may also be found in Boost and C++ TR1).
Allocating in one scope and deleting in another is one of the major reasons for using dynamic allocation instead of an automatic local variable.
As James says, prefer to use smart pointers to track dynamically allocated objects.
The only constraint I can think of on allocation in one scope and deallocation in another is multi-component applications where different components are built with different compilers (or maybe different versions of the same compiler). On Windows, each compiler provides its own memory management library, and you shouldn't free memory from a different component than the one that allocated it. Or you can use Windows-provided memory management routines which are common to all compilers (e.g. HeapAlloc/HeapFree). On Linux, everyone uses the glibc-supplied malloc, free, new[], and delete[], so it isn't such an issue. For other OSes, you need to investigate.
This example is very trivial, but image the following modification of your code:
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
return(0); // WHOOPS! I JUST RETURNED AND DIDN'T FREE THE MEMORY
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
I just returned before freeing the memory, which results in a memory leak! Of course, you might be thinking that you would never do such a thing, but imagine a much more complex program, it is easy to make such a mistake as the above, and using smart pointers as the other answers suggest, would alleviate you of having to worry about such tasks.
#include<iostream>
using namespace std;
int main()
{
char arr[200];
while(1) {
cin >> arr;
int i = sizeof(arr);
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
For the input of 34,
This code outputs :The arr input is 34 and the size of the array is 200
while I want it to get the size of the used space of the array . So for The last input i want it to output :The arr input is 34 and the size of the array is 2
Can someone tell me how?
Maybe you want strlen(arr) here. It must be null terminated, otherwise the cout << arr would not have worked.
You would need to #include <cstring>
There's no automatic way to do what you want in the general case - you'll need to keep track somehow, either with your own counter, or by seeding the array with an 'invalid' value (that you define) and search for to find the end of the used elements (that's what the '\0' terminator character in a C-style string is).
In the example code you posted, the array should receive a null terminated C-style string, you can use that knowledge to count the number of valid elements.
If you're using C++ or some other library that has some more advanced data structures, you may be able to use one that keeps track of this kind of thing for you (like std::vector<>).
the size of the used space of the array
There is no such thing. If you have an array of 200 chars, then you have 200 chars. Arrays have no concept of "used" and "unused" space. It only works with C-strings because of the convention that those are terminated by a 0 character. But then again, the array itself cannot know if it is holding a C-string.
in a less involved manner, you can just count through each character till you hit a null with just a while loop. It will do the exact same thing strlen() does. Also, in practice, you should do type checking with cin, but i'll assume this was just a test.
#include <iostream>
using namespace std;
int main()
{
char arr[200];
int i;
while(1) {
cin >> arr;
i=0;
while (arr[i] != '\0' && i<sizeof(arr))
i++;
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
Just for completeness, here is a much more C++ like solution that is using std::string instead of a raw char array.
#include <iostream>
#include <string>
int
main()
{
while (std::cin.good()) {
std::string s;
if (std::cin >> s) {
std::cout
<< "The input is " << s
<< " and the size is " << s.length()
<< std::endl;
}
}
return 0;
}
It doesn't use an array, but it is the preferable solution for this kind of problem. In general, you should try to replace raw arrays with std::string and std::vector as appropriate, raw pointers with shared_ptr (scoped_ptr, or shared_array, whatever is most appropriate), and snprintf with std::stringstream. This is the first step to simply writing better C++. You will thank yourself in the future. I wish that I had followed this advice a few years ago.
Try it
template < typename T, unsigned N >
unsigned sizeOfArray( T const (&array)[ N ] )
{
return N;
}