I need to create a C-function to concatenate two of any type of data and return the string that is the result of concatenation. I have done this function below, but it does not work. Could somebody help me?
// void pointer does not store value, is just the address of a memory location
char* concatenate(void* varA, int tamA, void* varB, int tamB)
{
// char is 1 byte
char* result;
char* a,b; // helpers
result = malloc((tamA+tamB)*sizeof(char));
a = varA; // "a" receives the address pointed to by the pointer varA
b = varB; // "b" receives the address pointed to by the pointer varB
*result = *result << tamA + *a;
*result = *result << tamB + *b;
result = a; // let the results point to "a"
return result; // the result is the pointer "a"
}
In C, which is what you're asking about even though your code is C++, you can't do it like that.
There's no way to figure out from a bare void * how to convert it to a string.
You must add type information of some form, such as printf()'s string using e.g. %d for decimal integers and so on.
This would be a workable prototype, I think:
char * concat_any(const char *format1, const void *data1,
const char *format2, const void *data2);
I'm not saying "optimal" or even "suitable", but it would at least be possible to implement to that prototype. The format strings could be printf()-style, or whatever.
Note that for C, this would also be very impractical, since taking a void * implies that you need a pointer to the data, always. If you wanted to e.g. concatenate two numbers, you couldn't do it like this:
char *fortytwo = concat_any("%d", 4, "%d", 2); /* BROKEN CODE */
since that passes integers instead of void *, which is very ugly. You would have to do it like this:
const int four = 4, two = 2;
const char *fortytwo = concat_any("%d", &four, "%d", &two);
which is clearly not exactly convenient.
So, it would be better to use varargs, but then you get the problem of not being able to associate different varargs with different non-variable arguments, like so:
char * concat_anyv(const char *format1, ...,
const char *format2, ...); /* BROKEN CODE */
So, how about having two formatting strings first, then trusting the caller to pass the two arguments as varargs? That would give:
char * concat_anyv2(const char *format1, const char *format2, ...);
Now we're talking. This can be trivially implemented, even: internally concatenate the two formatting strings, and call vsnprintf() two times: once to figure out buffer size, then allocate, and call it again.
Usage would be like so:
char *fortytwo = concat_anyv2("%d", "%d", 4, 2);
Done.
If I understand correctly, what you are trying to do is copy the data that varA and varB point to into a new memory buffer, one after the other, and return a char-pointer to this buffer. You can achieve this easily with the memcpy function.
char *concatenate(void *varA, int tamA, void *varB, int tamB)
{
char* result = malloc(tamA + tamB);
// copy varA to "result"
memcpy(result, varA, tamA);
// copy varB to "result" after varA
memcpy(result+tamA, varB, tamB);
return result;
}
Note that whatever data varA and varB hold it is used as is and not converted to a human readable representation.
I have two little string functions in C that I use. The first is an adaptation others have made that uses the printf model as others mentioned, you have to know what the data types are going in:
char* str(const char *fmt, ...)
{
int size;
char *buff;
va_list argp1;
va_list argp2;
va_start(argp1, fmt);
va_copy(argp2, argp1);
//calling vsnprintf with a NULL buffer simply returns what would
//be the size of the resulting string but does not include space for nul byte
size = vsnprintf(NULL, 0, fmt, argp1) + 1;
va_end(argp1);
//now actually allocate a buffer of the correct size and then fill it
buff = calloc(1,size);
assert(buff != NULL);
vsnprintf(buff, size, fmt, argp2);
va_end(argp2);
return buff;
}
With this I can concat doing a simple
char *d = str("%s%s%d", s1, s2, 25);
I just have to remember to free the string that is returned as it is allocated memory.
I have a second routine that I use for simple string concatenations that I can nest in other calls as it does internal cleanup for me:
typedef enum {FREE_NONE, FREE_ONE, FREE_TWO, FREE_BOTH} CONCAT_FREE_FLAG;
char *concat(char *one, char *two, CONCAT_FREE_FLAG f)
{
int size = strlen(one) + strlen(two) + 1;
char *buff = calloc(1,size);
assert(buff != NULL);
strcpy(buff, one);
strcat(buff, two);
if( f == FREE_ONE || f == FREE_BOTH)
free(one);
if( f == FREE_TWO || f == FREE_BOTH)
free(two);
return buff;
}
This allows me to do things like:
char *s = concat(
concat("Static ",str("%dx%d", x, y), FREE_TWO),
"Other Static", FREE_ONE);
The reason I have this is really syntactic sugar so I can pass dynamically allocated strings in, get a new dynamically allocated string but not have to worry about cleaning up the input strings.
Related
The point being saying w.r.t c only, as I am more comfortable in C.
I am not expecting a example which says this is how it works ... What I am expecting is why should we use the Call back function or some say it as function pointer.
I followed many blog and stack-overflow also, but not satisfied with any of those answers.
Let's say ( I am suggesting one scenario here, like sorting thing) we should use the call back thing, where a method/function will take more time for processing.
Let's say a process is there with one thread only, and the program is doing a sorting, which will take huge time ( let's assume > 1 min ). According to huge no of bloggers here we should use the function pointer. But how it would be useful ?
Any how we are having only one Program Counter and we will get some amount of time to process this process from CPU, then how it would be useful ?
If you think some other example is there to explain the function pointer concept please provide the example.
I saw some body suggesting like, if you will use function pointer, then the result u can collect later, but this sounds really awkward ! how is this even if possible ? How can u collect something from a function after returning from there ? the function would have been destroyed right !!!
In real time people use this for any change in events, so that they can get notification...( just adding a point )
I have seen some good programmer using this function pointer, I am dying to know why would I use this , surely there is something I am missing here...
Please reply, thanks in Advance.
Since there was still a bit of uncertianty in your last comment, perhaps a concrete example illustrating the points would help. Let's start with a simple example that takes a string as user input from the command line (you could prompt the user for input as well). Now let's say we want to give the user to option to tell us how they want to store the input. For purpose of this example, lets say the options are (1) to store the string normally, such that it prints on one line horizonally, (2) store the reverse of the string which will also print on one line, (3) store the string with newlines after each character so it prints vertically, and (4) store the string in reverse with embedded newlines.
In a normal approach to this problem, you would probably code a switch statement or a series of else if statements and pass the string to 4 different routines to handle the different cases. Function pointers allow you to approach the problem a little differently. Rather than 4 different input routines to handle each case, why not 1 input routine that takes a function pointer as it's argument and changes the way it handles the string based on the function passed as an argument. The input routine could be as simple as making a copy of the string (to prevent modifying argv[1], etc...) and then passing the string as an argument to a function represented by the pointer:
/* make copy of original string, pass to callback function */
char *input (char *d, char *s, char *(*cbf)(char *))
{
strcpy (d, s);
return (*cbf) (d);
}
The input function above takes as arguments the destination string d, the source string s and then a pointer to a funciton cbf (short for callback function). Let's look at the function pointer syntax quickly and digest what it tells us:
char *(*cbf)(char *)
| | \
return | argument
type | list
|
function pointer
name/label
Above, the function pointer named cbf has a return type of char *, and takes a single argument of type char *. (note: only the type is specified in the funciton pointer argument list, not both the type and argument name -- e.g. no char *str, just char *) Now that may seem like a lot to type each time you want to pass a function of that type as an argument or use it in an assignment. It is. There is an easy solution to reduce the typing required. You can use a typedef for the function pointer similar to how you use a typedef with a struct, etc. Creating a typedef of type cbf is equally easy:
typedef char *(*cbf)(char *);
The funciton pointer typedef above creates a type cbf that can be used in place of char *(*cbf)(char *) wherever the function pointer type is needed. When a typedef is used, you are relieved from specifying the return type and the argument list as well as not having to put the function pointer inside parenthesis. This reduces the original function declaration to:
char *input (char *d, char *s, cbf fname)
{
strcpy (d, s);
return fname (d);
}
Making use of a typedef for a function not only simplifies passing the functions as argument, but also simplifies creating arrays of funciton pointers as well. An array of funtion pointers can be used to simplify selecting and passing any one of a given number of functions, as needed. For our input function we create an array of function pointers each pointing to a different function that can be used to put the input string in the desired format. For example, let's say our 4 functions described above have declaration like this:
/* input processing callback functions */
char *hfwd (char *s);
char *hrev (char *s);
char *vfwd (char *s);
char *vrev (char *s);
note: each of the functions match our pointer definition of type char * and accept a single argument of type char *. Using our cbf typedef, we can easily create an array of function pointers called fnames as follows:
cbf fnames[] = { &hfwd, &hrev, &vfwd, &vrev };
The fnames array can then be used like any other array to select any one of our functions by array index. (e.g. fnames[0] is our function hfwd) This now gives us the ability to take a second input from our user, a number, to select the format for our input string. This provides the ability to use any one of our callback function by simply giving the array index for the desired function as the second argument on the command line. For example any one of the functions can be designated by calling out program with:
./progname my_string 1 /* to process the input with the hrev */
Now granted this example does not do much more than reformat a string, but from the standpoint of function pointer syntax, collecting function pointers in an array, and passing a function pointer as an argument to extend the capabilities of your code, it covers a great deal. Take a look at the following example, and let me know if you have any questions. (recall, the full function pointer syntax, in the absence of a typedef, is also included, but commented so you can compare/contrast typedef use)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXS 128
/* typedef for function pointer */
typedef char *(*cbf)(char *);
/* simple string reverse function */
char *strrevstr (char *str);
/* input processing callback functions */
char *hfwd (char *s);
char *hrev (char *s);
char *vfwd (char *s);
char *vrev (char *s);
/* input function, pointer to function will determine behavior */
// char *input (char *d, char *s, char *(*cbf)(char *));
char *input (char *d, char *s, cbf fn);
int main (int argc, char **argv) {
if (argc < 3 ) {
fprintf (stderr, "error: insufficient input, usage: %s string int\n", argv[0]);
return 1;
}
int idx = atoi(argv[2]);
if (idx > 3 || idx < 0) {
fprintf (stderr, "error: invalid input -- out of range, (0 !< %d !< 3)\n", idx);
return 1;
}
cbf fnames[] = { &hfwd, &hrev, &vfwd, &vrev };
// char *(*fnames[])(char *) = { &hfwd, &hrev, &vfwd, &vrev };
char string[MAXS] = {0};
input (string, argv[1], fnames[idx]);
printf ("\nProcessed input ('%s' '%s'):\n\n%s\n\n", argv[1], argv[2], string);
return 0;
}
/* strrevstr - reverse string, original is not preserved. */
char *strrevstr (char *str)
{
if (!str) {
printf ("%s() error: invalid string\n", __func__);
return NULL;
}
char *begin = str;
char *end = str + strlen (str) - 1;
char tmp;
while (end > begin)
{
tmp = *end;
*end-- = *begin;
*begin++ = tmp;
}
return str;
}
/* string unchanged - print horizontal */
char *hfwd (char *s)
{ return s; }
/* string reversed - print horizontal */
char *hrev (char *s)
{ return strrevstr (s); }
/* string unchanged - print vertical */
char *vfwd (char *s)
{
char *p = s;
static char buf[MAXS] = {0};
char *b = buf;
while (*p)
{
*b++ = *p++;
*b++ = '\n';
}
*b = 0;
b = buf;
while (*b)
*s++ = *b++;
*b = 0;
return buf;
}
/* string reversed - print vertical */
char *vrev (char *s)
{
char *p = strrevstr (s);
static char buf[MAXS] = {0};
char *b = buf;
while (*p)
{
*b++ = *p++;
*b++ = '\n';
}
*b = 0;
b = buf;
while (*b)
*s++ = *b++;
*b = 0;
return buf;
}
/* make copy of original string, pass to callback function */
char *input (char *d, char *s, cbf fn)
// char *input (char *d, char *s, char *(*cbf)(char *))
{
strcpy (d, s);
return fn (d);
// return (*cbf) (d);
}
Output
$ ( for i in {0..3}; do ./bin/fnc_pointer my_string $i; done )
Processed input ('my_string' '0'):
my_string
Processed input ('my_string' '1'):
gnirts_ym
Processed input ('my_string' '2'):
m
y
_
s
t
r
i
n
g
Processed input ('my_string' '3'):
g
n
i
r
t
s
_
y
m
I need to store a list of names in C. I decided a good way to do this would be to use double pointers (or pointers-to-pointers).
So I will have an array of names. Each array value is a pointer to another array: the name, stored as a character array.
The names might look like
unsigned char *name = "Joseph";
etc.
And then I would have a list of names (double pointer), to which I could (dynamically) assign each name (single pointer).
(type) **listOfNames;
My question is: what type should the double pointer be? Since it is a pointer to a pointer, I was thinking that it must be large enough to hold an arbitrary memory address: unsigned long, maybe? Or is there another type meant specifically for double pointers?
Alternatively — is there a better way of storing a variable-length array or variable-length strings?
If you have a collection of unsigned char * values:
unsigned char *name_0 = "Joseph";
unsigned char *name_1 = "Helen";
unsigned char *name_2 = "Maximillian";
Then you can create:
unsigned char *data[] = { name_0, name_1, name_2 };
unsigned char **listOfNames = data;
Note that you need to allocate space for the list of pointers — in my code, that's the data array. You could use malloc() instead, but you'd need to remember to code the matching free() at some point.
Adding appropriate const qualifications is left as an exercise in frustration to the interested reader.
If you are reading a variable length list of names from a file a run time, with (presumably) one name per line, then you'd do best with POSIX getline() and strdup().
There must be a number of other questions that deal with this scenario, so I'll be terse with this code:
char **read_file(FILE *fp)
{
char *buffer = 0;
size_t bufsiz = 0;
char **lines = 0;
size_t n_lines = 0;
size_t n_alloc = 0;
while (getline(&buffer, &bufsiz, fp) > 0)
{
if (n_lines + 1 >= n_alloc)
{
size_t new_num = (n_alloc + 1) * 2;
size_t new_size = new_num * sizeof(*lines);
char **new_lines = realloc(lines, new_size);
if (new_lines == 0)
{
free(buffer);
free(lines);
return(0);
}
lines = new_lines;
n_alloc = new_num;
}
lines[n_lines++] = strdup(buffer); // Includes newline!
}
lines[n_lines] = 0; // Null terminate list of strings
free(buffer); // Release input line's memory
return lines;
}
Note that the code uses plain char and not unsigned char. You face some issues if you use unsigned char because neither getline() nor strdup() expects to work with unsigned char. While you can cast your way around the issue, it is messy to do so.
I have a character pointer, which has a string assigned to it. And I'm sure that the string is of 8 characters length. (Ex: SHIVA0BS) And it is also a fact that the last two letters are always going to be "BS". But I'm just going to double check it. Now I'd like to take the first 6 characters ("SHIVA0") and append it to something else, say ("SHIVA0NN") - how would I make it possible?
#include<stdio.h>
#include<stdlib.h>
void main()
{
char *ptr, *new;
ptr = "FECI00BS";
strncpy(new,ptr,6);
printf("%s",new);
strcat(new,"NN");
}
The above code is what I wrote. And I'm not sure why it is not working. I understand that my requirement is very trivial, but I tried printfs in between. I was able to find that (ptr+6) printed "BS", so that 6 is the length that I need. But this is still not working. Any help appreciated. I need the output in a string pointer. A new one is fine. But a string pointer.
P.S: Only C code please. No C++.
You didn't allocate memory to hold your new string
char * new = calloc(1, 10); // on heap
or
char new[10]; // on stack
memset(new, 0, sizeof(new)); // zero it
You're not allocating memory for storing the strings.
You need to allocate memory for both *ptr and *new.
The bare minimum would be:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr, *new;
new = (char*)malloc(sizeof(char) * 9);
new = (char*)malloc(sizeof(char) * 9);
ptr = "FECI00BS";
strncpy(a,ptr,6);
printf("%s",new);
strcat(a,"NN");
printf("%s",new);
}
You need 9 bytes (assuming your platform needs one byte per char) because of the End-Of-Line character, '\0', that needs to be present at the end of strings in order to use some string.h functions or print them correctly.
Also, read on why you need to be careful with strncpy. Depending on your platform, you may have access to some newer, safer alternatives from the C standard.
I think you want:
sprintf(ptr+6, "NN");
That will modify your buffer to convert BS into NN. In this case you can get rid of the new variable.
EDIT
Try this. Notice the char ptr[] instead of char* ptr. By using [] instead of a pointer you are allocating the buffer on the stack. This allows you to write to the buffer.
#include<stdio.h>
#include<stdlib.h>
void main()
{
char ptr[] = "FECI00BS";
sprintf(ptr+6,"NN");
printf(ptr);
}
Just a few simple checks and memcpy().
char *ShivaAppend(char *dest, const char *ptr, const char *suffix) {
size_t len = strlen(ptr);
if (len != 8) {
return NULL;
}
if (strcmp(ptr, "BS") != 0) {
return NULL;
}
len = strlen(suffix);
if (len != 2) {
return NULL;
}
memcpy(dest, ptr, 6);
memcpy(&dest[6], suffix, 2);
return dest;
}
...
char dest[9];
char *p = ShivaAppend(dest, "SHIVA0BS", "NN")
puts(p == NULL ? "fail", p);
Alright, so forgive me. I've started learning C, and coming from PHP, I hate the lack of explode() so I decided to create my own.
Here's what I have so far:
#include <stdio.h>
#include <windows.h>
char * explode(char * toExplode, char * delimiter) /* Need to add a buffer size here */
{
char * token;
token = strtok(toExplode, delimiter);
token = strtok(NULL, delimiter);
return token;
}
int main(void)
{
char string[] = "This is a string yaaaaay";
char * exploded;
exploded = explode(string, " ");
printf("%s\n", exploded); /* Should currently return 'is' */
return 0;
}
So far, it's working just as I expect it to. However, now I need to create a 2D array of variable size in the first dimension (actually, both dimensions.)
I was thinking of doing something like char * explode(char * toExplode, char * delimiter, int length = strlen(toExplode)) so that I could either specify the length or have it set it default. This of course doesn't work though, and I have no idea where to go from here.
Any ideas/help?
You can pass a known bad value (commonly a 0 or -1) as the length, have multiple similar functions, or use a macro.
If you go the bad value route, when you call your function you can give it a value you know isn't possible and check for such a bad value at the start of the function. Then automatically calculate the correct value and continue as usual. The problem with this is that you are now forced to have at least one bad value (not a problem in this case).
char * explode(char * toExplode, char * delimiter, int length){
if(length == 0)
length = ...;
In the multiple similar functions method, each function has a slightly different declaration. They cannot all have the same name because C does not support overloading the way that another language like C++ has. The printf() family of functions is a good example of this.
char * explodel(char * toExplode, char * delimiter, int length);
char * explode (char * toExplode, char * delimiter){
int length = ...;
return explodel(toExplode, delimiter, length);
}
The macro method is a bit of a hack, but it does work. It is a bit of a combination of the previous two methods, in which you have the two different functions you can call, but the first one gets preprocessed with a bad value automatically being passed to the other so it can figure out the correct length value.
#define explode (s, ...) explodel(s, __VA_ARGS__, 0)
char * explodel(char * toExplode, char * delimiter, int length, ...);
The way this works is that if you only give it the first two arguments, the 0 fall into place as the third argument. If you give it three arguments, all three are passed normally and the 0 is added as a forth invisible argument hidden away in the function stack. If you pass more than three, all the extra arguments will be hidden like the 0. If you try to pass only one argument, you will get the following error:
error: expected expression before ',' token
No you can't but that doesn't stop you from pushing in a dummy value (i.e. -1) and then first thing in the function if the value is -1 then change it to whatever value you want.
If you're stuck using C then the solution I'd recommend is rolling two functions; one with length, one without.
char * explode(char * toExplode, char * delimiter, int length)
{
...
}
char * explode(char * toExplode, char * delimiter)
{
int len = strlen(toExplode);
return explode(toExplode, delimiter, len);
}
So, the latter just works out the length for you and passes it to the former and returns the result.
In C you can't.
This is possible in C++, but with a constant value (-1), for example.
You can't overload a function in C, neither have default arguments, that's C++.
The only solution I can think of is having an static local variable, with the default value.
char * explode(char * toExplode, char * delimiter,unsigned int plen) /* Need to add a buffer size here */
{
static unsigned int slen = 100;
unsigned int len;
char * token;
if (plen!=0)
len = plen;
else
len = slen;
/*...*/
}
Some preface: I'm a computer engineering student taking a first class in C after 3 semesters of Java (up to data structures). This question is in relation to a homework assignment, but a few steps removed from solving it for me.
I have an input file that I read into memory such that it is stored in char[9][500]. I read in at most 500 strings of maximum length 8. I am attempting to sort this array using stdlib's built in qsort() function, and am having some memory errors.
Important snippets of code:
char data[4][500][60];
char debug[500][9];
size_t count = 0;
/* initialize file, open for reading */
FILE* pUserlog;
pUserlog = fopen("userlog","r");
while(!feof(pUserlog))
{
fscanf(pUserlog, "%9s %8s %16s",debug[count], data[1][count], data[2][count]);
fgets(data[3][count], 60, pUserlog);
count++;
}
This section reads the data into the arrays. The array of interest in this part is "debug". This is the array specified above. Here is my comparison function for qsort:
int compare(const void* a, const void* b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
puts("I'm in compare!");
return strncmp(*ia, *ib,8);
}
This is my attempt to call qsort:
size_t debug_len = sizeof(debug)/sizeof(char*);
printf("debug len: %d, count: %d, sizeof(char*): %d\n",debug_len,count,sizeof(char*));
qsort(debug,count, sizeof(char *), compare);
I attempted substituting debug_len in my call where count is, but I am still segfaulting. Here is the output:
$ ./test
debug len: 1125, count: 453, sizeof(char*): 4
I'm in compare!
Segmentation fault (core dumped)
Thank you!
The compare function will receive pointers to the elements that are being compared. You are effectively trying to compare characters using strncmp(). Since you have pointers to each of the strings, cast it to a char * and compare.
int compare(const void* a, const void* b)
{
const char *ia = (const char *)a;
const char *ib = (const char *)b;
puts("I'm in compare!");
return strncmp(ia, ib, 9);
}
Remember also, it's an array of arrays, not an array of pointers. So the size of an element should be the size of the array, 9 and not of the pointer, 4. At this point, it would be easier to just use sizeof debug[0] since it is a two-dimensional array. If you don't do this with the right sizes, qsort() will just destroy your array.
size_t elemsize = sizeof debug[0]; /* 9 - size of each element */
size_t count = sizeof(debug)/elemsize; /* 500 - number of elements in array */
qsort(debug, count, elemsize, compare);
What happens here is: you've got 500 strings. Now you pass all 500 to qsort, and it in turn passes each one as first and second argument to your compare function. It's a bit like writing this:
compare(debug[0], debug[1])
The C compiler passes the addresses, not the actual values of course. But now you interpret the pointer-to-void as pointer-to-pointer-to-char. Your code now does a dereference when calling strncmp, but that makes the value (the first 4 bytes) be treated as a pointer in strncmp. But strncmp will now in turn try to dereference the garbage "pointer" (which consists of part of one of your strings) and that makes bang.
To fix this, use char * instead of char **:
int compare(const void* a, const void* b)
{
puts("I'm in compare!");
return strncmp((const char *)a, (const char *)b, 8);
}