I have a C++ std::string str that I've set to some string, and now want to reset so it can be used again. Is there a difference between calling str.clear() vs str = ""?
EDIT. To clarify: I'm reusing str by appending a char array buffer to it: str.append(buf)
There is no effective difference. Depending on the implementation, using clear() may be faster than assigning to a char pointer to zero. Even if this were not the case, though, prefer the method that more clearly expresses your intent. If you want to clear the string, use clear(). If you want to assign an empty string, use = "".
Though I will note, you said, "so I can use it again." Use it again for what? If you are just assigning it to something else, there's no need to clear it beforehand.
Related
Given a string variable set to some value:
string s = "Hello";
Is there any difference (performance, gotchas) between the following methods to clear the contents?:
s = ""
s = std::string()
s.clear()
I got the sample code from this answer to a question about clearing a variable https://stackoverflow.com/a/11617595/1228532
There are some noticeable differences.
clear sets the length of the string to 0, but does not change its capacity.
s="" or s = std::string() creates a whole new (empty) string, assigns its value to the existing string, and throws away the contents of the existing string. Especially if you're using an implementation of std::string that doesn't include the short string optimization, this may well be much slower than clear. To add insult to injury, it also means that if you add more data to the string, it'll end up reallocating the buffer starting from a tiny buffer that it will probably have to reallocate as the string grows.
Bottom line: clear will often be faster, not to mention giving a...clear expression of your real intent.
I have a problem with overlapping char*.
I'm working in a low-memory environment, namely Arduino and I would like to use the least memory possible. I want to be able to prepend a string with another and to do it without any copying of variables which wastes memory.
This is standard C or C++.
char* bigPacket = (char*)malloc(25); //Makes a big string of length 25
char* payload = bigPacket + 2; //This is part of the big string, 2 chars in.
bigPacket[0] = 72; // Letter 'H'
bigPacket[1] = 72; //I'm expecting the final bigPacket to read "HHHello, world"
payload = "Hello, World";
print(bigPacket);
But the problem is that it does not print "HHHello, world" as it should. Instead, it just prints "HH". Is there a proper way to make it be able to overlap these strings to print "HHHello, world"?
You changed where payload points. What you needed to do was leave payload alone and change the data it points to.
strcpy(payload, "Hello World");
Edit: If you really want to avoid copies you'd end up with something like the SGI Rope class. But you'd pay a lot in code complexity.
If you want to do this without either very complicated code or multiple copies of data, destroying the benefit, you need to have the complete string as one literal in your program: "HHHelloWorld". You can then play with pointers and lengths to access various parts of it, but remember there is only one null byte, at the end of the string.
However, I suspect that this is an over-optimization. Arduino programming rarely involves a lot of very long string. It is important to keep the code simple and direct.
You should not mess with pointers for something like that. Instead you should store string literals in flash instead of sram memory. This is usually done with the help of progmem macros. Often the "F" macro is sufficient though. Then you can copy your strings - as needed - and if needed - into a suitable buffer.
Simplest example:
Serial.println(F("this is text from flash memory"));
You just assign the payload pointer to point to the constant string, you do not copy the string to what it currently points to.
In order to copy the string you need to use strcpy or memcpy:
char *bigPacket = malloc(25);
bigPacket[0] = bigpacket[1] = 72;
strcpy( bigpacket+2, "Hello, World");
print( bigPacket );
Note that this is rather unlikely to save memory, since "Hello, world" will exist as a constant string in your code, to save memory it is probably most efficient to call print multiple times.
However, I guess that is not possible in this case.
what is the best way to call a function with the following declaration
string Extract(const char* pattern,const char* input);
i use
string str=Extract("something","input text");
is there a problem with this usage
should i use the following
char pattern[]="something";
char input[]="input";
//or use pointers with new operator and copy then free?
the both works but i like the first one but i want to know the best practice.
A literal string (e.g. "something") works just fine as a const char* argument to a function call.
The first method, i.e. passing them literally in, is usually preferable.
There are occasions though where you don't want your strings hard-coded into the text. In some ways you can say that, a bit like magic numbers, they are magic words / phrases. So you prefer to use constant identifier to store the values and pass those in instead.
This would happen often when:
1. a word has a special meaning, and is passed in many times in the code to have that meaning.
or
2. the word may be cryptic in some way and a constant identifier may be more descriptive
Unless you plain to have duplicates of the same strings, or alter those strings, I'm a fan of the first way (passing the literals directly), it means less dotting about code to find what the parameters actually are, it also means less work in passing parameters.
Seeing as this is tagged for C++, passing the literals directly allows you to easily switch the function parameters to std::string with little effort.
I am having a mental block and I know I should know this but I need a little help.
If I declare a string variable like this:
string word = "Hello";
How do I find the memory address of "Hello"?
Edit: This is what I am trying to do...
Write a function that takes one argument, the address of a string, and prints that string once. (Note: you will need to use a pointer to complete this part.)
However, if a second argument, type int, is provided and is nonzero, the function should print the string a number of times equal to the number of times that function has been called at that point. (Note that the number of times the string is printed is not equal to the value of the second argument; it is equal to the number of times the function has been called so far.)
Use either:
std::string::data() if your data isn't null-terminated c-string like.
or
std::string::c_str() if you want the data and be guaranteed to get the null-termination.
Note that the pointer returned by either of these calls doesn't have to be the underlying data the std::string object is manipulating.
Take the address of the first character is the usual way to do it. &word[0]. However, needing to do this if you're not operating with legacy code is usually a sign that you're doing something wrong.
I guess you want a pointer to a plain old C-string? Then use word.c_str(). Note that this is not guaranteed to point to the internal storage of the string, it's just a (constant) C-string version you can work with.
You can use the c_str() function to get a pointer to the C string (const char *); however note that the pointer is invalidated whenever you modify the string; you have to invoke c_str() again as the old string may have been deallocated.
OK, so, I know this question is old but I feel like the obvious answer here is actually:
std::string your_string{"Hello"};
//Take the address of the beginning
auto start_address = &(*your_string.begin())
//Take the address at the end
auto end_address = &(*your_string.end())
In essence this will accomplish the same thing as using:
auto start_address = your_string.c_str();
auto end_address = your_string.c_str() + strlen(your_string.c_str());
However I would prefer the first approach (taking the address of the dereferenced iterator) because:
a) Guaranteed to work with begin/end compatible containers which might not have the c_str method. So for example, if you decided you wanted a QString (the string QT uses) or AWS::String or std::vector to hold your characters, the c_str() approach wouldn't work but the one above would.
b) Possibly not as costly as c_str()... which generally speaking should be implemented similarly to the call I made in the second line of code to get the address but isn't guaranteed to be implemented that way (E.g. if the string you are using is not null terminated it might require the reallocation and mutation of your whole string in order to add the null terminator... which will suddenly make it thread unsafe and very costly, this is not the case for std::string but might be for other types of strings)
c) It communicates intent better, in the end what you want is an address and the first bunch of code expresses exactly that.
So I'd say this approach is better for:
Clarity, compatibility and efficiency.
Edit:
Note that with either approach, if you change your initial string after taking the address the address will be invalidated (since the string might be rellocated). The compiler will not warn you against this and it could cause some very nasty bugs :/
Declare a pointer to the variable and then view it how you would.
It's a shame I can't figure out such basic thing about c++, but c-style strings are acting as I wouldn't expect. For example, I create it like this:
char* cstr = new char[1];
It's initialized to: Íýýýýý««««««««îţ . Like normal, I can set just first char because others are not really existing (or I thought that they aren't). While working whit c-style strings all this junk is ingored and everything works fine.
Now I mixed std::string whit those c-stlye one and what I get is a mess. Whit this code:
std::string str = "aaa";
str += cstr;
I end up whit: aaaÍýýýýý««««««««îţ , but now those characters actually exist as string.size() returns length including this junk.
I can't find why is this happening, but it must be connected whit string creating, because something like char* cstr = "aaa" results in aaa without any additional junk, but trying to change string initialized this way results in memory access violation. Could someone explain me this behavior please? Thanks!
PS: My JavaScript Failed to load so if someone could format this post properly, I'd be glad!
Answer: Oh god! How could I forget on that... thanks to all for, well, immediate answer. Best one was from minitech so I'll mark this as answer as soon as my java script loads up :/
All C-style strings are null-terminated. So, a string initialized using new char[1] leaves you space for no characters. You can't set the first character to anything but \0, otherwise normal string operations will keep reading into memory until they find a zero. So use new char[2] instead.
When working with C-style strings you need to have a null terminator:
char* cstr = new char[2];
cstr[0] = 'X';
cstr[1] = '\0';
Having said all that, it is really bad code to do the above. Just use std::string unless you have a very good reason not too. It takes care of the memory allocations and deallocations for you.
C-style strings require a NUL ('\0') terminator; they don't have a length associated with them like C++ strings do. So your single-character string must be new char[2]; it will not be initialized; and you will need to make sure it's terminated with \0.
When you use new char[1], you request space for an array of characters. There is no request that said characters are initialized. Thus, the "junk" that you see is uninitialized memory. Before treating the array as a C-style string, you should do this:
cstr[0] = '\0';
c-style strings are NULL delimited. So, to ignore any junk in memory you need to place NULL byte('\0') in the string body. Otherwise, system library function will look at all bytes starting with your string start until they meet NULL byte in the memory (which will be at some random position).
This also mean that to have c-style string of one character you actually need to allocate 2 bytes: one for a meaningful character and second for '\0'.