The right way to copy C-lines

Is there an easy way to copy C lines?

I have const char *stringA , and I want char *stringB to accept a value (note that stringB not const ). I tried stringB=(char*) stringA , but stringB still points to the same place in memory, so when stringA later changes, stringB does too.

I also tried strcpy(stringB,stringA) , but it seems that if stringB not initialized to a large enough array, there is segfault. I'm not a super experience with C-strings, though, am I missing something obvious? If I just initialize stringB as char *stringB[23] because I know that I will never have a string longer than 22 characters (and given the null terminator), is this the right way? If stringB checked for equality with other C-strings, will there be extra space on anything?

(and just using strings here is not a solution, since I need minimal overhead and easy access to individual characters)

+7
source share
4 answers

You can use strdup() to return a copy of the C-string, for example:

 #include <string.h> const char *stringA = "foo"; char *stringB = NULL; stringB = strdup(stringA); /* ... */ free(stringB); 

You can also use strcpy() , but first you need to allocate a place, which is not difficult to do, but can lead to an overflow error if it is not done correctly:

 #include <string.h> const char *stringA = "foo"; char *stringB = NULL; /* you must add one to cover the byte needed for the terminating null character */ stringB = (char *) malloc( strlen(stringA) + 1 ); strcpy( stringB, stringA ); /* ... */ free(stringB); 

If you cannot use strdup() , I recommend using strncpy() instead of strcpy() . The strncpy() function copies up to - and only up to - n bytes, which helps to avoid overflow errors. However, if strlen(stringA) + 1 > n , you will need to end stringB yourself. But, as a rule, you will know what sizes you need for things:

 #include <string.h> const char *stringA = "foo"; char *stringB = NULL; /* you must add one to cover the byte needed for the terminating null character */ stringB = (char *) malloc( strlen(stringA) + 1 ); strncpy( stringB, stringA, strlen(stringA) + 1 ); /* ... */ free(stringB); 

I think strdup() cleaner, myself, so I try to use it when it works exclusively with strings. I don’t know if there are serious disadvantages for the POSIX / non-POSIX approach, in terms of performance, but I am not an expert in C or C ++.

Note that I passed the result of malloc() to char * . This is because your question is marked as a c++ question. In C ++, you need to pass the result from malloc() . In C, however, you did not select this.

EDIT

There you go, there is one complication: strdup() not in C or C ++. So use strcpy() or strncp() with a predefined array or malloc -ed pointer. It's a good habit to use strncp() instead of strcpy() , wherever you use this function. This will help reduce the likelihood of errors.

+10
source

If I just initialize stringB as char * stringB [23] because I know that I will never have a string longer than 22 characters (and given the null terminator), is this the right way?

Nearly. In C, if you know for sure that the string will never be too long:

 char stringB[MAX+1]; assert(strlen(stringA) <= MAX)); strcpy(stringB, stringA); 

or, if there is a possibility that the line may be too long:

 char stringB[MAX+1]; strncpy(stringB, stringA, MAX+1); if (stringB[MAX] != '\0') { // ERROR: stringA was too long. stringB[MAX] = '\0'; // if you want to use the truncated string } 

In C ++, you should use std::string if you have not proven that the overhead is excessive. Many implementations have "short row optimization", which avoids dynamic allocation for short lines; in this case there will be little or no overhead to use a C-style array. Access to individual characters is as convenient as for a C-style array; in both cases s[i] gives the character at position i as an lvalue. Copy becomes stringB = stringA; no danger of undefined behavior.

If you really find that std::string unusable, consider std::array<char,MAX+1> : a copy class containing an array of fixed size.

If stringB is checked for equality with other C-strings, will there be extra space on anything?

If you use strcmp , then it will stop at the end of the shortest and will not be affected by the extra space.

+3
source

If you want to do this in pure C style than:

 char* new_string = strdup(old_string); free(new_string); 

If you want to do this in a (view) C ++ style:

 char* new_string = new char[strlen(old_string) + 1]; strcpy(new_string,old_string); delete[] new_string; 
+2
source

Perhaps you are looking for strncpy , which allows you to copy the first n characters from a string. Just remember to add a null terminator at position n of the copied line.

0
source

All Articles