How to split char* into 3 char* at delimiter? - c

I want to split a char* time = "15:18:13"; into char* hour;, char* minute; and char* seconds;.
The problem is that I don't know how. I am like to try a Pebble Watchface. I already used char* hour = strok(time, ":"); but the first parameter needs to be a char[] but time is a char*.
Does anyone know how to do this?

Based on alk's comment, the approach one can use is sscanf, like this:
#include <string.h>
int main ()
{
char* str = "15:18:13";
int a, b, c;
sscanf(str, "%d:%d:%d", &a, &b, &c);
printf("%d %d %d\n", a, b, c);
return 0;
}
However, the following is a more general solution.
Use strtok.
You can store them in an array, like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char str[] ="15:18:13";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,":");
char* a[3];
int i = 0;
while (pch != NULL)
{
a[i] = malloc( (strlen(pch)+1) * sizeof(char));
strcpy(a[i++], pch);
printf ("%s\n",pch);
pch = strtok (NULL, ":");
}
for(i = 0 ; i < 3 ; i++)
printf ("%s\n",a[i]);
return 0;
}
strdup, as suggested by Deduplicator, can also help, but it is not standard, thus I suggest to avoid (or implement your own, not that hard). :)
Moreover, strtok_s that Deduplicator mentions is not provided in C.
Reply to OP's comment below:
Question: str is char str[] but time is a char*. Can I convert this?
You can assign it to an array like this:
#include <stdio.h>
int main ()
{
char* from = "15:18:13";
char to[strlen(from) + 1]; // do not forget +1 for the null character!
strcpy(to, from);
printf("%s\n", to);
return 0;
}
GIFT: I suggest you read the first answer from here.
It provides a smooth explanation to char* and char[].

Don't need those api. Pebble has own api for time out: strftime
tm *tmNext = localtime(&timeRequestTmp);
static char strformatForTimeNext[10];
strftime(strformatForTimeNext,10,"%H:%M",tmNext);
text_layer_set_text(layer_nextTime, strformatForTimeNext);

Related

Separating two values in a char and assigning them to varables

