int size = sizeof(original) / sizeof(char*);
Applying sizeof to a pointer not an array over here. This will not return the size of the string to which it points to. strlen is the one you should look for here. Replace the above line with this (Solution to the size determination)
int size = strlen(original); // better to use `size_t`
Now here what is going on - the string literal is a char array which decays into pointer to the first element and that pointer value is being assigned - over which you applied sizeof. There is no trace of array here. To get the number of elements an array can hold you have to pass the array itself not the pointer.
Another thing is C is pass by value - so here to retain the changes either pass the pointer to the pointer or pass the allocated memory address from the function.
sizeof(char) is 1 so you don't need to write it explicitly - you can simply write
copy = malloc(size + 1);
Code:
stringcpy(original, ©);
And
void stringcpy(const char* original, char** copy) {
int size = strlen(original);
*copy = malloc(size + 1);
int i;
for(i = 0; original[i] != '\0'; i++) {
(*copy)[i] = original[i];
}
(*copy)[i] = '\0';
}
I have shown you the solution of the problem by passing the address of the pointer variable to the other function. Alternatively (try it yourself) you can return the allocated memory chunk's address from the function and assign it to the copy. This would also work.
Edit: If you are not allowed to change the function signature then yes it's not possible unless you provide the allocated memory to the copy like you did before in case-1.
The otherway to achieve correct behavior would be to do this
char* stringcpy(const char* original) {
int size = strlen(original) ;
char* copy = malloc(size + 1);
int i;
for(i = 0; original[i] != '\0'; i++) {
copy[i] = original[i];
}
copy[i]=0;
return copy;
}
And use it like this
copy = stringcpy(original);
Few things omitted in this answer:
Always check the return value of
malloc- in case it returns NULL you won't dereference it if you put a check of it.Don't cast the return type of
malloc-char*tovoid*conversion is implicit.Free the dynamically allocated memory when you are done working with it.
int size = sizeof(original) / sizeof(char*);
Applying sizeof to a pointer not an array over here. This will not return the size of the string to which it points to. strlen is the one you should look for here. Replace the above line with this (Solution to the size determination)
int size = strlen(original); // better to use `size_t`
Now here what is going on - the string literal is a char array which decays into pointer to the first element and that pointer value is being assigned - over which you applied sizeof. There is no trace of array here. To get the number of elements an array can hold you have to pass the array itself not the pointer.
Another thing is C is pass by value - so here to retain the changes either pass the pointer to the pointer or pass the allocated memory address from the function.
sizeof(char) is 1 so you don't need to write it explicitly - you can simply write
copy = malloc(size + 1);
Code:
stringcpy(original, ©);
And
void stringcpy(const char* original, char** copy) {
int size = strlen(original);
*copy = malloc(size + 1);
int i;
for(i = 0; original[i] != '\0'; i++) {
(*copy)[i] = original[i];
}
(*copy)[i] = '\0';
}
I have shown you the solution of the problem by passing the address of the pointer variable to the other function. Alternatively (try it yourself) you can return the allocated memory chunk's address from the function and assign it to the copy. This would also work.
Edit: If you are not allowed to change the function signature then yes it's not possible unless you provide the allocated memory to the copy like you did before in case-1.
The otherway to achieve correct behavior would be to do this
char* stringcpy(const char* original) {
int size = strlen(original) ;
char* copy = malloc(size + 1);
int i;
for(i = 0; original[i] != '\0'; i++) {
copy[i] = original[i];
}
copy[i]=0;
return copy;
}
And use it like this
copy = stringcpy(original);
Few things omitted in this answer:
Always check the return value of
malloc- in case it returns NULL you won't dereference it if you put a check of it.Don't cast the return type of
malloc-char*tovoid*conversion is implicit.Free the dynamically allocated memory when you are done working with it.
The memory that you allocate inside the function is allocated from the heap. When you exit the function, that memory is given back to the system, so that it is no longer allocated when you return.
Are you looking for something like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
int i;
char input[1000] = "Sample string";
char *in = malloc(1000 * sizeof(char)); // use dynamic number instead of 1000
strcpy(in, input);
for (i = 0; i < 5; ++i) { // intentionally printing the first 5 character
printf("%c", in[i]);
}
}
The output is:
Sampl
Edit: In C++ the cast is required for malloc, so I write:
(char *)malloc(1000 * sizeof(char))
But in C, never cast the result of malloc().
What you can do is just use strcpy() offer by C string.h after dynamically allocating memory to your array, as shown:
char *input = malloc(1000*sizeof(char));
and if the string you are trying to copy to variable input exceeds the allocated memory size (strlen > 999: don't forget! String has a null terminator '\0' that takes up the additional 1 char space), just realloc as shown:
input = realloc(input, 1000*2*sizeof(char));
/* check if realloc works */
if (!input) {
printf("Unexpected null pointer when realloc.\n");
exit(EXIT_FAILURE);
}
copying string using dynamic memory
c - Copy a String using dynamic function - Stack Overflow
c++ - Proper way to copy C strings - Stack Overflow
c - Copying dynamically allocated char* string into new char* string - Stack Overflow
Videos
the question asks to returns a pointer to a new dynamically allocated StringPair structure that contains pointers to two newly created copies of the parameter strings s1 and s2.
the function im working on is: StringPair* newStringPair(const char* s1, const char* s2)
my attempt:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// Declare the StringPair type.
// Note that we have incorporated the struct declaration into
// the typedef, but that this only works because we don't have any
// StringPair pointers in the structure (e.g. StringPair* next).
typedef struct stringpair_s {
char* first;
char* second;
} StringPair;
// **** Insert your newStringPair function definition here ***
StringPair* newStringPair(const char* s1, const char* s2)
{
StringPair* strings;
strings->first = s1;
strings->second = s2;
char* buff1 = malloc(sizeof(s1) * strlen(s1) + 1);
char* buff2 = malloc(sizeof(s2) * strlen(s2) + 1);
char *strncpy(buff1, strings->first, strlen(s1) + 1);
char *strncpy(buff2, strings->second, strlen(s2) + 1)
return strings;
free(buff1);
free(buff2);
}
int main(void)
{
char s1[] = "My first string";
char s2[] = "Another one";
StringPair* pair = NULL;
pair = newStringPair(s1, s2);
// Before printing, alter the initial strings to ensure
// the function hasn't just copied the pointers.
strncpy(s1, "Smasher1", strlen(s1)+1);
strncpy(s2, "Clobber2", strlen(s2)+1);
// Now print the new StringPair.
printf("String pair: ('%s', '%s')\n", pair->first, pair->second);
// Lastly free all dynamic memory involved.
free(pair->first);
free(pair->second);
free(pair);
}sizeof(char) is always 1. You can simplify your code by eliminating it.
Once you know the size of the string you're about to read, there's no way using scanf(3) to limit the input it reads to the size of the buffer you allocated. In general, we don't rely on the input to describe itself accurately.
In your case, even if the description is accurate, the code isn't: scanf promises to terminate the string read by %s with a NUL character, so your 6-byte input needs a 7-byte buffer to accommodate that NUL. That is one error.
There is a fancy way to get scanf to allocate the string memory for you. Traditionally, though, you'd use getline(3) for that, and strlen(3) to find out how much it read.
As one comment points out, realloc(3) invalidates its first argument, meaning p1 can't be relied on after that call. You really want output to be a separate buffer, into which you'll copy data from p1 and p2.
Once you've allocated your output buffer, though, you may be surprised to learn that sprintf(3) is your friend. One call to that function, with %.*s constructions to limit string output dynamically, and pointer arithmetic on the inputs, will generate what you need.
Here is the correct code of copy a string using dynamic method. Refer the point 1 to get more clarity.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1, n2, loc;
char *p1, *p2, *output;
printf("Enter size of p1: ");
scanf("%d", &n1);
p1 = malloc((n1 + 1) * sizeof(char));
printf("Enter the P1 String: ");
scanf("%s", p1);
printf("\nEnter the size of p2: ");
scanf("%d", &n2);
p2 = malloc((n2 + 1) * sizeof(char));
printf("Enter the P2 String: ");
scanf("%s", p2);
printf("\nEnter the Location to copy: ");
scanf("%d", &loc);
output = malloc((n1 + n2 + 1) * sizeof(char)); //After allocating a memory to both sizes of string along with adding memory for NULL.
for (int i = 0; i < loc; i++)
*(output + i) = *(p1 + i);
for (int i = loc - 1; i <= n1; i++)
*(output + i + n2) = *(p1 + i);
for (int i = 0; i < n2; i++)
*(output + i + loc) = *(p2 + i);
printf("\nFinal copy is: ");
printf("%s\n", output);
free(p1);
free(p2);
free(output);
return 0;
}
You could use strdup() to return a copy of a C-string, as in:
#include <string.h>
const char *stringA = "foo";
char *stringB = NULL;
stringB = strdup(stringA);
/* ... */
free(stringB);
stringB = NULL;
You could also use strcpy(), but you need to allocate space first, which isn't hard to do but can lead to an overflow error, if 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);
stringB = NULL;
If you cannot use strdup(), I would recommend the use of strncpy() instead of strcpy(). The strncpy() function copies up to โ and only up to โ n bytes, which helps avoid overflow errors. If strlen(stringA) + 1 > n, however, you would need to terminate stringB, yourself. But, generally, you'll 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);
stringB = NULL;
I think strdup() is cleaner, myself, so I try to use it where working with strings exclusively. I don't know if there are serious downsides to the POSIX/non-POSIX approach, performance-wise, but I am not a C or C++ expert.
Note that I cast the result of malloc() to char *. This is because your question is tagged as a c++ question. In C++, it is required to cast the result from malloc(). In C, however, you would not cast this.
EDIT
There you go, there's one complication: strdup() is not in C or C++. So use strcpy() or strncp() with a pre-sized array or a malloc-ed pointer. It's a good habit to use strncp() instead of strcpy(), wherever you might use that function. It will help reduce the potential for errors.
If I just initialize stringB as char *stringB[23], because I know I'll never have a string longer than 22 characters (and allowing for the null terminator), is that the right way?
Almost. 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's a possibility that the string might 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, unless you've proved that the overhead is prohibitive. Many implementations have a "short string optimisation", which will avoid dynamic allocation for short strings; in that case, there will be little or no overhead over using a C-style array. Access to individual characters is just as convenient as with a C-style array; in both cases, s[i] gives the character at position i as an lvalue. Copying becomes stringB = stringA; with no danger of undefined behaviour.
If you really do find that std::string is unusable, consider std::array<char,MAX+1>: a copyable class containing a fixed-size array.
If stringB is checked for equality with other C-strings, will the extra space affect anything?
If you use strcmp, then it will stop at the end of the shortest string, and will not be affected by the extra space.
You need to null terminate your string by appending \0 at the end of string.
encode_data = malloc(6*sizeof(char));
for( i = 0; i < 5; i++)
encode_data[i] = 'a';
encode_data[i] = '\0';
The copied string is not zero terminated. You can print a string without a zero terminator like this:
int copy_data_len = 5;
printf("\nCopy Data= %.*s", copy_data_len, copy_data);
Alternatively allocate one more character for the zero terminator and set it to 0.
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.