I'm new to C and trying to split a character array (which I receive from a Serial Port in Ardunio). I looked up some tutorials and came up with this. Help me debug it please.
char action[10];
unsigned long duration;
void split(char input[20])
{
char *param, *ptr;
param = strtok_r(input, "#", &ptr);
action = *param; // Need help with this line
param = strtok_r(NULL, "!", &ptr);
duration = (unsigned long) *param; // Need help with this line
}
From what I understand, strtok_r returns a pointer to the character right after the delimiter(#). So if I wanted action[] to be a subset character array of input[] till the delimiter, what should I do?
Edit:
Input is something like this: "left#1000!"
It looks like your first token is a string, and the second token is a long. You can use strncpy to copy param into action, and then strtoul to parse an unsigned long to duration.
param = strtok_r(input, "#!", &ptr);
strncpy(action, param, sizeof(action));
// Force zero termination
action[sizeof(action)-1] = '\0';
param = strtok_r(NULL, "#!", ptr);
duration = strtoul(param, ¶m, 10);
You cannot initialize action = *param.
You need to use
memcpy(action, param, strlen(param))
and
duration = (unsigned long) atoi(param)
This snippet should work in plain C (comments added). You could use a C struct to collect values. Structs may be returned from functions like simple data types (as is shown). You could use that as a start for your own program.
Edit: Such programs don't need the strXYZ(..) functions (useful if you may have '\0'-bytes in your incoming data).
...
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char action[10]; unsigned long duration;
} Result;
Result split(char *input, char delim)
{
Result result = {'\0', 0}; // initialize result by zeros
char *p = (char*)memchr(input, delim, sizeof(result.action)-1);
if(p != NULL) { // if delimiter found in input
memcpy(result.action, input, p-input); // copy text till delimiter
result.duration = strtoul(p+1, NULL, 10); // convert number after delimiter
}
return result; // return values
}
int main(char argc, const char*argv[])
{
char input[20] = "left#1000!";
Result result = split(input, '#');
printf("action: %s, duration %u\n", result.action, result.duration);
return 0;
}
...
Regards
rbo
You should use strcpy() and necessary casting in order to assign strings(or char arrays) in C.
Visit http://en.cppreference.com/w/c/string/byte/strcpy
This function will care for membervise assignment between strings. To do it manually you must use loops and assign each array member seperately.
Related
I was messing around with all of the string functions today and while most worked as expected, especially because I stopped trying to modify literals (sigh), there is one warning and oddity I can't seem to fix.
#include <stdio.h>
#include <string.h>
int main() {
char array[] = "Longword";
char *string = "Short";
strcpy(array, string); // Short
strcat(array, " "); // Short (with whitespace)
strcat(array, string); // Short Short
strtok(array, " "); // Short
if (strcmp(array, string) == 0)
{
printf("They are the same!\n");
}
char *substring = "or";
if (strstr(array, substring) != NULL)
{
printf("There's a needle in there somewhere!\n");
char *needle = strstr(array, substring);
int len = strlen(needle);
needle[len] = "\0"; // <------------------------------------------------
printf("Found it! There ya go: %s",needle);
}
printf("%s\n", array);
return 0;
}
Feel free to ignore the first few operations - I left them in because they modified array in a way, that made the strstr function useful to begin with.
The point in question is the second if statement, line 32 if you were to copy it in an editor.
(EDIT: Added arrow to the line. Sorry about that!)
This line is wrong:
needle[len] = "\0";
Doublequotes make a string literal, whose type is char *. But needle[len] is a char. To make a char literal you use singlequotes:
needle[len] = '\0';
See Single quotes vs. double quotes in C or C++
Your second strcat call overruns the end of array, corrupting whatever happens to be after it in memory. Once that happens, the later code might do just about anything, which is why writing past the end of an array is undefined behavior
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
In my project there is a method which only returns a const char*, whereas I need a char* string, as the API doesn't accept const char*.
Any idea how to convert between const char* to char*?
First of all you should do such things only if it is really necessary - e.g. to use some old-style API with char* arguments which are not modified. If an API function modifies the string which was const originally, then this is unspecified behaviour, very likely crash.
Use cast:
(char*)const_char_ptr
To be safe you don't break stuff (for example when these strings are changed in your code or further up), or crash you program (in case the returned string was literal for example like "hello I'm a literal string" and you start to edit it), make a copy of the returned string.
You could use strdup() for this, but read the small print. Or you can of course create your own version if it's not there on your platform.
You can use the strdup function which has the following prototype
char *strdup(const char *s1);
Example of use:
#include <string.h>
char * my_str = strdup("My string literal!");
char * my_other_str = strdup(some_const_str);
or strcpy/strncpy to your buffer
or rewrite your functions to use const char * as parameter instead of char * where possible so you can preserve the const
A const to a pointer indicates a "read-only" memory location. Whereas the ones without const are a read-write memory areas. So, you "cannot" convert a const(read-only location) to a normal(read-write) location.
The alternate is to copy the data to a different read-write location and pass this pointer to the required function. You may use strdup() to perform this action.
To convert a const char* to char* you could create a function like this :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* unconstchar(const char* s) {
if(!s)
return NULL;
int i;
char* res = NULL;
res = (char*) malloc(strlen(s)+1);
if(!res){
fprintf(stderr, "Memory Allocation Failed! Exiting...\n");
exit(EXIT_FAILURE);
} else{
for (i = 0; s[i] != '\0'; i++) {
res[i] = s[i];
}
res[i] = '\0';
return res;
}
}
int main() {
const char* s = "this is bikash";
char* p = unconstchar(s);
printf("%s",p);
free(p);
}
You can cast it by doing (char *)Identifier_Of_Const_char
But as there is probabbly a reason that the api doesn't accept const cahr *,
you should do this only, if you are sure, the function doesn't try to assign any value in range of your const char* which you casted to a non const one.
For example, you could write this way:
const char* a = "art.bin";
char* b = new char[sizeof(a)];
strcpy(b, a);
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.
Yes, I'm a newbie as well. And I have been having this problem for quite some time. I'm trying to use strtok to split off a string, but the thing is it does not work. I have looked at the example on the man-pages as well as those online, and I still don't have the answer.
In the code below, I tried to use the sample code given as an answer in this site. The original while loop is:
char str[] = "hello world how are you?\n";
char *res;
res = strtok(str, " \n");
puts(res);
while (res != NULL)
{
res = strtok(NULL, " \n");
if(res!=NULL)
puts(res);
}
but when a change the str to data, and its respective delimiters (&=), it becomes a Segmentation Fault. How do I fix this? What's wrong in the code? Here is the complete code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *data;
data = "integer1=1&integer2=2&integer3=3&integer4=4";
puts(data);
char str[] = "hello world how are you?\n";
char *res;
res = strtok(data, "=&");
puts(res);
while (res != NULL)
{
res = strtok(NULL, "=&");
if(res!=NULL)
puts(res);
}
return 0;
}
by the way, the strtok_r function doesn't work either.
This:
char str[] = "hello world how are you?\n";
creates an array and initializes it with the contents of the string literal. This, however:
char *data;
data = "integer1=1&integer2=2&integer3=3&integer4=4";
declares data to be a pointer to the first character of the string literal, which is, of course, read-only, so when strtok() tries to modify it, it fails (invoking undefined behavior).
Notes:
So that's why you declare pointers to string literals as const char * and explicitly not as char *, and if you do so, I will find you and const-qualify you.
Arrays are not pointers, they never were, and they never will be either.
The behaviour you're observing can be explained by question 1.32 in com.lang.c FAQ:
What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
And the answer is:
A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:
As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values of the characters in that array (and, if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.
strtok break memory block. And literal strings can't modofiy. So you can't use strtoke for both.
Try this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char *data;
data = "integer1=1&integer2=2&integer3=3&integer4=4";
char *cur, *res;
cur = data;
res = strpbrk(cur, "=&");
while (res != NULL)
{
fwrite(cur, 1, res-cur, stdout);
fputc('\n', stdout);
cur = res + 1;
res = strpbrk(cur, "=&");
}
fputs(cur, stdout);
return 0;
}
This doesn't modify memory block.