int main(int argc, char *argv[]) {
if(argc!=3) {
printf("You must pass exactly three para \n");
return 0;
}
char *buffer = argv[1];
//printf("The length of the buffer string is %d\n",buflen);
char *mystring = argv[2];
//printf("The length of the user string is %d\n",len);
addstring(buffer, mystring);
return 0;
}
int addstring(char *buffer, char *mystring)
{
int buflen = strlen(buffer);
int len = strlen(mystring);
char *dest;
*dest = (char *)malloc(buflen + len + 1);
printf("The size of destination is %lu\n",sizeof(dest));
dest = strcpy(dest,buffer);
dest = (dest + buflen);
dest = strcpy(dest,mystring);
printf("The final string is %p",dest);
return 0;
}
In the above code, the function addstring(..) shoes this error Assignment makes integer from a pointer without a cast. I know I'm taking the value of a pointer and putting it in integer, but how may I do it to resolve this error?
Even after changing *dest to dest, your function addstring is not works properly.. Simply try like this
int addstring(char *buffer, char *mystring)
{
int buflen = strlen(buffer);
int len = strlen(mystring);
char *dest;
dest = (char *)malloc(buflen + len + 1);
printf("The size of destination is %d\n",sizeof(dest));
strcpy(dest,buffer);
strcat(dest,mystring);
printf("The final string is %s\n",dest);
return 0;
}
You have done
*dest = (char *)malloc(buflen + len + 1);
instead of
dest =malloc(buflen + len + 1);
Your program saying warning to me for this line
printf("The size of destination is %lu\n",sizeof(dest));
sizeof() return type is not long unsigned int.
So use %d or %u or %zu as a access specifier in printf() statement.
change
char *dest;
*dest = (char *)malloc(buflen + len + 1);
to
char *dest;
dest = (char *)malloc(buflen + len + 1);
EDIT: As #POW said, you need not cast the result of malloc
There are multiple issue in your code.
Please check the below code
int addstring(char *buffer, char *mystring)
{
int buflen = strlen(buffer);
int len = strlen(mystring);
char *dest;
/* No need to type-cast the malloc() */
dest = malloc(buflen + len + 1); /* *dest holds the value, dest holds the address */
printf("The size of destination is %lu\n",sizeof(dest));
strcpy(dest,buffer);
strcpy(dest+buflen,mystring);/* copy the second string to dest after buffer is copied */
printf("The final string is %s\n",dest); /*To print a string use %s, %p is to print pointer*/
return 0;
}
Related
Maybe it's a stupid question, but I get stuck here for a while.
Let's say freq_tostring() converts a word frequency freq into string, and freq_intostream() appends that string to the end of a stream.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
typedef struct {
char *word; // null-terminated
int freq;
} freq;
/**
* Constructor
*/
void new_freq(freq *fq, const char *word, const int freq) {
fq->word = (char *)malloc((strlen(word) + 1) * sizeof(char)); // +1 for null-terminator
strcpy(fq->word, word);
fq->freq = freq;
}
/**
* Free memory
*/
void dispose_freq(void *fq) {
freq *p = (freq *)fq;
free(p->word);
p->word = NULL;
}
/**
* snprintf() will terminate the string with a null character, unless buf_size is zero.
*/
char *freq_tostring(freq *fq) {
size_t wordlen = strlen(fq->word);
char *buffer = (char *)malloc(wordlen + 16); // maximum integer has 10 digits
snprintf(buffer, wordlen + 16, "[%s, %d]\n", fq->word, fq->freq);
return buffer;
}
/**
* Append the string of freq to the end of stream.
*/
void freq_intostream(void *elem, void *stream) {
freq *fq = (freq *)elem;
char *str = *(char **)stream;
size_t strsize = strlen(str);
// printf("Stream = \"%s\", length = %lu\n", str, strsize);
char *word = freq_tostring(fq);
size_t wordsize = strlen(word);
// printf("Element = \"%s\"%lu\n", word, wordsize);
char *temp = (char *)realloc(str, strsize + wordsize + 1);
strcpy(temp + strsize, word);
temp[strsize + wordsize] = '\0';
// printf("After strcpy(): \"%s\"\n", temp);
str = temp;
free(word);
}
int main(void) {
freq apple, banana, kiwi;
new_freq(&apple, "apple", 3);
new_freq(&banana, "banana", 2);
new_freq(&kiwi, "kiwi", 5);
char *buffer = (char *)malloc(1);
buffer[0] = '\0';
freq_intostream(&apple, &buffer);
freq_intostream(&banana, &buffer);
freq_intostream(&kiwi, &buffer);
assert(strlen(buffer) == 33);
assert(strcmp(buffer, "[apple, 3]\n[banana, 2]\n[kiwi, 5]\n") == 0);
dispose_freq(&apple);
dispose_freq(&banana);
dispose_freq(&kiwi);
free(buffer);
}
The weird thing is, when I run 10 times, it gives me about 9 pointer being realloc'd was not allocated, but maybe in 1~2 cases, everything is ok.
If I comment out the printf(), it shows that before appending the third element kiwi, the stream is empty, and that could be why realloc is failed. But I'm sure that I pass a pointer of char * stream to the freq_intostream() function, which is a char ** for sure. I can't find out what's the problem, anyone can help?
You've done the equivalent of i = j; i = 3; when you wanted j = 3;. Obviously, these don't do the same thing. Have a close look at the marked line in this funciton:
/**
* Append the string of freq to the end of stream.
*/
void freq_intostream(void *elem, void *stream) {
freq *fq = (freq *)elem;
char *str = *(char **)stream;
size_t strsize = strlen(str);
// printf("Stream = \"%s\", length = %lu\n", str, strsize);
char *word = freq_tostring(fq);
size_t wordsize = strlen(word);
// printf("Element = \"%s\"%lu\n", word, wordsize);
char *temp = (char *)realloc(str, strsize + wordsize + 1);
strcpy(temp + strsize, word);
temp[strsize + wordsize] = '\0';
// printf("After strcpy(): \"%s\"\n", temp);
str = temp; // OOPS!!
free(word);
}
You change the value of str, but str is a local to this function and its value is thrown away as soon as the function ends.
You wanted: *(char**)stream = temp; to change the value the caller passed you a pointer to.
This code would be much simpler if you get rid of all the casts. If elem were of type char **, you could just do *elem = temp; and the code would be much easier to understand.
My problem is as follows. I have to create a C program that concatenates all the parameters in input in one buffer and then this return this buffer. My solution works, but there are memory management issues.
How can I fix the problem?
#define RIALLOCA(buf, newsize) buf = realloc(buf, newsize);
char *mystrcat(char *buf, size_t sz, char *first, ...) {
va_list l;
va_start(l, first);
buf = malloc(strlen(buf) + 1);
if (sz < strlen(first) + 1) {
sz += (strlen(first) + 1);
}
RIALLOCA(buf, sz + 1 + 16);
strncat(buf, first, strlen(first));
char *nextString = va_arg(l, char *);
while (nextString != NULL) {
// sz += strlen(nextString);
RIALLOCA(buf, strlen(buf) + strlen(nextString) + 1 + 16);
strncat(buf, nextString, strlen(nextString));
nextString = va_arg(l, char *);
}
va_end(l);
return buf;
}
int main(int argc, char *argv[]) {
if (argc != 7) {
printf("troppi pochi argomenti\n");
return -1;
}
char *buffer = NULL;
RIALLOCA(buffer, 16); // macro che effettua l'allocazione
buffer[0] = '\0';
buffer = mystrcat(buffer, 16, argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], NULL);
printf("%s\n", buffer);
free(buffer);
return 0;
}
This is problem with Valgrind
The problem is that - when you call buf = malloc() inside mystrcat() - you are causing a memory leak. Memory had already been dynamically allocated for buf within your main().
Change
buf = malloc(strlen(buf)+1);
to
buf = realloc(buf, strlen(buf) + 1);
Also ... I agree with user3629249: providing macros for standard library functions in the way you have done seems redundant - at least in this context.
in function: mystrcat()
This statement:
buf = malloc(strlen(buf) + 1);
is not correct. Because buf is already a pointer to allocated memory AND this is not modifying the pointer buf back in the main() function but rather just the parameter on the stack.
To correct:
in main() (notice the additional '&' on parameter: buffer)
buffer = mystrcat(&buffer, 16, argv[1], argv[2], argv[3], argv[4],
argv[5], argv[6], NULL);
in mystrcat() remove this line
buf = malloc(strlen(buf) + 1);
regarding:
if(sz < strlen(first) + 1)
{
sz += (strlen(first) + 1);
}
since sz contains 16 and the first character in buf is '\0' This if() statement will never be entered.
Since the passed parameter buf is now a pointer to a pointer, due to the change in main(), the signature should be:
char* mystrcat(char **buf, size_t sz, char *first, ...)
and all references to buf should be de-referencing that parameter to access the pointer value in main()
There is plenty more, but the above are the underlying problems
I am writing a very simple program to copy a string using malloc.
#include <stdio.h>
#include <stdlib.h>
char * copyStr(char s[])
{
int len = strlen(s); //find length of s
char * copy;
copy = (char *)malloc(len); //dynamically allocate memory
int i;
for(i=0;i<len;i++)
{
copy[i]=s[i]; //copy characters
}
return copy; //return address
}
int main(int argc, char ** argv)
{
char * str;
str = "music is my aeroplane";
char * res;
res = copyStr(str);
printf("The copied string is : %s",res);
getch();
}
The desired output is:
The copied string is : music is my aeroplane
The current output is:
The copied string is : music is my aeroplaneOMEeJ8«≤╝
Any advice is appreciated.
A C string is null terminated. Add a null character (ie the char which ASCII code is 0) at end of the string :
char * copyStr(char s[])
{
size_t len = strlen(s); //find length of s
char * copy;
copy = (char *)malloc(len + 1); //dynamically allocate memory
/* One more char must be allocated for the null char */
size_t i;
for(i=0;i<len;i++)
{
copy[i]=s[i]; //copy characters
}
copy[i] = '\0'; // HERE
return copy; //return address
}
It is better to use size_t for the lengths because it is unsigned.
Strings in C are null-terminated.
The C programming language has a set of functions implementing
operations on strings (character strings and byte strings) in its
standard library. Various operations, such as copying, concatenation,
tokenization and searching are supported. For character strings, the
standard library uses the convention that strings are null-terminated:
a string of n characters is represented as an array of n + 1 elements,
the last of which is a "NUL" character.
In this case, you should have enough memory to store the original string contents and the "NUL" character (length+1). And don't forget to ensure the presence of the "NUL" character after the end of the string.
There are many possible ways to implement char * copyStr(char[]) function:
1) Your way (corrected):
char * copyStr(char s[])
{
int i;
size_t len = strlen( s );
char * p = (char*) malloc( len + 1 );
for( i = 0; i < len; i++ )
p[i] = s[i];
p[i] = '\0';
return p;
}
2) Using memcpy():
char * copyStr(char s[])
{
size_t len = strlen( s );
char * p = (char*) malloc( len + 1 );
memcpy( p, s, len );
p[ len ] = '\0';
return p;
}
3) Using strcpy():
char * copyStr(char s[])
{
size_t len = strlen( s );
char * p = (char*) malloc( len + 1 );
strcpy( p, s );
return p;
}
4) Using strdup():
char * copyStr(char s[])
{
return strdup(s);
}
Note: For every malloc() function call you need a free() function call, your main() needs a little modification for correctness:
int main( int argc, char ** argv )
{
char * str;
char * res;
str = "music is my aeroplane";
res = copyStr( str );
printf( "The copied string is : %s", res );
free(res); /* freedom */
getch();
return 0;
}
Hope it Helps!
I wrote a program to concat two strings and make sure the buffer will double the size when there's no enough space.
char * strcat_ex(char * * dest, int * n, const char * src){
int dest_len = 0;
int src_len = 0;
if (*dest == NULL) *n = 0;
else dest_len = strlen(*dest);
if (src == NULL) return *dest;
else src_len = strlen(src);
if (dest_len + src_len + 1 > *n) {
//(1) malloc a new buffer of size 1 + 2 * (strlen(*dest) + strlen(src))
char * temp;
temp = (char*) malloc(1 + 2 * (strlen(*dest) + strlen(src)));
//(2) set '*n' to the size of the new buffer
*n = 1 + 2 * (strlen(*dest) + strlen(src));
//(3) copy '*dest' into the beginning of the new buffer
strcpy(temp, *dest);
//(4) free the memory '*dest', and then set '*dest' to point to the new buffer
free(*dest);
*dest = temp;
}
//(5) concatenate 'src' onto the end of '*dest'.
while (temp) temp++;
while ((temp++ = src++) =! '\0');
return *dest;}
and this code doesn't work. I got segmentation fault at "free(*dest)".
Please help. Thank you very much!
Here's the main function:
int main(int argc, char * * argv){
printf("\nTesting strcat_ex(...)\n");
char * str1;
str1 = "one";
char * str2;
str2 = "two";
int n;
n = strlen(str1);
printf("Before strcat_ex, str1 == %p (%s), str2 == %p (%s)\n", str1, str1, str2, str2);
strcat_ex(&(str1), &n, str2);
printf("After swap, str1 == %p (%s), str2 == %p (%s)\n", str1, str1, str2, str2);
return EXIT_SUCCESS;
}
The problem is that the initial value of str1 is a pointer to a literal string. That pointer cannot be freed. So the fix is to malloc space in main, e.g.
char *str1 = malloc( 100 ); // allocate an initial buffer
int n = 100; // the buffer has 100 bytes
strcpy( str1, "one" ); // put some text in the buffer
I'm trying to read two consecutive characters from one string and pass two by two characters to another string. The code is below but it gives me segmentation fault! What am I doing wrong?
char *st = malloc(16*sizeof(char));
char *string = "purpleredblue";
int i;
int x=0;
while(x<=16)
{
for(i=x;i<=x+2;i++)
{
*st++=*string++; //copies content from string to st
}
x+=2;
}
printf("%s\n",st);
Your code is completely wrong. This might help:
char *buffer = (char*)malloc(16 * sizeof(char));
char *source = "purpleredblue";
char *dst = buffer;
char *src = source;
char *end = source + strlen(source);
while (src <= end)
{
strncpy(dst, src, 2);
dst += 2;
src += 2;
}
printf("%s", buffer);