You can't directly do array2 = array1, because in this case you manipulate the addresses of the arrays (char *) and not of their inner values (char).
What you, conceptually, want is to do is iterate through all the chars of your source (array1) and copy them to the destination (array2). There are several ways to do this. For example you could write a simple for loop, or use memcpy.
That being said, the recommended way for strings is to use strncpy. It prevents common errors resulting in, for example, buffer overflows (which is especially dangerous if array1 is filled from user input: keyboard, network, etc). Like so:
Copy// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);
As @Prof. Falken mentioned in a comment, strncpy can be evil. Make sure your target buffer is big enough to contain the source buffer (including the \0 at the end of the string).
You can't directly do array2 = array1, because in this case you manipulate the addresses of the arrays (char *) and not of their inner values (char).
What you, conceptually, want is to do is iterate through all the chars of your source (array1) and copy them to the destination (array2). There are several ways to do this. For example you could write a simple for loop, or use memcpy.
That being said, the recommended way for strings is to use strncpy. It prevents common errors resulting in, for example, buffer overflows (which is especially dangerous if array1 is filled from user input: keyboard, network, etc). Like so:
Copy// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);
As @Prof. Falken mentioned in a comment, strncpy can be evil. Make sure your target buffer is big enough to contain the source buffer (including the \0 at the end of the string).
If your arrays are not string arrays, use:
memcpy(array2, array1, sizeof(array2));
Copy string in C
How to copy a string into an array of chars without using any built-in function?
c - How can I copy individual chars from a char** into another char**? - Stack Overflow
c - Copying multi char array to another multi char array - Stack Overflow
Is there a function to copy a char** object to another char** object?
TIA.
A C string is a nul-terminated character array.
The C language does not allow assigning the contents of an array to another
array. As noted by Barry, you must copy the individual characters one by one
from the source array to the destination array. e.g. -
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
char str1[] = "Hello";
char str2[10] = {0};
for (int x = 0; x < strlen(str1); ++x)
{
str2[x] = str1[x];
}
printf("%s\n", str2);
return 0;
}
To make this common task easier there are standard library functions provided
which will perform this operation. e.g. - memcpy(), etc.
memcpy(str2, str1, 6);
When the array contains a nul-terminated string of characters you can use
strcpy(), etc.
strcpy(str2, str1);
Caveat: Some of the above functions are considered unsafe as they do not guard
against buffer overruns of the source and destination arrays. There are safer
versions provided by the compiler.
Note that if and when you start learning C++ you will find that there you can
assign a C++ std::string object to another object of the same type. However,
even in C++ the same rules apply when working with C strings, "raw" character
arrays, etc.
- Wayne
str2 is an array. It cannot appear on the left side of an assignment. You will need to use something like strcpy.
q is a pointer. It is perfectly legal to copy one pointer to another.
If I have array of strings like string a = {"Hello", "Bye", "HI"};
I want to copy hello in an array of char such as char copy. So that I can iterate over characters of Hello one by one.
How can I achieve this?
Assuming that you are using calloc size parameter wrong. One of these char** cleanList = (char**)calloc(arrayLength, CHARLEN); or cleanList[i] = (char*)calloc(10,CHARLEN); is wrong. You also should not cast the return value of a malloc() / calloc(). For legibility and code flow purposes I also replaced ifs statements. You also wrote for (j=0; j<strlen(dirtyList[i]+1);j++) instead of for (j=0; j<strlen(dirtyList[i])+1;j++) because strlen() calculates the length of the string without \0.Here is the code with few changes.
char** cleanStrings (char**dirtyList, int arrayLength)
{
int i, j, k;
char **cleanList = calloc(arrayLength,sizeof * cleanList);
for (i=0; i<arrayLength; i++)
{
k= 0;
cleanList[i] = calloc(10,sizeof * cleanList[i]);
for (j=0; j<strlen(dirtyList[i])+1;j++)
{
if ((dirtyList[i][j] != '[') && (dirtyList[i][j] != '#') && (dirtyList[i][j] != '-') ){
cleanList[i][k] = dirtyList[i][j];
k++;
}
}
}
return cleanList;
}
You're not allocating enough memory for cleanList. I assume CHARLEN is sizeof(char), which is 1 byte. But the elements of cleanList are char*, which is either 4 or 8 bytes, the allocation is much too small. It should be:
char **cleanList = calloc(arrayLength, sizeof(char *));
The general rule when using malloc or calloc is that the multiplier is always sizeof (T), where T is the destination type with one less *. So if you're assigning to char **, it's sizeof(char *).
we simply use the strcpy function to copy the array into the pointer.
char str[] = "Hello World";
char *result = (char *)malloc(strlen(str)+1);
strcpy(result,str);
In your first snippet you modify the pointer in the loop, so after the loop it will no longer point to the same location returned by the malloc call.
Look at it this way, after the call to malloc the pointer and the memory look like this:
result | v +---+---+---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+---+
After the first iteration of the loop it will look like this:
result
|
v
+---+---+---+---+---+---+---+---+---+---+---+---+
| H | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+
And after the loop is done it will look like this
result
|
v
+---+---+---+---+---+---+---+---+---+---+---+----+
| H | e | l | l | o | | W | o | r | l | d | \0 |
+---+---+---+---+---+---+---+---+---+---+---+----+
The copying is made, but the pointer no longer points to the original position.
[Note: Before the copying, the memory allocated by malloc will not be "empty" or initialized in any way, I just show it like that here for simplicity's sake.]
You will always need to 'worry' about the null terminator, in the sense that you can't not have a null terminator in your destination C string, and you will always need to explicitly write the null terminator at the end of your new C string.
Even the built-in strcpy method will copy the null terminator character from your original string to the destination string.
#include <stdio.h>
#include <assert.h>
int copy(char * source, char * destination, unsigned int lengthDestination);
int copy(char * source, char * destination, unsigned int lengthDestination)
{
int i;
for(i = 0; source[i] != '\0'; i++) {
destination[i] = source[i];
}
assert(i+1 == lengthDestination);
destination[i+1] = '\0';
return 0;
}
int main() {
char * source = "Test number 17"; //Length is 15 counting the null character
unsigned int destinationLength = 15;
char destination[destinationLength];
copy(source, destination, destinationLength);
printf("The String source is: %s\n", source);
printf("The String destination is: %s\n", destination);
return 0;
}
If you are passing destination previously declared with automatic storage type or as a pointer previously allocated with malloc, calloc or realloc having allocated storage type, and in either case having nchars of storage available, you can implement a fairly robust copy function by simply using snprintf.
Since you are passing the maximum number of characters, including the nul-terminating character as a parameter to your copy function, that dovetails nicely with the size parameter for snprintf. Further, snprintf will insure a nul-terminated string in destination -- even if source is too long to fit in destination. As a benefit, snprintf returns the number of characters copied if there is sufficient storage in destination for source, otherwise it returns the number of characters that would have been copied had destination had sufficient space -- allowing you to determine the number of characters truncated if destination is insufficient to hold your source string.
Before looking at the implementation of copy let's look at a prototype and talk about declaring functions to that they provide a meaningful return, and while up to you, let's also look at the order of parameters and type qualifier for source, e.g.
/* simple strcpy src to dest, returns dest on success and number of chars
* (including nul-termining char) in nchar, returns NULL otherwise.
*/
char *copy (char *dest, const char *src, size_t *nchar);
If you notice, most string functions return a pointer to the destination string on success (or NULL otherwise) which allows you to make immediate use of the return. Next, while not a show-stopper, most string (or memory in general) copy functions place the destination as the first parameter, followed later by the source. I'm sure either Brian Kerrigan or Dennis Ritchie could explain why, but suffice it to say, most copy function parameters are ordered that way.
Notice also that since you are not modifying the source string in copy, it is best to qualify the parameter as const. The const qualifier is more or less a promise you make to the compiler that source will not be modified in copy which allows the compiler to warn if it sees you breaking that promise, while also allowing the compiler to further optimize the function knowing source will not change.
Finally notice your size or my nchar is passed as a pointer above instead of an immediate value. Since a function in C can only return a single value, if you need a way to get a second piece of information back to the caller, pass a pointer as a parameter so the value at that address can be updated within the function making the new value available to the calling function. Here you return a pointer to dest (or NULL) to indicate success/failure while also updating nchar to contain the number of characters in dest (including the nul-terminating character as you passed in a size not a length).
The definition of copy is quite short and simplistic. The only requirement is the source and destination strings not overlap. (neither strcpy or snprintf are defined in that case). The basic flow is to validate both src and dest are not NULL, then handle the case where src is the "empty-string" (e.g. 1st character is the nul-character) and then to copy src to dest using snprintf saving the return in written and then using a simple conditional to determine whether truncation occurred (and warning in that case) and concluding by updating the value pointed to by nchar and returning dest, e.g.
/* simple strcpy src to dest, returns dest on success and number of chars
* (including nul-termining char) in nchar, returns NULL otherwise.
*/
char *copy (char *dest, const char *src, size_t *nchar)
{
if (!src || !dest) { /* validate src & dest not NULL */
fputs ("error: src or dest NULL\n", stderr);
return NULL; /* return NULL on error */
}
if (!*src) /* handle src being an "empty-string" */
*dest = 0, *nchar = 0;
int written = snprintf (dest, *nchar, "%s", src); /* call snprintf */
if ((size_t)written + 1 > *nchar) { /* handle truncated case */
fprintf (stderr, "warning: dest truncated by %zu chars.\n",
(size_t)(written + 1) - *nchar); /* warn with count */
}
else /* src fit in dest, set nchar to no. of chars in dest */
*nchar = (size_t)(written + 1); /* including nul-character */
return dest; /* return dest so available for immediate use */
}
Putting it altogether in a short example that takes the string to copy as the first argument to the program (using "source string" by default if no argument is given), you could do something like the following:
#include <stdio.h>
#define MAXC 16 /* constant for destination length */
/* simple strcpy src to dest, returns dest on success and number of chars
* (including nul-termining char) in nchar, returns NULL otherwise.
*/
char *copy (char *dest, const char *src, size_t *nchar)
{
if (!src || !dest) { /* validate src & dest not NULL */
fputs ("error: src or dest NULL\n", stderr);
return NULL; /* return NULL on error */
}
if (!*src) /* handle src being an "empty-string" */
*dest = 0, *nchar = 0;
int written = snprintf (dest, *nchar, "%s", src); /* call snprintf */
if ((size_t)written + 1 > *nchar) { /* handle truncated case */
fprintf (stderr, "warning: dest truncated by %zu chars.\n",
(size_t)(written + 1) - *nchar); /* warn with count */
}
else /* src fit in dest, set nchar to no. of chars in dest */
*nchar = (size_t)(written + 1); /* including nul-character */
return dest; /* return dest so available for immediate use */
}
int main (int argc, char **argv) {
char *src = argc > 1 ? argv[1] : "source string",
dest[MAXC];
size_t n = MAXC;
if (copy (dest, src, &n))
printf ("dest: '%s' (%zu chars including nul-char)\n", dest, n);
}
(note: the maximum number of characters in dest is kept short intentionally to easily show how truncation is handled -- size as appropriate for your needs)
Example Use/Output
$ ./bin/strcpy_snprintf
dest: 'source string' (14 chars including nul-char)
Showing maximum number of characters that can be copied without warning:
$ ./bin/strcpy_snprintf 123456789012345
dest: '123456789012345' (16 chars including nul-char)
Showing handling source too long for destination:
$ ./bin/strcpy_snprintf 1234567890123456
warning: dest truncated by 1 chars.
dest: '123456789012345' (16 chars including nul-char)
Look things over and let me know if you have further questions. There are at least a dozen different ways to approach a string copy, but given you are passing dest with its own storage and passing the maximum number of characters (including the nul-character) as a parameter, it's hard to beat snprintf in that case.
You can do it directly. If you want to copy a char of a specific position you can use
char c = source[index_of_array];
strcpy takes pointers to characters and not characters, what you could do is
void copyElement(int n, char source[100])
{
char * s = (char *) malloc (1) ;
strcpy(s, &source[n]);
}