So I know that you should declare char arrays to be one element bigger than the word you want to put there because of the \0 that has to be at the end, but what about char arrays that I don't want to use as words?
I'm currently writing a program in which i store an array of keyboard letters that have some function assigned to them. Should I still end this array with \0?
That is probably not necessary.
A null terminator is not a requirement for arrays of char; it is a requirement for "C-strings", things that you intend to use as unitary blobs of data, particularly if you intend to pass them to C API functions. It's the conventional way that the "length" of the string is determined.
But if you just want a collection of chars to use independently then knock yourself out.
We cannot see your code, but it sounds to me like you don't want or need it in this case.
The array should have, at least, the same number of elements as the data you will put there. So, if:
you don't need the '\0'
you won't place it there
you won't use routines that will depend on an '\0' to tell you the array size
... you are good with not using the trailing '\0'
If you're using C++, you should probably just use std::string or std::vector<char> or even std::array<char> and not worry about terminators.
It depends on usage. If you want to use it not as just byte array, but as c-string with probably usage of some standard string algorithms (strcmp and so on), or output to the stream - your array should ends with \0.
It depends on what you are trying to do, if you are trying to define a C-style string then, you need the terminator since the C-library won't be able to calculate the size of the string and other things if you don't...
In C++, though, the size of the string is already stored inside the std::string class along with the dynamic array of chars...
But if you just need a free container for storing characters where you don't need it to do C-string-like things... You are free to do:
char hello[128]; // 128 elements, do anything with them...
Without the terminator...
In your case, you are storing values, not creating a string, and you won't probably treat it as a string either, so doing it without the null-terminator, suffices...
\0 will certainly make it easier when wanting to use functions like strlen, strcmp, strcatand the like, but is not required.
An aside - We have an entire enterprise code base built upon strings (char arrays) with no null terminators in the database. Works just fine.
Related
I am reading strings from a structure in a file where each string has a fixed length, with '\0' padding. They are not zero-terminated if the stored string needs the whole length.
I'm currently constructing std::strings out of those like this:
// char MyString[1000];
std::string stdmystring(MyString, ARRAYSIZE(MyString));
However, this copies the padding, too. I could trim the string now, but is there an elegant and quick way to prevent the copying in the first place?
Speed is more important than space, because this runs in a loop.
Simple solutions are:
Just calculate the correct length first
either use strnlen as Dieter suggested
or std::find(MyString,MyString+ARRAYSIZE(MyString),'\0') which IME isn't any slower
note that if your string fits in cache, that will likely dominate the extra loop cost
reserve the max string size (you did say space was less important), and write a loop appending characters until you exhaust the width or hit a nul (like copy_until)
actually create a max-size string initialized with nuls, strncpy into it, and optionally erase unused nuls if you want the size to be correct
The second option uses only a single loop, while the third notionally uses two (it in the string ctor, and then in the copy). However, the push_back of each character seems more expensive than the simple character assignment, so I wouldn't be surprised if #3 were faster in reality. Profile and see!
Well If size is not a problem one potential way to do it is to create an empty std::string then use reserve() to pre-allocate the space potentially needed and then add each char until you come across '\0'.
std::string stdmystring;
stdmystring.reserve(MyString_MAX_SIZE) ;
for(size_t i=0;i<MyString_MAX_SIZE && MyString[i]!='\0';++i);
stdmystring+=MyString[i];
reserve() garanties you one memory allocation since you know the max_size and the string will never get larger than that.
The calls to += operator function will probably be inlined but it still has to check that the string has the needed capacity which is wasteful in your case. Infact this could be the same or worse than simply using strlen to find the exact length of the string first so you have to test it.
I think the most straightforward way is to overallocate your internal MyString array by one byte, always null terminate that final byte, and use the C-string constructor of std::string. (Keep in mind that most likely your process will be I/O bound on the file so whatever algorithm the C-string constructor uses should be fine).
I am new to C++ and programming and I would like to know if there is a way to get the length of a pointer.
Let's say Myheader is a struct with different types of data inside.
My code goes like this:
char *pStartBuffer;
memcpy(pStartBuffer, &MyHeader, MyHeader.u32Size);
So I want to know the length of the buffer so that I can copy the data to a file using QT write function.
file.write(pStartBuffer, length(pStartBuffer));
How can I do this?
Pointers don't know its allocated size.
You may use std::vector which keep track of size for you:
std::vector<char> pStartBuffer(MyHeader.u32Size);
memcpy(pStartBuffer, &MyHeader, MyHeader.u32Size);
And latter:
file.write(pStartBuffer.data(), pStartBuffer.size());
There is no way to find the length of a buffer given nothing but a pointer. If you are certain that it's a string you can use one of the string length functions, or you can keep track of the length of the buffer yourself.
Pointer doesn't have a "length". What you need is the length of the array which the pointer points to.
No, you cannot extract that information from the pointer.
If the array contains a valid, null-terminated character string, then you can get the length of that string by iterating it until you find a null character which is what strlen does.
If not, then what you normally do is you store the length in a variable when you allocate the array. Which is one of the things that std::vector or std::string will do for you, whichever is more appropriate for your use.
Good day to everyone,
there's some kind of big deal that I cannot figure out.
I create a multidimensional array of pointers:
char *listA[5000][2];
In particular condition, I want that specific strings are saved inside this array.
These are a normal string, in a simple variable, and another contained inside an array of strings.
listA[j][0]=strMix;
listA[j][1]=ingredients[i];
j++;
j, of course, is the row, that is increased for every adding.
The result must be an array that, for every row, contains two columns, one whit an ingredient, and another with the relative strMix.
The problem is that when I try to read this multidimensional array:
printf( "%s", listA[0][1]); // the ingredient
is always correct, but:
printf( "%s", listA[0][0]); // the strMix code
is always incorrect; precisely it reads the last strMix read, for every row.
I tried to change the order of the columns, and with my big surprise, the problem is always for the strMix, and never for the ingredients[i] string.
strMix column is correct only if I write it inside listA, and immediately read it. Of course, I'd say.
For example:
printf("Current: %s vs Previously: %s",lista[j][0], lista[j-1][0]);
they are the same, for every j, equal to the last strMix read.
If you have any ideas, something about memory or multidimensional array of pointers that I simply are missing, I'd appreciate your advises.
Thank you for the time, in every case.
fdt.
You're not saving strings in this array -- you're saving pointers.
This statement copies an address, not a string:
listA[j][0]=strMix;
If you want to copy the string, you can either:
Use an char array that stores the strings. For some strings, this may use too much memory. For others, it may offer not enough.
Use a char* array that stores addresses to the strings, and allocate separate memory for each referenced string.
Regardless, to copy the strings, prefer strncpy() to the unsafe strcpy().
Is it C or C++? Maybe instead of using the assignment:
listA[j][0]=strMix;
you should use strcpy function?
strcpy (listA[j][0], strMix);
The constraint is that it should be contiguous memory. The reason is, this is being sent to another language legacy code, which expects it in that format as a 2D array.
so esentially i want to send
char *temp[20] = { "abc", "def"};
etc where abc, def are part of a space thats 20 byte length.
Now, i would like to dynamically create this array and add as many 20 character or less strings to it.
And then send that as an array into the different layer.
Whats the best way to do this.
std::vector< std::array<char, 20> > will do the trick
vector allows dynamically allocating more memory for more strings, the type std::array<char,20> ensures that each member of the vector is indeed 20 characters (make sure to verify boundaries on copy etc, as with any array).
This is for newer C++ standard, IIRC, so older compilers might not support it. Use boost.array instead, then.
What is the difference between the string and character array?
How can each element of the string be accessed in C++?
string manages its own memory; this is not so with an array of char except as a local variable.
In both cases you can access individual elements using [] (but in the case of string this is actually operator[]).
string has a lot of built-in functions that you don't easily get in a C++-friendly way with C-Strings.
In C, they are the same, a string is a char array and you have a lot of standard methods to handle them like sprintf, strcat, strcpy, strdup, strchr, strstr...
In C++, you can also use the STL string class that will provide a object oriented string that you can manipulate in an easier way. The advantage is that the code is easier to read and you don't need to allocate/deallocate memory for the strings by yourself.