C++ copying char to a char array (Debug assertion failed) says string is not null terminated - c++

Just trying to assign chars to the char array and it says string in not null terminated?
I want to be able to change the teams around in the array like a scoreboard.
#include <string.h>
#include <iostream>
int main(int argc, char* argv[])
{
char Team1[7] = "Grubs";
char Team2[7] = "Giants";
char Team3[7] = "Bulls";
char Team4[7] = "Snakes";
char Team5[7] = "Echos";
char TeamList[5][7];
strcpy_s(TeamList[0], Team1);
strcat_s(TeamList[1], Team2);
strcat_s(TeamList[2], Team3);
strcat_s(TeamList[3], Team4);
strcat_s(TeamList[4], Team5);
TeamList[5][7]= '\0';
system("pause");
return 0;
}

strcat() (which is a "less-safe" version of strcat_s()) requires both strings to be null-terminated. That's because strcat() appends its second parameter (source) where first parameter (dest) ends. It replaces null-terminator of dest with first character of source, appends rest of source and then
a null-character is included at the end of the new string formed by
the concatenation of both
I would simply change
strcpy_s(TeamList[0], Team1);
strcat_s(TeamList[1], Team2);
strcat_s(TeamList[2], Team3);
strcat_s(TeamList[3], Team4);
strcat_s(TeamList[4], Team5);
to
strcpy_s(TeamList[0], Team1);
strcpy_s(TeamList[1], Team2);
strcpy_s(TeamList[2], Team3);
strcpy_s(TeamList[3], Team4);
strcpy_s(TeamList[4], Team5);
strcpy_s() does not have any requirements regarding contents of destination - only its capacity matters.
If you want to stick with strcat_s(), do this:
char TeamList[5][7];
memset(TeamList, 0, sizeof(char) * 5 * 7);
Then, this line:
TeamList[5][7]= '\0';
is not required, It is incorrect anyway, because for N-element array valid indexes are [0; N-1].
EDIT
Since in your case swapping comes into play, I would suggest you totally different approach.
First of all:
#include <string>
Then, initialize teams this way:
std::string TeamList[] =
{
"Grubs",
"Giants",
"Bulls",
"Snakes",
"Echos"
};
Now, TeamList is an array containing 5 elements and each of these elements is an object of type std::string, containing name of a particular team.
Now, if you want to swap, let's say, teams 1 and 3:
std::swap(TeamList[1], TeamList[3]);
std::swap() is a standard C++ function extensively used in standard library implementation. It is overloaded for many standard types, including std::string. This solution has one, critical benefit: if string's content is held on the heap, swapping two strings is as simple as swapping pointers (and some length/capacity variables).
Oh, and one more thing: if you are not familiar with std::string and you would need to get pointer to a buffer containing string's data, you can do it this way:
const char* team_1_raw_name = TeamList[0].c_str();
See this page for more info about std::string

strcat requires that there already be a null-terminated string in the destination to concatenate the source string onto; you're calling it with uninitialised values in the destination.
It looks like you want strcpy in every case, not just the first.
Also, remove the bogus TeamList[5][7]= '\0';. Even if you fix it to write inside the array bounds, each string has already been terminated by strcpy so there's no need to try to do that yourself.
Then stop messing around with low-level arrays and pointers. std::vector<std::string> would be much friendlier.

Related

Null character behavior c++