New to C and Arduino programming, my issue, how to split char c into two separate integer variables? char c's value looks like this 140,100, both numbers are integers. I need to create two integer variables, SpeedX and SpeedY from this data so that SpeedX = 140 and SpeedY = 100. Thanks for your help!
how to split char c into two separate integer variables?
First of all, what you have is a string, not a char.
You can use the strtok() function to split a string (and specify the delimiter to use), like this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char nums[] = "140,100";
char *str;
int num;
int SpeedX, SpeedY, i = 0;
str = strtok (nums, ",");
while (str != NULL)
{
num = atoi(str);
if (i == 0)
SpeedX = num;
else if (i == 1)
SpeedY = num;
str = strtok (NULL, ",");
i++;
}
return 0;
}
NOTE : If, generally speaking about such a problem to solve in c and not in arduino, you do not know for sure that you will have only two elements in nums, you should use dynamic memory allocation (read more about it here), and modify your code like this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char nums[] = "140,100,500";
char *str;
int num;
int len, i = 0;
int *p;
str = strtok (nums, ",");
len = strlen(str);
p = malloc((len-1)*sizeof(int));
while (str != NULL)
{
num = atoi(str);
*(p+i) = num;
i++;
str = strtok (NULL, ",");
}
for (i = 0; i < len-1; i++)
printf("%d\n", *(p+i));
return 0;
}
The char you are talking about is most likely string or char array, which is really a pointer to a number of chars. A char can only store 1 character.
The function strtol defined in stdlib.h takes three arguments:
A char pointer to the beginning of your string (or the place you want to start looking
A pointer to a char pointer that will be updated to point to the first char after the end of the number
The base the number is represented in, most likely 10 in your case
Your data type is probably char* or char[50], because char can only represent one character, not a sequence of characters like "140,100".
Anyway, use sscanf, which scans a string and extracts values according to a given format:
char *myNums = "140,100";
int first,second;
int elementsRead = sscanf(myNums,"%d,%d", &first, &second);
// note: elementsRead is `2` if both format specifiers `%d` and `%d` have been scanned successfully

Can sscanf in C write on char* instead of char[]?

I'm looking for the simplest way in standard C to parse a string. The number of words inside the string is fixed, but the length of each single word is not. The code will be running on a microprocessor with limited memory so I can't just allocate an overkill buffer, I'd like to allocate just the memory that I need.
The following code works, but I'd like the single words to be char* . Is there some way around this?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char * my_words = "foo bar 1 2";
char word1[20];
char word2[20];
char word3[20];
char word4[20];
int match = sscanf(my_words,"%s %s %s %s",word1,word2,word3,word4);
printf("Matches: %d\r\n",match);
printf("%s\r\n",word1);
printf("%s\r\n",word2);
printf("%s\r\n",word3);
printf("%s\r\n",word4);
return 0;
}
Thank you
For parsing you can use strtok() function. A simple approach can be like that also you can modify it
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char const *my_words = "foo bar 1 2";
char *str = malloc(1 + strlen(my_words));
strcpy(str, my_words);
int countWord = 0;
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ");
++countWord;
}
printf("Total words = %d\n", countWord);
return 0;
}
The answer depends on how simple and standard your code should be.
If your target supports POSIX 2008 (recent GNU libc does), then you could use m modifier as docs suggest to allocate just enough space to read data.
But if you have to stay with ANSI C, then probably you're stuck to functions like strtok/strtok_r or alike.
And in the event you must roll your own, the algorithm goes like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
/* your input, I'll presume its constant */
const char *input = " foo bar 1 2 ";
/* here is your array of char*.
* you indicate the number of words is fixed */
char *words[4];
/* the algo */
size_t b = 0;
size_t e = 0;
size_t l = strlen(input);
int w = 0;
while (b < l) {
b += strspn(input + b, " ");
e = b + strcspn(input + b, " ");
words[w] = malloc(e - b + 1);
strncpy(words[w], input + b, e - b);
w++;
b = e+1;
}
/* debugging, outputs in reverse order */
while (w--) {
printf("%s\n", words[w]);
free(words[w]);
}
exit(EXIT_SUCCESS);
}
Obviously, you'd want to add error checking.

How do I use strtok to take in words separated by white space into a char array in C?

I have opened a file as such:
#define MAX 1000000000
char buffer[MAX];
FILE *file = fopen("sample1.txt", "r");
char c;
if(file == NULL) {
perror("File open error");
return -1;
}
Now what I want to do is that use 'strtok' and take in seperate words from the file into the char array buffer.
Since you seem new here, I will answer, but make sure to put more effort on your next question in SO.
Did you search for strtok()? In the ref, there is a very nice example. I just modified it a bit to use only the whitespace as a token.
I will leave the integration of this code to your code for you.
/* strtok example with whitespaces*/
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into token:\n",str);
pch = strtok (str," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ");
}
return 0;
}
Also notice that you can search google for relevant problems to yours. Here is a relevant question!
As Alter Mann pointed out:
#include <stdio.h>
#include <string.h>
char *strsep(char **, const char *);
int main(void)
{
char str[] = "- This, a sample string.";
char *pch = str;
char *tok;
printf("Splitting string \"%s\" into token:\n", str);
while (tok = strsep(&pch, " \t\n")) {
printf("%s\n", tok);
}
return 0;
}
is what you are looking for, is not standard but its available on many implementations. Check its ref here.
Moreover, notice how this is a tip for improving the strtok() code I provided above.

How do I concatenate two strings in C?

