write a funtion in C, that will take any number of strings or char* arguments, concatenate them, malloc memory and return the pointer to the new string.
this is a very useful tool, and i suggest doing this, just so you know how to.
ps: ever wonder why printf can take variable length arguments.
hint: its not a bunch of over ridden functions.
C Challenge #1
Moderator: Coders of Rage
C Challenge #1
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"
Re: C Challenge #1
This was a pretty interesting 'challenge', I knew how printf worked but had never created a function like this before...
I'd like to know what your approach to something like this would be, if it's any different at all.
Here's the code:
I'd like to know what your approach to something like this would be, if it's any different at all.
Here's the code:
Code: Select all
#include <stdarg.h> //va_list etc..
#include <stdio.h> //printf
#include <stdlib.h> //malloc
#include <string.h> //memcpy, strlen
/*
* @param amount The amount of null terminated character arrays that
* should be concatenated.
* @param ... Variable length list of char * to null terminated
* character arrays.
*/
char * my_concat(int amount, ...)
{
int i = 0;
int totalSize = 0;
int * lengths = (int*)malloc(amount);
char * concatenate = 0;
va_list vl;
// First calculate the total size of the end product
// by summing up the lengths of the individual parts
// whilst storing these lengths for fast lookup
va_start(vl, amount);
for(i = 0; i < amount; i++)
{
lengths[i] = strlen(va_arg(vl, char*));
totalSize += lengths[i];
}
va_end(vl);
// Then create a container for the end product using
// the size that was just calculated, +1 (for termination)
concatenate = (char*)malloc(sizeof(char) * (totalSize+1));
// Copy the individual parts into the container
va_start(vl, amount);
for(i = 0; i < amount; i++)
{
char * arg = va_arg(vl, char*);
memcpy(concatenate, arg, lengths[i]);
concatenate += lengths[i];
}
va_end(vl);
free(lengths);
// Append the termination character
*concatenate = '\0';
// Restore the pointer to its original location and return
return concatenate - totalSize;
}
int main(int argc, char * argv[])
{
char * mystring = my_concat(4,"Do not ","enter ","the wrong amount", " of strings!");
printf("%s\n", mystring);
free(mystring);
return 0;
}
177
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: C Challenge #1
Amarant did everything exactly as I would have.
Re: C Challenge #1
nide, except that you dont need the count, you just need it in this format
char *concatSTR(char *first, ....).
so there are better ways of doing it, but you are on the right track.
char *concatSTR(char *first, ....).
so there are better ways of doing it, but you are on the right track.
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"
Re: C Challenge #1
Unless you're using an entirely different mechanism I don't see how that would work.
The documentation for the va_arg function states the following:
It would certainly be more user friendly and less error prone, but the implementation would have gotten a little bit more complicated so I chose not to do it.
Also even printf fails to detect situations where the amount of arguments is too low, and crashes as a result of a segmentation error.
The documentation for the va_arg function states the following:
An alternative I had already thought up involved terminating the call to the concat method with a 0 value, so that it would look like this:Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list). The function should be designed in such a way that the amount of parameters can be inferred in some way by the values of either the named parameters or the additional arguments already read.
Code: Select all
concat("a", "b", "c", 0);
Also even printf fails to detect situations where the amount of arguments is too low, and crashes as a result of a segmentation error.
177
Re: C Challenge #1
in this function you have to add the (char*)NULL, but you can easily surpass that by just doing inside the function.Amarant wrote:Unless you're using an entirely different mechanism I don't see how that would work.
The documentation for the va_arg function states the following:An alternative I had already thought up involved terminating the call to the concat method with a 0 value, so that it would look like this:Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list). The function should be designed in such a way that the amount of parameters can be inferred in some way by the values of either the named parameters or the additional arguments already read.It would certainly be more user friendly and less error prone, but the implementation would have gotten a little bit more complicated so I chose not to do it.Code: Select all
concat("a", "b", "c", 0);
Also even printf fails to detect situations where the amount of arguments is too low, and crashes as a result of a segmentation error.
Code: Select all
#include <stdlib.h> /* for malloc, NULL, size_t */
#include <stdarg.h> /* for va_ stuff */
#include <string.h> /* for strcat et al */
char *vstrcat(char *first, ...)
{
size_t len = 0;
char *retbuf;
va_list argp;
char *p;
if(first == NULL)
return NULL;
len = strlen(first);
va_start(argp, first);
while((p = va_arg(argp, char *)) != NULL)
len += strlen(p);
va_end(argp);
retbuf = malloc(len + 1); /* +1 for trailing \0 */
if(retbuf == NULL)
return NULL; /* error */
(void)strcpy(retbuf, first);
va_start(argp, first);
while((p = va_arg(argp, char *)) != NULL)
(void)strcat(retbuf, p);
va_end(argp);
return retbuf;
}
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"
Re: C Challenge #1
Ah yes that's pretty much what I had in mind, except for the mistake I made with passing 0 instead of (char*)NULL.
177
Re: C Challenge #1
yeah you did well. i'll post a new challenge in a little bit, gotta think of a juicy one. go look and see if you can figuer the binary challege out.Amarant wrote:Ah yes that's pretty much what I had in mind, except for the mistake I made with passing 0 instead of (char*)NULL.
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"