#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello";
cout << s[5] << endl;
return 0;
}
In the above code, if I print s[5], it correctly prints a NULL character. But if I change the code to this:
#include <iostream>
#include <string>
using namespace std;
int main() {
char[] s = {'a','b','c','d','e'};
cout << s[5] << endl;
return 0;
}
It doesn't print a NULL character but something random. If I store the string as a string or as a char*, then the behavior is in tune with what I expect.
But if I explicitly declare the character array, how does the compiler know when the array ends? Does the size of the array gets stored at compile time?
String literals and std::strings store null terminated strings.
But an array of 5 char declared like:
char s[] = {'a','b','c','d','e'};
contains only 5 char, no null terminator.
But the compiler does know the size of s. It is part of the type of s. It has no convenient .size() function like std::string, std::vector or std::array does but you can get it by doing:
sizeof(s) / sizeof(s[0])
Or more safely in C++11:
std::extent<decltype(s)>::value
Or in C++17:
std::size(s)
(demo)
Arrays have a habit of decaying to pointers though and then there is no way of getting the size, you have to keep track of it yourself. Which is why std::string, std::vector or std::array is preferred in C++.
Strings are null-terminated, and const char* are treated the same way as Strings are. When you declare a array with a size it's put on the stack and the compiler doesn't know the size. Array out-of-bounds exceptions aren't determined during compile time.
the string class in c++ has the constructor which by itself adds the null character to the string passed to it if not explicitly added. But while using char it only stores the content passed to it (i.e) if you want to have a null character you have to explicitly add in the declaration or the definition of that char.
When you do char[] s = {'a','b','c','d','e'};, it will store characters mentioned and nothing else.
if I explicitly declare the character array, how does the compiler know when the array ends?
size is determined by number of characters provided by you.
Does the size of the array gets stored at compile time?
no, the size of array is determined by memory blocks allocated to it. (It is not stored separately in memory, if that's what you meant)
And when you use this string s = "hello";, strings are always null terminated.
Your code is char s[] = {'a','b','c','d','e'};, so it will not put the \0 at the end of your char array. It will put the \0 with three methods below:
1. char s[] = {'a','b','c','d','e', '\0'};
2. char s[] = "abcde";
3. string s = "abcde";
So if you use any of the three above, you will get a NULL character.
"how does the compiler know when the array ends ?": the compiler knows how many elements the array has, from its declaration, and this information is available through the sizeof operator.
Anyway C-style arrays have virtually no size, as they are implicitly turned to pointers when passed as arguments, and their length is dropped (IMO a major flaw in the design of the C language). Overflow avoidance is your responsibility.
For this reason, you mustn't use a cout << statement if your string isn't null-terminated.

Store value in Pointers as an Array - C++

I am trying to make a function like strcpy in C++. I cannot use built-in string.h functions because of restriction by our instructor. I have made the following function:
int strlen (char* string)
{
int len = 0;
while (string [len] != (char)0) len ++;
return len;
}
char* strcpy (char* *string1, char* string2)
{
for (int i = 0; i<strlen (string2); i++) *string1[i] = string2[i];
return *string1;
}
main()
{
char* i = "Farid";
strcpy (&i, "ABC ");
cout<<i;
}
But I am unable to set *string1 [i] value. When I try to do so an error appears on screen 'Program has encountered a problem and need to close'.
What should I do to resolve this problem?
Your strcpy function is wrong. When you write *string1[i] you are actually modifying the first character of the i-th element of an imaginary array of strings. That memory location does not exist and your program segfaults.
Do this instead:
char* strcpy (char* string1, char* string2)
{
for (int i = 0; i<strlen (string2); i++) string1[i] = string2[i];
return string1;
}
If you pass a char* the characters are already modifiable. Note It is responsibility of the caller to allocate the memory to hold the copy. And the declaration:
char* i = "Farid";
is not a valid allocation, because the i pointer will likely point to read-only memory. Do instead:
char i[100] = "Farid";
Now i holds 100 chars of local memory, plenty of room for your copy:
strcpy(i, "ABC ");
If you wanted this function to allocate memory, then you should create another one, say strdup():
char* strdup (char* string)
{
size_t len = strlen(string);
char *n = malloc(len);
if (!n)
return 0;
strcpy(n, string);
return n;
}
Now, with this function the caller has the responsibility to free the memory:
char *i = strdup("ABC ");
//use i
free(i);
Because this error in the declaration of strcpy: "char* *string1"
I don't think you meant string1 to be a pointer to a pointer to char.
Removing one of the * should word
The code has several issues:
You can't assign a string literal to char* because the string literal has type char const[N] (for a suitable value of N) which converts to char const* but not to char*. In C++03 it was possible to convert to char* for backward compatibility but this rule is now gone. That is, your i needs to be declared char const*. As implemented above, your code tries to write read-only memory which will have undesirable effects.
The declaration of std::strcpy() takes a char* and a char const*: for the first pointer you need to provide sufficient space to hold a string of the second argument. Since this is error-prone it is a bad idea to use strcpy() in the first place! Instead, you want to replicate std::strncpy() which takes as third argument the length of the first buffer (actually, I'm never sure if std::strncpy() guarantees zero termination or not; you definitely also want to guarantee zero termination).
It is a bad idea to use strlen() in the loop condition as the function needs to be evaluated for each iteration of the loop, effectively changing the complexity of strlen() from linear (O(N)) to quadratic (O(N2)). Quadratic complexity is very bad. Copying a string of 1000 characters takes 1000000 operations. If you want to try out the effect, copy a string with 1000000 characters using a linear and a quadratic algorithm.
Your strcpy() doesn't add a null-terminator.
In C++ (and in C since ~1990) the implicit int rule doesn't apply. That is, you really need to write int in front of main().
OK, a couple of things:
you are missing the return type for the main function
declaration. Not really allowed under the standard. Some compilers will still allow it, but others will fail on the compile.
the way you have your for loop structured in
strcpy you are calling your strlen function each time through
the loop, and it is having to re-count the characters in the source
string. Not a big deal with a string like "ABC " but as strings get
longer.... Better to save the value of the result into a variable and use that in the for loop
Because of the way that you are declaring i in
`main' you are pointing to read-only storage, and will be causing an
access violation
Look at the other answers here for how to rebuild your code.
Pointer use in C and C++ is a perennial issue. I'd like to suggest the following tutorial from Paul DiLorenzo, "Learning C++ Pointers for REAL dummies.".
(This is not to imply that you are a "dummy," it's just a reference to the ",insert subject here> for Dummies" lines of books. I would not be surprised that the insertion of "REAL" is to forestall lawsuits over trademarked titles)
It is an excellent tutorial.
Hope it helps.

list of char* to vector of strings

it looks like when I cout *cp, it only outputs the first letter of the string and after I put them in vector, my output is blank. what am I doing wrong?
//write a program to assign the elements from a list of char* pointers to c-style character strings to a vector of strings
#include <iostream>
#include <cstring>
#include <vector>
#include <list>
#include <string>
using namespace std;
int main ()
{
list<const char*> clist;
cout<<"please enter a string"<<endl;
for(string s; getline(cin,s); )
{
const char* cp=s.c_str();
clist.push_back(cp);
cout<<*cp;
}
cout<<*clist.begin();
vector<string> svec;
svec.assign(clist.begin(),clist.end());
for(vector<string>::iterator iter=svec.begin(); iter!=svec.end(); ++iter)
cout<<*iter<<endl;
return 0;
}
This will print the whole string:
cout << cp; // You're providing cout a const char *
This will only print one character:
cout << *cp; // You're providing cout a char
As to what's wrong with your vector, you're only storing pointers to strings, not strings themselves. The memory for the string has gone out of scope. As others have said, use std::string instead of raw const char *.
cout *cp, it only outputs the first letter of the string
Well, *cp is a character (the one found at the location to which the pointer cp pointers). So, yea, it will.
after I put them in vector, my output is blank
It's unfortunate that your program did not crash outright, as the pointers in your list become dangling pointers almost as soon as you store them.
Store std::strings from the very start.
cout<<*cp;
will output a single character because it points to a const char *
You need to do:
cout<<cp;
This will output the entire string pointed by cp.
You have a couple big problems here. First of all,
const char* cp=s.c_str();
returns a pointer to an internal member string within std::string. When you change the string, the value referenced by the returned pointer to c_str may be changed (may even be in a new location). So, the values in your list are not valid. Make sure you don't use c_str and try to make use of the result after the original string has been changed (unless you copy the c_str result into a new char array.
Also,
cout<<*cp;
only prints our your first element. Get rid of the * to print the whole c-string at that list element.
it looks like when I cout *cp, it only outputs the first letter of the string
*cp is the first letter of the string. cout << cp will print the whole string.
after I put them in vector, my output is blank.
Your list contains pointers to the contents of s, which is only valid within the body of the loop. Once the string goes out of scope, the pointer is "dangling" - pointing to deallocated memory. Trying to use the pointer will give undefined behaviour.
You'll need to keep hold of a copy of the string itself, either by making clist a list<string>, or by keeping the strings in another container, and storing pointers to the data in that container in clist.
Alternatively, you could use string literals rather than reading strings from cin. String literals live as long as the program, so there are no issues with dangling pointers.
(That's assuming that the comment in the first line of your code is a specification that you can't change. Otherwise, I'd get rid of clist completely, and push each string onto the back of svec as I read it. It's rarely a good idea to use pointers for anything.)

Is there a safe version of strlen?

std::strlen doesn't handle c strings that are not \0 terminated. Is there a safe version of it?
PS I know that in c++ std::string should be used instead of c strings, but in this case my string is stored in a shared memory.
EDIT
Ok, I need to add some explanation.
My application is getting a string from a shared memory (which is of some length), therefore it could be represented as an array of characters. If there is a bug in the library writing this string, then the string would not be zero terminated, and the strlen could fail.
You've added that the string is in shared memory. That's guaranteed readable, and of fixed size. You can therefore use size_t MaxPossibleSize = startOfSharedMemory + sizeOfSharedMemory - input; strnlen(input, MaxPossibleSize) (mind the extra n in strnlen).
This will return MaxPossibleSize if there's no \0 in the shared memory following input, or the string length if there is. (The maximal possible string length is of course MaxPossibleSize-1, in case the last byte of shared memory is the first \0)
C strings that are not null-terminated are not C strings, they are simply arrays of characters, and there is no way of finding their length.
If you define a c-string as
char* cowSays = "moo";
then you autmagically get the '\0' at the end and strlen would return 3. If you define it like:
char iDoThis[1024] = {0};
you get an empty buffer (and array of characters, all of which are null characters). You can then fill it with what you like as long as you don't over-run the buffer length. At the start strlen would return 0, and once you have written something you would also get the correct number from strlen.
You could also do this:
char uhoh[100];
int len = strlen(uhoh);
but that would be bad, because you have no idea what is in that array. It could hit a null character you might not. The point is that the null character is the defined standard manner to declare that the string is finished.
Not having a null character means by definition that the string is not finished. Changing that will break the paradigm of how the string works. What you want to do is make up your own rules. C++ will let you do that, but you will have to write a lot of code yourself.
EDIT
From your newly added info, what you want to do is loop over the array and check for the null character by hand. You should also do some validation if you are expecting ASCII characters only (especially if you are expecting alpha-numeric characters). This assumes that you know the maximum size.
If you do not need to validate the content of the string then you could use one of the strnlen family of functions:
http://msdn.microsoft.com/en-us/library/z50ty2zh%28v=vs.80%29.aspx
http://linux.about.com/library/cmd/blcmdl3_strnlen.htm
size_t safe_strlen(const char *str, size_t max_len)
{
const char * end = (const char *)memchr(str, '\0', max_len);
if (end == NULL)
return max_len;
else
return end - str;
}
Yes, since C11:
size_t strnlen_s( const char *str, size_t strsz );
Located in <string.h>
Get a better library, or verify the one you have - if you can't trust you library to do what it says it will, then how the h%^&l do you expect your program to?
Thats said, Assuming you know the length of the buiffer the string resides, what about
buffer[-1+sizeof(buffer)]=0 ;
x = strlen(buffer) ;
make buffer bigger than needed and you can then test the lib.
assert(x<-1+sizeof(buffer));
C11 includes "safe" functions such as strnlen_s. strnlen_s takes an extra maximum length argument (a size_t). This argument is returned if a null character isn't found after checking that many characters. It also returns the second argument if a null pointer is provided.
size_t strnlen_s(const char *, size_t);
While part of C11, it is recommended that you check that your compiler supports these bounds-checking "safe" functions via its definition of __STDC_LIB_EXT1__. Furthermore, a user must also set another macro, __STDC_WANT_LIB_EXT1__, to 1, before including string.h, if they intend to use such functions. See here for some Stack Overflow commentary on the origins of these functions, and here for C++ documentation.
GCC and Clang also support the POSIX function strnlen, and provide it within string.h. Microsoft too provide strnlen which can also be found within string.h.
You will need to encode your string. For example:
struct string
{
size_t len;
char *data;
} __attribute__(packed);
You can then accept any array of characters if you know the first sizeof(size_t) bytes of the shared memory location is the size of the char array. It gets tricky when you want to chain arrays this way.
It's better to trust your other end to terminate it's strings or roll your own strlen that does not go outside the bounderies of the shared memory segment (providing you know at least the size of that segment).
If you need to get the size of shared memory, try to use
// get memory size
struct shmid_ds shm_info;
size_t shm_size;
int shm_rc;
if((shm_rc = shmctl(shmid, IPC_STAT, &shm_info)) < 0)
exit(101);
shm_size = shm_info.shm_segsz;
Instead of using strlen you can use shm_size - 1 if you are sure that it is null terminated. Otherwise you can null terminate it by data[shm_size - 1] = '\0'; then use strlen(data);
a simple solution:
buff[BUFF_SIZE -1] = '\0'
ofc this will not tell you if the string originally was exactly BUFF_SIZE-1 long or it was just not terminated... so you need xtra logic for that.
How about this portable nugget:
int safeStrlen(char *buf, int max)
{
int i;
for(i=0;buf[i] && i<max; i++){};
return i;
}
As Neil Butterworth already said in his answer above: C-Strings which are not terminated by a \0 character, are no C-Strings!
The only chance you do have is to write an immutable Adaptor or something which creates a valid copy of the C-String with a \0 terminating character. Of course, if the input is wrong and there is an C-String defined like:
char cstring[3] = {'1','2','3'};
will indeed result in unexpected behavior, because there can be something like 123#4x\0 in the memory now. So the result of of strlen() for example is now 6 and not 3 as expected.
The following approach shows how to create a safe C-String in any case:
char *createSafeCString(char cStringToCheck[]) {
//Cast size_t to integer
int size = static_cast<int>(strlen(cStringToCheck)) ;
//Initialize new array out of the stack of the method
char *pszCString = new char[size + 1];
//Copy data from one char array to the new
strncpy(pszCString, cStringToCheck, size);
//set last character to the \0 termination character
pszCString[size] = '\0';
return pszCString;
}
This ensures that if you manipulate the C-String to not write on the memory of something else.
But this is not what you wanted. I know, but there is no other way to achieve the length of a char array without termination. This isn't even an approach. It just ensures that even if the User (or Dev) is inserting ***** to work fine.

Difference between string and char[] types in C++

For C, we use char[] to represent strings.
For C++, I see examples using both std::string and char arrays.
#include <iostream>
#include <string>
using namespace std;
int main () {
string name;
cout << "What's your name? ";
getline(cin, name);
cout << "Hello " << name << ".\n";
return 0;
}
#include <iostream>
using namespace std;
int main () {
char name[256];
cout << "What's your name? ";
cin.getline(name, 256);
cout << "Hello " << name << ".\n";
return 0;
}
(Both examples adapted from http://www.cplusplus.com.)
What is the difference between these two types in C++? (In terms of performance, API integration, pros/cons, ...)
A char array is just that - an array of characters:
If allocated on the stack (like in your example), it will always occupy eg. 256 bytes no matter how long the text it contains is
If allocated on the heap (using malloc() or new char[]) you're responsible for releasing the memory afterwards and you will always have the overhead of a heap allocation.
If you copy a text of more than 256 chars into the array, it might crash, produce ugly assertion messages or cause unexplainable (mis-)behavior somewhere else in your program.
To determine the text's length, the array has to be scanned, character by character, for a \0 character.
A string is a class that contains a char array, but automatically manages it for you. Most string implementations have a built-in array of 16 characters (so short strings don't fragment the heap) and use the heap for longer strings.
You can access a string's char array like this:
std::string myString = "Hello World";
const char *myStringChars = myString.c_str();
C++ strings can contain embedded \0 characters, know their length without counting, are faster than heap-allocated char arrays for short texts and protect you from buffer overruns. Plus they're more readable and easier to use.
However, C++ strings are not (very) suitable for usage across DLL boundaries, because this would require any user of such a DLL function to make sure he's using the exact same compiler and C++ runtime implementation, lest he risk his string class behaving differently.
Normally, a string class would also release its heap memory on the calling heap, so it will only be able to free memory again if you're using a shared (.dll or .so) version of the runtime.
In short: use C++ strings in all your internal functions and methods. If you ever write a .dll or .so, use C strings in your public (dll/so-exposed) functions.
Arkaitz is correct that string is a managed type. What this means for you is that you never have to worry about how long the string is, nor do you have to worry about freeing or reallocating the memory of the string.
On the other hand, the char[] notation in the case above has restricted the character buffer to exactly 256 characters. If you tried to write more than 256 characters into that buffer, at best you will overwrite other memory that your program "owns". At worst, you will try to overwrite memory that you do not own, and your OS will kill your program on the spot.
Bottom line? Strings are a lot more programmer friendly, char[]s are a lot more efficient for the computer.
Well, string type is a completely managed class for character strings, while char[] is still what it was in C, a byte array representing a character string for you.
In terms of API and standard library everything is implemented in terms of strings and not char[], but there are still lots of functions from the libc that receive char[] so you may need to use it for those, apart from that I would always use std::string.
In terms of efficiency of course a raw buffer of unmanaged memory will almost always be faster for lots of things, but take in account comparing strings for example, std::string has always the size to check it first, while with char[] you need to compare character by character.
I personally do not see any reason why one would like to use char* or char[] except for compatibility with old code. std::string's no slower than using a c-string, except that it will handle re-allocation for you. You can set it's size when you create it, and thus avoid re-allocation if you want. It's indexing operator ([]) provides constant time access (and is in every sense of the word the exact same thing as using a c-string indexer). Using the at method gives you bounds checked safety as well, something you don't get with c-strings, unless you write it. Your compiler will most often optimize out the indexer use in release mode. It is easy to mess around with c-strings; things such as delete vs delete[], exception safety, even how to reallocate a c-string.
And when you have to deal with advanced concepts like having COW strings, and non-COW for MT etc, you will need std::string.
If you are worried about copies, as long as you use references, and const references wherever you can, you will not have any overhead due to copies, and it's the same thing as you would be doing with the c-string.
One of the difference is Null termination (\0).
In C and C++, char* or char[] will take a pointer to a single char as a parameter and will track along the memory until a 0 memory value is reached (often called the null terminator).
C++ strings can contain embedded \0 characters, know their length without counting.
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
void NullTerminatedString(string str){
int NUll_term = 3;
str[NUll_term] = '\0'; // specific character is kept as NULL in string
cout << str << endl <<endl <<endl;
}
void NullTerminatedChar(char *str){
int NUll_term = 3;
str[NUll_term] = 0; // from specific, all the character are removed
cout << str << endl;
}
int main(){
string str = "Feels Happy";
printf("string = %s\n", str.c_str());
printf("strlen = %d\n", strlen(str.c_str()));
printf("size = %d\n", str.size());
printf("sizeof = %d\n", sizeof(str)); // sizeof std::string class and compiler dependent
NullTerminatedString(str);
char str1[12] = "Feels Happy";
printf("char[] = %s\n", str1);
printf("strlen = %d\n", strlen(str1));
printf("sizeof = %d\n", sizeof(str1)); // sizeof char array
NullTerminatedChar(str1);
return 0;
}
Output:
strlen = 11
size = 11
sizeof = 32
Fee s Happy
strlen = 11
sizeof = 12
Fee
Think of (char *) as string.begin(). The essential difference is that (char *) is an iterator and std::string is a container. If you stick to basic strings a (char *) will give you what std::string::iterator does. You could use (char *) when you want the benefit of an iterator and also compatibility with C, but that's the exception and not the rule. As always, be careful of iterator invalidation. When people say (char *) isn't safe this is what they mean. It's as safe as any other C++ iterator.
Strings have helper functions and manage char arrays automatically. You can concatenate strings, for a char array you would need to copy it to a new array, strings can change their length at runtime. A char array is harder to manage than a string and certain functions may only accept a string as input, requiring you to convert the array to a string. It's better to use strings, they were made so that you don't have to use arrays. If arrays were objectively better we wouldn't have strings.