How do I add two strings?
I tried name = "derp" + "herp";, but I got an error:
Expression must have integral or enum type
C does not have the support for strings that some other languages have. A string in C is just a pointer to an array of char that is terminated by the first null character. There is no string concatenation operator in C.
Use strcat to concatenate two strings. You could use the following function to do it:
#include <stdlib.h>
#include <string.h>
char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
This is not the fastest way to do this, but you shouldn't be worrying about that now. Note that the function returns a block of heap allocated memory to the caller and passes on ownership of that memory. It is the responsibility of the caller to free the memory when it is no longer needed.
Call the function like this:
char* s = concat("derp", "herp");
// do things with s
free(s); // deallocate the string
If you did happen to be bothered by performance then you would want to avoid repeatedly scanning the input buffers looking for the null-terminator.
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator
return result;
}
If you are planning to do a lot of work with strings then you may be better off using a different language that has first class support for strings.
#include <stdio.h>
int main(){
char name[] = "derp" "herp";
printf("\"%s\"\n", name);//"derpherp"
return 0;
}
David Heffernan explained the issue in his answer, and I wrote the improved code. See below.
A generic function
We can write a useful variadic function to concatenate any number of strings:
#include <stdlib.h> // calloc
#include <stdarg.h> // va_*
#include <string.h> // strlen, strcpy
char* concat(int count, ...)
{
va_list ap;
int i;
// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for(i=0 ; i<count ; i++)
len += strlen(va_arg(ap, char*));
va_end(ap);
// Allocate memory to concat strings
char *merged = calloc(sizeof(char),len);
int null_pos = 0;
// Actually concatenate strings
va_start(ap, count);
for(i=0 ; i<count ; i++)
{
char *s = va_arg(ap, char*);
strcpy(merged+null_pos, s);
null_pos += strlen(s);
}
va_end(ap);
return merged;
}
Usage
#include <stdio.h> // printf
void println(char *line)
{
printf("%s\n", line);
}
int main(int argc, char* argv[])
{
char *str;
str = concat(0); println(str); free(str);
str = concat(1,"a"); println(str); free(str);
str = concat(2,"a","b"); println(str); free(str);
str = concat(3,"a","b","c"); println(str); free(str);
return 0;
}
Output:
// Empty line
a
ab
abc
Clean-up
Note that you should free up the allocated memory when it becomes unneeded to avoid memory leaks:
char *str = concat(2,"a","b");
println(str);
free(str);
I'll assume you need it for one-off things. I'll assume you're a PC developer.
Use the Stack, Luke. Use it everywhere. Don't use malloc / free for small allocations, ever.
#include <string.h>
#include <stdio.h>
#define STR_SIZE 10000
int main()
{
char s1[] = "oppa";
char s2[] = "gangnam";
char s3[] = "style";
{
char result[STR_SIZE] = {0};
snprintf(result, sizeof(result), "%s %s %s", s1, s2, s3);
printf("%s\n", result);
}
}
If 10 KB per string won't be enough, add a zero to the size and don't bother, - they'll release their stack memory at the end of the scopes anyway.
You should use strcat, or better, strncat. Google it (the keyword is "concatenating").
You cannot add string literals like that in C. You have to create a buffer of size of string literal one + string literal two + a byte for null termination character and copy the corresponding literals to that buffer and also make sure that it is null terminated. Or you can use library functions like strcat.
Concatenate Strings
Concatenating any two strings in C can be done in atleast 3 ways :-
1) By copying string 2 to the end of string 1
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
int i,j=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=strlen(str1);str2[j]!='\0';i++) //Copying string 2 to the end of string 1
{
str1[i]=str2[j];
j++;
}
str1[i]='\0';
printf("\nConcatenated string: ");
puts(str1);
return 0;
}
2) By copying string 1 and string 2 to string 3
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX],str3[MAX];
int i,j=0,count=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=0;str1[i]!='\0';i++) //Copying string 1 to string 3
{
str3[i]=str1[i];
count++;
}
for(i=count;str2[j]!='\0';i++) //Copying string 2 to the end of string 3
{
str3[i]=str2[j];
j++;
}
str3[i]='\0';
printf("\nConcatenated string : ");
puts(str3);
return 0;
}
3) By using strcat() function
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
strcat(str1,str2); //strcat() function
printf("\nConcatenated string : ");
puts(str1);
return 0;
}
Without GNU extension:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
res = malloc(strlen(str1) + strlen(str2) + 1);
if (!res) {
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
strcpy(res, str1);
strcat(res, str2);
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
Alternatively with GNU extension:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
if (-1 == asprintf(&res, "%s%s", str1, str2)) {
fprintf(stderr, "asprintf() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
See malloc, free and asprintf for more details.
#include <string.h>
#include <stdio.h>
int main()
{
int a,l;
char str[50],str1[50],str3[100];
printf("\nEnter a string: ");
scanf("%s",str);
str3[0]='\0';
printf("\nEnter the string which you want to concat with string one: ");
scanf("%s",str1);
strcat(str3,str);
strcat(str3,str1);
printf("\nThe string is %s\n",str3);
}
using memcpy
char *str1="hello";
char *str2=" world";
char *str3;
str3=(char *) malloc (11 *sizeof(char));
memcpy(str3,str1,5);
memcpy(str3+strlen(str1),str2,6);
printf("%s + %s = %s",str1,str2,str3);
free(str3);
my here use asprintf
sample code:
char* fileTypeToStr(mode_t mode) {
char * fileStrBuf = NULL;
asprintf(&fileStrBuf, "%s", "");
bool isFifo = (bool)S_ISFIFO(mode);
if (isFifo){
asprintf(&fileStrBuf, "%s %s,", fileStrBuf, "FIFO");
}
...
bool isSocket = (bool)S_ISSOCK(mode);
if (isSocket){
asprintf(&fileStrBuf, "%s %s,", fileStrBuf, "Socket");
}
return fileStrBuf;
}
In C, you don't really have strings, as a generic first-class object. You have to manage them as arrays of characters, which mean that you have to determine how you would like to manage your arrays. One way is to normal variables, e.g. placed on the stack. Another way is to allocate them dynamically using malloc.
Once you have that sorted, you can copy the content of one array to another, to concatenate two strings using strcpy or strcat.
Having said that, C do have the concept of "string literals", which are strings known at compile time. When used, they will be a character array placed in read-only memory. It is, however, possible to concatenate two string literals by writing them next to each other, as in "foo" "bar", which will create the string literal "foobar".

copying string from strtok

I need to divide a C string into tokens. I thought that strtok will be my best try, but I'm getting very strange results...
Here is my test program. In this example I will get 3 tokens with "##" separator but when I try to work with the ones I supposedly had copied, only the third one is shown correctly.. the other two look corrupted or something... I don't know... ?
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define TAM 3 //elements
char** aTokens(char* str, char* delimitador)
{
char* pch;
char** tokens;
int i = 0;
tokens = (char**)malloc(sizeof(char*)*TAM);
pch = strtok(str, delimitador);
while(pch != NULL)
{
tokens[i] = (char*)malloc((sizeof(strlen(pch))+1) * sizeof(char));
strcpy(tokens[i], pch);
pch = strtok(NULL, delimitador);
i++;
}
return tokens;
}
int main ()
{
char str[] = "30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,##30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,##30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,";
char** tokens;
int i;
tokens = aTokens(str, "##");
for(i = 0; i<TAM; i++)
printf("%d -- %s\n", strlen(tokens[i]), tokens[i]);
//Clean
//for(i = 0; i<TAM; i++)
//free(tokens[i]);
//free(tokens);
return 0;
}
output with GCC on Linux:
13 -- 30117700,1,T <---- ?
13 -- 30117700,1,T <----- ?
115 -- 30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,
I have commented the "clean" section because it provides lots of runtime error too ... :(
Help please!!
I think you are slightly confused on how strtok works.
For the most part, you've got it right. However, the string of separator characters that is given to strtok is not used as a string per se, but it used more like an array of characters, and strtok only cares about these individual characters. So calling strtok with the string "#" is exactly the same as giving it "##". In order to tokenize your string correctly, you need to decide on a single separator character to use, or use a different (perhaps custom) tokenizer function that can handle multi-character separators..
The following line isn't correct. sizeof(strlen(..)) will be 4 (in a 32-bit app) regardless of the length of the string.
tokens[i] = (char*)malloc((sizeof(strlen(pch))+1) * sizeof(char));
It should probably be:
tokens[i] = (char*)malloc((strlen(pch)+1) * sizeof(char));
Standard implementation of strtok:
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,##30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,##30117700,1,TITULAR,SIGQAA070,1977/11/30,M,1,14000,0.00,6600.00,10.00,2011/09/01,2012/09/01,0|17,0.00,NO,0,0,0.00, ,";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,"#");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, "#");
}
return 0;
}

Resources