Standard Template String class: string.fill() - c++

I need a way to create a string of n chars. In this case ascii value zero.
I know I can do it by calling the constructor:
string sTemp(125000, 'a');
but I would like to reuse sTemp in many places and fill it with different lengths.
I am calling a library that takes a string pointer and length as an argument and fills the string with bytes. (I know that technically string is not contiguous, but for all intents and purposes it is, and will likly become the standard soon). I do NOT want to use a vector.
is there some clever way to call the constructor again after the string has been created?

The string class provides the method assign to assign a given string a new value. The signatures are
1. string& assign ( const string& str );
2. string& assign ( const string& str, size_t pos, size_t n );
3. string& assign ( const char* s, size_t n );
4. string& assign ( const char* s );
5. string& assign ( size_t n, char c );
6. template <class InputIterator>
string& assign ( InputIterator first, InputIterator last );
Citing source: cplusplus.com (I recommend this website because it gives you a very elaborated reference of the C++ standard libraries.)
I think you're looking for something like the fifth one of these functions: n specifies the desired length of your string and c the character filled into this string. For example if you write
sTemp.assign(10, 'b');
your string will be solely filled with 10 b's.
I originally suggested to use the STL Algorithm std::fill but thus your string length stays unchanged. The method string::resize provides a way to change the string's size and fills the appended characters with a given value -- but only the appended ones are set. Finally string::assign stays the best approach!

Try to use:
sTemp.resize(newLength, 'a');
References:
void __CLR_OR_THIS_CALL resize(size_type _Newsize)
{ // determine new length, padding with null elements as needed
resize(_Newsize, _Elem());
}
void __CLR_OR_THIS_CALL resize(size_type _Newsize, _Elem _Ch)
{ // determine new length, padding with _Ch elements as needed
if (_Newsize <= _Mysize)
erase(_Newsize);
else
append(_Newsize - _Mysize, _Ch);
}

Related

Is this how the size() function really works in std::string?

I wrote a simple function that can get the size of a std::string class object, and I know that size() function in std::string does the same job, So I wanted to know if the size() function really works like my function or if it is more complicated? If it's more complicated, then how?
int sizeOfString(const string str) {
int i=0;
while (str[i] != '\0') {
++i;
}
return i;
}
An std::string can contain null bytes, so your sizeOfString() function will produce a different result on the following input:
std::string evil("abc\0def", 7);
As for your other question: the size() method simply reads out an internal size field, so it is always constant time, while yours is linear in the size of the string.
You can peek at the implementation of std::string::size for various implementations for yourself: libc++, MSVC, libstdc++.
No.
Firstly, a std::string can contain NUL characters that count as part of the length, so you can't use '\0' as a sentinal, in the way you would for C-strings.
Secondly, The Standard guarantees that std::string::size has constant complexity.
In practice there are a few slightly different ways to represent a std::string:
pointer to start of buffer, buffer size, length of current data - size() just has to return the length member.
pointer to start of buffer, pointer to end of current data, pointer to end of buffer - size() has to return a simple calculation.
It is different than your implementation.
Your function iterates over the string until it find a null byte. Null terminated string are how string are handled in C through char*. In C++ a string is a full object with member variables.
Specifically for C++, the size of the string is stored as part of the object, making the size() function simply read out the value of a variable.
For a interesting talk about how a string works in C++ check out this video from CppCon: https://www.youtube.com/watch?v=kPR8h4-qZdk
No. Not at all like that.
std::string actually maintains the size as one of its data member. Think of std::string as a container that keeps a pointer to the actual data(a char*) and length of that data separate.
When you call size(), it actually just returns this size, hence it's O(1).
One example to highlight it's effect in practicality will be
// WRONG IMPLEMENTATION
int wrongChangeLengthToZero(std::string& s)
{
assert(s.size() != 0);
s[0]='\';
return s.size(); // Won't return 0
}
// CORRECT
int correctChangeLengthToZero(std::string& s)
{
assert(s.size() != 0);
s.resize(0);
return s.size(); // Will return 0
}

Why aren't string literals passed as references to arrays instead of opaque pointers?

In C++, the type of string literals is const char [N], where N, as std::size_t, is the number of characters plus one (the zero-byte terminator). They reside in static storage and are available from program initialization to termination.
Often, functions taking a constant string doesn't need the interface of std::basic_string or would prefer to avoid dynamic allocation; they may just need, for instance, the string itself and its length. std::basic_string, particularly, has to offer a way to be constructed from the language's native string literals. Such functions offer a variant that takes a C-style string:
void function_that_takes_a_constant_string ( const char * /*const*/ s );
// Array-to-pointer decay happens, and takes away the string's length
function_that_takes_a_constant_string( "Hello, World!" );
As explained in this answer, arrays decay to pointers, but their dimensions are taken away. In the case of string literals, this means that their length, which was known at compile-time, is lost and must be recalculated at runtime by iterating through the pointed memory until a zero-byte is found. This is not optimal.
However, string literals, and, in general, arrays, may be passed as references using template parameter deduction to keep their size:
template<std::size_t N>
void function_that_takes_a_constant_string ( const char (& s)[N] );
// Transparent, and the string's length is kept
function_that_takes_a_constant_string( "Hello, World!" );
The template function could serve as a proxy to another function, the real one, which would take a pointer to the string and its length, so that code exposure was avoided and the length was kept.
// Calling the wrapped function directly would be cumbersome.
// This wrapper is transparent and preserves the string's length.
template<std::size_t N> inline auto
function_that_takes_a_constant_string
( const char (& s)[N] )
{
// `s` decays to a pointer
// `N-1` is the length of the string
return function_that_takes_a_constant_string_private_impl( s , N-1 );
}
// Isn't everyone happy now?
function_that_takes_a_constant_string( "Hello, World!" );
Why isn't this used more broadly? In particular, why doesn't std::basic_string have a constructor with the proposed signature?
Note: I don't know how the proposed parameter is named; if you know how, please, suggest an edition to the question's title.
It's largely historical, in a sense. While you're correct that there's no real reason this can't be done (if you don't want to use your whole buffer, pass a length argument, right?) it's still true that if you have a character array it's usually a buffer not all of which you're using at any one time:
char buf[MAX_LEN];
Since this is usually how they're used, it seems needless or even risky to go to the trouble of adding a new basic_string constructor template for const CharT (&)[N].
The whole thing is pretty borderline though.
The trouble with adding such a templated overload is simple:
It would be used whenever the function is called with a static buffer of char-type, even if the buffer is not as a whole a string, and you really wanted to pass only the initial string (embedded zeroes are far less common than terminating zeroes, and using part of a buffer is very common): Current code rarely contains explicit decay from array to pointer to first element, using a cast or function-call.
Demo-code (On coliru):
#include <stdio.h>
#include <string.h>
auto f(const char* s, size_t n) {
printf("char* size_t %u\n", (unsigned)n);
(void)s;
}
auto f(const char* s) {
printf("char*\n");
return f(s, strlen(s));
}
template<size_t N> inline auto
f( const char (& s)[N] ) {
printf("char[&u]\n");
return f(s, N-1);
}
int main() {
char buffer[] = "Hello World";
f(buffer);
f(+buffer);
buffer[5] = 0;
f(buffer);
f(+buffer);
}
Keep in mind: If you talk about a string in C, it always denotes a 0-terminated string, while in C++ it can also denote a std::string, which is counted.
I believe this is being addressed in C++14 building on user defined string literals
http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s
#include <string>
int main()
{
//no need to write 'using namespace std::literals::string_literals'
using namespace std::string_literals;
std::string s2 = "abc\0\0def"; // forms the string "abc"
std::string s1 = "abc\0\0def"s; // form the string "abc\0\0def"
}
You can create helper class that will fix that without using overload for every function
struct string_view
{
const char* ptr;
size_t size;
template<size_t N>
string_view(const char (&s)[N])
{
ptr = s;
size = N;
}
string_view(const std::string& s)
{
ptr = s.data();
size = s.size() + 1; // for '\0' at end
}
};
void f(string_view);
main()
{
string_view s { "Hello world!" };
f("test");
}
You should expand this class for helper function (like begine and end) to simplify usage in your program.

Why is there no std::string constructor for reference to array?

String literals are array objects:
typeid("hello").name() // char [6]
This seems convenient because the size of the string literal (=array) is known at compile time. So why is there no constructor to std::string that takes a reference to an array?
// this would be great
template <int N>
std::string(const char (& array)[N]);
Instead there are constructors that take const char * s, const char * s, size_t n or two InputIterators (eg. const char * begin, const char * end). All of these have drawbacks; the array is implicitly converted to a pointer and the size information is lost, so various methods are used to get it back. Working, but increasingly crazy examples:
// std::string(const char * s) version:
std::string s1("hello"); // calls std::strlen(s) internally
// std::string(const char * s, size_t n) version:
std::string s2("hello", 5); // programmer does std::strlen(s) mentally
std::string s3("hello", sizeof("hello")); // have to repeat string literal
// macro helper to avoid repeating string literal (ugly and dangerous)
#define STRLIT(x) std::string(x, sizeof(x)); // could be a function I guess
std::string s4 = STRLIT("hello"); // not much improvement (and macros are evil)
// std::string(InputIterator begin, InputIterator end) version:
char tmp[] = "hello"; // copy array
std::string s5(&tmp[0], &tmp[sizeof(tmp)]); // so you can reference it twice
// or trust the compiler to return the same address for both literals
std::string s6(&"hello"[0], &"hello"[sizeof("hello")]); // totally crazy
Such a templated constructor would be separately instantiated for each value of N. This could result in unnecessary code bloat.
The bloat is avoidable, but let's combine this thought with an answer from the ever-quotable Raymond Chen:
The answer to "Why doesn't this feature exist?" is usually "By default features don't exist. Somebody has to implement them."
The key question when considering whether there should be a constructor taking a char const (&)[N] (for some statically determined N) is what the content of the resulting std::string should be. It might be obvious to some what it should be but I don't think it is. Consider this std::string("abc\0def"):
It could be a string with 8 elements, including the two null bytes.
It could be a string with 7 elements, excluding the second null bytes.
It could be a string with 3 elements, excluding everything starting at the first null byte.
If you use
std::cout << "string='" << "abc\0def" << "'\n";
you get the third option. It seems, this is the only sane alternative...
Because there is a generic constructor that uses iterators:
std::string s7(std::begin(container), std::end(container));
Note: assumes c++11 for std::begin/std::end but you can quickly write something similar really easyily.

string.c_str() is const? [duplicate]

This question already has answers here:
Can I get a non-const C string back from a C++ string?
(14 answers)
Closed 5 years ago.
I have a function in a library that takes in a char* and modifies the data.
I tried to give it the c_str() but c++ docs say it returns a const char*.
What can I do other than newing a char array and copying it into that?
You can use &str[0] or &*str.begin() as long as:
you preallocate explicitly all the space needed for the function with resize();
the function does not try to exceed the preallocated buffer size (you should pass str.size() as the argument for the buffer size);
when the function returns, you explicitly trim the string at the first \0 character you find, otherwise str.size() will return the "preallocated size" instead of the "logical" string size.
Notice: this is guaranteed to work in C++11 (where strings are guaranteed to be contiguous), but not in previous revisions of the standard; still, no implementation of the standard library that I know of ever did implement std::basic_string with noncontiguous storage.
Still, if you want to go safe, use std::vector<char> (guaranteed to be contiguous since C++03); initialize with whatever you want (you can copy its data from a string using the constructor that takes two iterators, adding a null character in the end), resize it as you would do with std::string and copy it back to a string stopping at the first \0 character.
Nothing.
Because std::string manages itself its contents, you can't have write access to the string's underlying data. That's undefined behavior.
However, creating and copying a char array is not hard:
std::string original("text");
std::vector<char> char_array(original.begin(), original.end());
char_array.push_back(0);
some_function(&char_array[0]);
If you know that the function will not modify beyond str.size() you can obtain a pointer in one of different ways:
void f( char* p, size_t s ); // update s characters in p
int main() {
std::string s=...;
f( &s[0], s.size() );
f( &s.front(), s.size() );
}
Note, this is guaranteed in C++11, but not in previous versions of the standard where it allowed for rope implementations (i.e. non-contiguous memory)
If your implementation will not try to increase the length of the string then:
C++11:
std::string data = "This is my string.";
func(&*data.begin());
C++03:
std::string data = "This is my string.";
std::vector<char> arr(data.begin(), data.end());
func(&arr[0]);
Here's a class that will generate a temporary buffer and automatically copy it to the string when it's destroyed.
class StringBuffer
{
public:
StringBuffer(std::string & str) : m_str(str)
{
m_buffer.push_back(0);
}
~StringBuffer()
{
m_str = &m_buffer[0];
}
char * Size(int maxlength)
{
m_buffer.resize(maxlength + 1, 0);
return &m_buffer[0];
}
private:
std::string & m_str;
std::vector<char> m_buffer;
};
And here's how you would use it:
// this is from a crusty old API that can't be changed
void GetString(char * str, int maxlength);
std::string mystring;
GetString(StringBuffer(mystring).Size(MAXLEN), MAXLEN);
If you think you've seen this code before, it's because I copied it from a question I wrote: Guaranteed lifetime of temporary in C++?

I'm finding String::copy rather difficult: copy first five characters of a string

I'm trying to teach myself to program, so I apologize in advance for any shoddy code or bad practices. Basically, I'm trying to copy part of a long string using string::copy, but I'm clearly not doing something right. My goal here is to copy and print the first five characters of the string "bignumber":
#include <iostream>
#include<string>
using namespace std;
int main()
{
const string bignumber = "73167176531330624919225119674426574742355349194934\
96983520312774506326239578318016984801869478851843\
85861560789112949495459501737958331952853208805511\
12540698747158523863050715693290963295227443043557\
6689664895044524452316173185640309871121722383113\
62229893423380308135336276614282806444486645238749\
30358907296290491560440772390713810515859307960866\
70172427121883998797908792274921901699720888093776\
65727333001053367881220235421809751254540594752243\
52584907711670556013604839586446706324415722155397\
53697817977846174064955149290862569321978468622482\
83972241375657056057490261407972968652414535100474\
82166370484403199890008895243450658541227588666881\
16427171479924442928230863465674813919123162824586\
17866458359124566529476545682848912883142607690042\
24219022671055626321111109370544217506941658960408\
07198403850962455444362981230987879927244284909188\
84580156166097919133875499200524063689912560717606\
05886116467109405077541002256983155200055935729725\
71636269561882670428252483600823257530420752963450";
int iter = 0;
size_t window;
char buffer[5];
window = bignumber.copy(buffer,iter,iter+5);
cout << window << endl;
return 0;
}
This is for project Euler problem 8 if you care. Thanks for your help.
I believe you misread the documentation of basic_string::copy. From this page :
size_type copy( Char* s, size_type count, size_type index = 0 ) const;
Copies count characters from the position, starting at index to the given character string s. The resulting string is not NULL terminated.
Your use of the first parameter is correct (buffer being a char array, it will decay to a char pointer upon function argument passing), but your second and third arguments aren't :
size_type count is the number of characters to copy : you are providing 0 while you seem to want 5
size_type index is the starting index for character copying : you are providing 5 while you apparently need 0 (copy count characters from the start of the string). The parameter happens to have a default argument value of 0 : you don't have to provide any value here.
In the end, you could do :
const size_t window = bignumber.copy(buffer, sizeof(buffer));
Notice that I've used sizeof(buffer) rather than the magic value 5 to avoid introducing a bug if the buffer size is changed without reflecting the modification to this call. Also be aware that buffer cannot be simply outputted to std::cout after the call to copy because it is not a null terminated string.
Now, if working with std::string only is an option (and in most cases, it should be), you might as well be using basic_string::substr :
basic_string substr( size_type index = 0, size_type count = npos ) const;
Returns a substring of the current string, starting at the given position index and having length of count characters.
For example :
const std::string substring = bignumber.substr(0, 5);
Contrary to the copy solution, there is no possible size issue here, and the result can be outputted to std::cout without any problem. In other words : it's much safer.
The substr member function would be the more conventional solution to this problem.