Pig Latin Implementation in C - c

I'm trying to implement question 8.13 from C How to program, which is simply shifting left from the second char of the string and concat the first char of the string with "ay". For example:
jump -> umpjay the -> hetay and so on.
My try is here:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *appender(char s);
void shiftLeft(char [], int);
int main()
{
char s[100], *lastThree;
fgets(s, 100, stdin);
s[strcspn(s, "\n")] = 0;
char *tokenPtr = strtok(s, " ");
while(tokenPtr != NULL){
lastThree = appender(tokenPtr[0]);
//printf("lastThree : %s\n", lastThree); //for debugging
shiftLeft(tokenPtr, strlen(tokenPtr));
sprintf(tokenPtr, "%s%s ", tokenPtr, lastThree); // concatenation
printf("tokenptr:%s ", tokenPtr);
tokenPtr = strtok(NULL, " ");
}
return 0;
}
char *appender(char s){
char *returned = (char*)malloc(sizeof(char)*4); // allocation
snprintf(returned, sizeof(returned), "%c%s",s,"ay"); // append ay
return returned;
}
void shiftLeft(char s[], int len){
int i;
for(i=0;i<len-1;i++){
s[i]=s[i+1];
}
s[i] = '\0';
}
But code works wrong. It evaluates tokenPtr as yaay even if the input is only a word.

Related

Sorting string lexicographically in c

I want to sort words of a string in lexicographical order.
For Example:
I have a string: I am Apple
Output should be: am Apple I
Problem (output):
enter the string
hello shamsh
the sorted array:
hello
It's not sorting the string and whole string is not being shown in the output, can anyone help me out here. Thanks!
Program code:
#include<stdio.h>
#include<string.h>
void main()
{
char a[25][25],t[25];
char s[200];
char * pch;
int count = 0;
int i,j ,n;
printf("enter the string\n");
gets(s);
pch = strtok (s," ,.-");
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
count=count+1;
i=0;
while(pch != NULL)
{
strcpy(a[i],pch);
pch = strtok (NULL, " ,.-");
i++;
}
for(i=0;i<count-1;i++)
{
for(j=i+1;j<count;j++)
{
if(strcmp(a[i],a[j])>0)
{
strcpy(t,a[i]);
strcpy(a[i],a[j]);
strcpy(a[j],t);
}
}
}
printf("the sorted array:\n");
for(i=0;i<count;i++)
printf("%s\n",a[i]);
}
If you try to print your string after you pch = strtok (s," ,.-"), you'll notice that your string is broken up. That's because strtok() is destructive and breaks up the string into tokens so you need to count the number of white spaces before calling strtok():
printf("enter the string\n");
gets(s);
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
count=count+1;
i=0;
pch = strtok (s," ,.-");
Also like Weather Vane said, don't use gets(), use fgets() instead oand remove the '\n' from end of the string afterwards. Also you can use realloc() to assign more memory to a dynamic array instead of using a static array since you wouldn't know the number of words in a string beforehand.
#include <stdlib.h>
#include<stdio.h>
#include<string.h>
void main()
{
char** a = NULL;
char t[25];
char s[512];
char * pch;
int count = 0;
int i,j ,n;
printf("enter the string\n");
if(fgets(s,512, stdin)==NULL)
{
printf("failed to read string\n");
exit(-1);
}
/*remove '\n' from end of the string*/
char *pos;
if ((pos=strchr(s, '\n')) != NULL)
*pos = '\0';
pch = strtok(s, " ,.-");
while(pch)
{
a = realloc(a, sizeof(char*)*++count);
if(a==NULL)
{
perror("failed to allocate memory\n");
exit(-1);
}
a[count-1] = pch;
pch = strtok(NULL, " ,.-");
}
for(i=0;i<count;i++)
printf("%d: %s\n", i, a[i]);
///...compare array
Use qsort() for this sort of thing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 0x100
int strcmp_wrapper(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
}
int main () {
char buffer[BUF_SIZE], *tokens[BUF_SIZE / 2 + 1];
int i = 0, j = 0;
printf("Enter a string: ");
fgets(buffer, BUF_SIZE, stdin);
tokens[0] = strtok(buffer, " ,.-\n");
while ((tokens[++i] = strtok(NULL, " ,.-\n")));
qsort(tokens, i, sizeof(tokens[0]), strcmp_wrapper);
while (j < i)
printf("%s\n", tokens[j++]);
return 0;
}
below is a compact working way of doing what you want. It prints the words of each line, sorted and separated by one space, without repeating words being repeated (if you want them repeated for sure you will be able to touch the program to make it work)
$ cat pru799.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DELIMITERS " \t\n,.-()&%$\"\'[]{}+-*/;:##|!\\<>=?"
#define LINE_SIZE 1024
#define MAX_WORDS 256
int compare(const char **p, const char **q)
{
return strcmp(*p, *q);
}
int main()
{
char line[LINE_SIZE];
char *words[MAX_WORDS];
int n_words;
while (fgets(line, sizeof line, stdin)) { /* while not eof */
char *p;
int i;
/* first get the words */
n_words = 0;
for (p = strtok(line, DELIMITERS); p; p = strtok(NULL, DELIMITERS)) {
if (strlen(p) == 0) continue; /* word is zero length */
if (n_words >= MAX_WORDS) {
fprintf(stderr, "MAX_WORDS(%d) exceeded\n", MAX_WORDS);
exit(EXIT_FAILURE);
}
words[n_words++] = p;
} /* for */
/* now we have all the words in the array of strings words, sort it */
qsort(words, n_words, sizeof words[0], (int(*)(const void *, const void *))&compare);
/* now print the words */
for (i = 0; i < n_words; i++) {
if (i) { /* all but the first one */
/* don't repeat words */
if (!strcmp(words[i], words[i-1]))
continue;
printf(" "); /* print a space between words */
}
printf("%s", words[i]);
}
printf("\n");
} /* while */
} /* main */

Reading input char by char using realloc in C

I would like to read input char by char and save it as a word into char* array. I don't know how long the input will be, so i want to alloc the memmory dynamicaly. The program ends,when the char is whitespace. How can i do this using realloc?
There is my code:
#include <stdio.h>
int main(void) {
char *word=malloc(1*sizeof(char));
char c;
int numOfChars=0;
c=getchar();
word[0]=c;
numOfChars++;
while((c=getchar())!=' '){
numOfChars++;
realloc(word,numOfChars);
word[numofChars-1]=c;
}
printf("%s", word);
return 0;
}
Example input:Word
Example output:Word
The program can look the following way. Take into account that the input is buffered and filled until a new line character is entered that is also a white space character. And the result word must be zero terminated if you are going to use format specifier %s to output it.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main( void )
{
int c;
size_t n;
char *word;
char *tmp;
n = 0;
word = malloc( n + 1 );
word[n++] = '\0';
printf( "Enter a word: " );
while ( ( c = getchar() ) != EOF && !isspace( c ) && ( tmp = realloc( word, n + 1 ) ) != NULL )
{
word = tmp;
word[n-1] = c;
word[n++] = '\0';
}
printf( "You've entered \"%s\"\n", word );
free( word );
}
The program output might look like
Enter a word: Hello
You've entered "Hello"
In order to explain what I had in mind, i quickly set up this little programm to explain how to use an exponential growth :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INITIAL_CAPACITY 100
#define GROW_FACTOR 1.5
struct string_buffer {
size_t capacity;
size_t length;
char *buffer;
};
typedef struct string_buffer string_buffer_t;
string_buffer_t *sb_init(void);
static void sb_grow(string_buffer_t *sb);
void sb_shrink(string_buffer_t *sb);
char *sb_release(string_buffer_t *sb);
void sb_append_char(string_buffer_t *sb, char c);
char *sb_peek_string(string_buffer_t *sb);
int main(void)
{
string_buffer_t *sb=sb_init();
int c;
while ( (c=getchar())!=' ' && c!='\n' && c!=EOF )
sb_append_char(sb, c);
char *string=sb_release(sb);
printf("string : \"%s\"\nlength : %zu\n", string, strlen(string));
free(string);
return 0;
}
string_buffer_t *sb_init(void)
{
string_buffer_t *new=malloc(sizeof *new);
if (new==NULL) exit(EXIT_FAILURE);
new->capacity=INITIAL_CAPACITY;
new->length=1;
new->buffer=malloc(INITIAL_CAPACITY);
if (new->buffer==NULL) exit(EXIT_FAILURE);
new->buffer[0]=0;
return new;
}
static void sb_grow(string_buffer_t *sb)
{
char *new=realloc(sb->buffer, (size_t) (GROW_FACTOR*sb->capacity));
if (new==NULL) exit(EXIT_FAILURE);
sb->capacity=(size_t) (GROW_FACTOR*sb->capacity);
sb->buffer=new;
}
void sb_shrink(string_buffer_t *sb)
{
char *new=realloc(sb->buffer, sb->length);
if (new==NULL) exit(EXIT_FAILURE);
sb->buffer=new;
}
char *sb_release(string_buffer_t *sb)
{
sb_shrink(sb);
char *string=sb->buffer;
free(sb);
return string;
}
void sb_append_char(string_buffer_t *sb, char c)
{
if (sb->capacity==sb->length) sb_grow(sb);
sb->buffer[sb->length-1]=c;
sb->buffer[sb->length]=0;
sb->length=sb->length+1;
}
This will do
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *ptr;
char *word=malloc(1*sizeof *word);
char c;
int numofChars=0;
printf("Enter string terminated by a space :");
c=getchar();
word[0]=c;
numofChars++;
while((c=getchar())!=' '){
numofChars++;
ptr=realloc(word,numofChars*sizeof *ptr);
if(ptr!=NULL)
{
word=ptr;
word[numofChars-1]=c;
}
}
/* You need to append a null character to make it a valid string */
numofChars++;
ptr=realloc(word,numofChars*sizeof *ptr);
if(ptr!=NULL)
{
word=ptr;
word[numofChars-1]='\0';
}
printf("Word : %s\n", word);
free(word); // Freeing word/
return 0;
}
Well, you may write a function to replace
numofChars++;
ptr=realloc(word,numofChars*sizeof *ptr);
if(ptr!=NULL)
{
word=ptr;
word[numofChars-1]='\0';
}
Note:
It is not suggested that you do
word=realloc(word,numOfChars*sizeof(char));
because in case realloc fails, you have memory leak. So I used ptr here.

How to double a float/integer within a user input string in C?

I'm sorry in advance because I'm fairly new to programming and some things in my code will probably look like utter nonsense! I'm not entirely sure if I'm using atoi right.
I'm trying to create a program that splits a user input sentence into single words and doubles the number(float/integer) if a user inputs one.
For example, I have 3 cats would come out as:
I
have
6
cats
My program right now is able to split the sentence, but I can't get the integer to double. Can anyone help me with this?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char sentence[100];
printf("Enter a sentence to split: ");
scanf("%[^\n]s", sentence);
char *pch;
int y;
y = atoi(sentence);
printf("After splitting:\n", sentence);
pch = strtok(sentence," ");
while (pch != NULL) {
printf("%s\n", pch);
pch = strtok(NULL, " ");
}
system("PAUSE");
}
And my output so far:
Enter a sentence to split: Hi, I have 7 cats.
After splitting:
Hi,
I
have
7
cats.
Press any key to continue . . .
Here is a simpler version with a test for all digit numbers:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char sentence[100];
char *pch;
printf("Enter a sentence to split: ");
if (!fgets(sentence, sizeof sentence, stdin))
return 1;
printf("After splitting:\n");
for (pch = strtok(sentence, " \n"); pch != NULL; pch = strtok(NULL, " \n")) {
if (pch[strspn(pch, "0123456789")] == '\0') {
printf("%d\n", atoi(pch) * 2);
} else {
printf("%s\n", pch);
}
}
system("PAUSE");
return 0;
}
If you want to parse floating point numbers too, you could use this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(void) {
char sentence[100];
char *pch, *pend;
double value;
printf("Enter a sentence to split: ");
if (!fgets(sentence, sizeof sentence, stdin))
return 1;
printf("After splitting:\n");
for (pch = strtok(sentence, " \n"); pch != NULL; pch = strtok(NULL, " \n")) {
value = strtod(pch, &pend);
if (*pend == '\0' && isfinite(value)) {
printf("%g\n", value * 2);
} else {
printf("%s\n", pch);
}
}
system("PAUSE");
return 0;
}
Note the test for isfinite() to avoid recognizing inf and nan as numbers.
NOTE: isfinite is part of C99, it is not supported by VisualStudio 12, but more recent versions do support it. For this older version, use _finite() defined in <float.h>.
Here is a working example, even if it's not really precise. Basically, we need to find out whether our current string is a number or not. In this case, I just tried to get the first element of the current string, and tried to determine if it's numeric or not.
Of course, if you want to be really sure, we need to iterate the string and check every char, if it is a number or not.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char sentence[100];
printf("Enter a sentence to split: ");
scanf("%[^\n]s", sentence);
char * pch;
int y;
y = atoi(sentence);
printf("After splitting:\n", sentence);
pch = strtok (sentence," ");
while (pch != NULL)
{
if(isdigit(pch[0]))
{
int number = atoi(pch);
number *=2;
printf("%d\n",number);
pch = strtok (NULL, " ");
continue;
}
printf("%s\n",pch);
pch = strtok (NULL, " ");
}
system("PAUSE");
}
For the split part I would recommend this version, it is easier to understand (considering that you've learned the for way of working). It does the same thing, but helps you organize your code.
char *p;
int i;
for(p = strtok(sentence, " "); p != NULL; p = strtok(NULL, " "))
{
int isNumber = 1;
for(i = 0; i < strlen(p); i ++)
{
if(!isDigit(p[i])
{
isNumber = 0;
break;
}
}
if(isNumber == 1)
{
int number = atoi(pch);
number *= 2;
printf("%d\n", number);
}
else
{
printf("%s\n", p);
}
}
For the number, I would recommend using the atoi function. Here you have a good reference.
To solve your problem, first of all, you need to check every single word you get. For example: You take it word by word and see if the "word" contains ONLY digits. If it contains only digits, you can use atoi to convert it to a number, multiply it by 2 and print the result.
On the other hand, if you find a char that is NOT a digit, you have letters or any other characters in your word, so it is not a word so you simply print that as it is.
Here's another (more compact) answer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int is_numeric(char *s)
{
int i = 0;
while (s[i] != '\0') {
if (!isdigit(s[i]))
return 0;
++i;
}
return 1;
}
int main()
{
char sentence[255];
char *pch;
printf("Enter a sentence to split: ");
if (!fgets(sentence, sizeof(sentence), stdin)) {
return 1;
}
sentence[strcspn(sentence, "\n\r")] = 0; /* Strip newline */
pch = strtok(sentence, " ");
while (pch != NULL) {
if (atoi(pch)) {
printf("%d\n", 2 * atoi(pch));
} else {
printf("%s\n", pch);
}
pch = strtok(NULL, " ");
}
return 0;
/* system("PAUSE"); */
}
The key is that atoi will return 0 for a non-numeric argument.

Tokenized string of char to ints using atoi

I am trying to take user input: (1 345 44 23) and make it into a tokenized char string then into ints. Surprisingly I could not find much help for what I would think would be a common task.
Any ideas how to convert the char string into an in string using tokens?
My program crashes when it gets to the conversion (after the tokenization [I realize this is not a word]).
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define StrSZE 81
void strInput (char str[], int maxChars);
void custatoi(char * tokenArray[], int * data, int numOfTok);
int main(int argc, char *argv[])
{
char str[StrSZE];
char* tokenArray;
int maxChars=StrSZE-1, cont=1, numOfToken=0, i=0;
int* data;
strInput(str, maxChars);
tokenArray = strtok(str, " \t");
while (tokenArray)
{
printf("token: %s\n", tokenArray);
tokenArray = strtok(NULL, " \t");
numOfToken++;
}
data = (int *) malloc(numOfToken * sizeof(int));
custatoi(tokenArray, data, numOfToken);
system("PAUSE");
return 0;
}
void strInput (char str[], int maxChars)
{
char garbage;
int k=0;
str[0]='\0';
printf("Please type a string of whole numbers (intigers).\n\n");
while ((k<80) && ((str[k] = getchar()) != '\n'))
k++;
/* Clears the keyboard buffer. */
if (k==80)
while((garbage = getchar()) != '\n')
;
/* Place null at the end of the line read in from user */
str[k]='\0';
printf("str after input is: %s\n\n", str);
}
void custatoi(char * tokenArray[], int * data, int numOfTok)
{
int i;
for (i=0; i < numOfTok; i++)
data[i] = atoi(tokenArray[i]);
}
I corrected the errors in yours code: There was some mistakes in main(), tokenArray data type was not correct.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define StrSZE 81
void strInput (char str[], int maxChars);
void custatoi(char* tokenArray[], int * data, int numOfTok);
int main(int argc, char *argv[])
{
char str[StrSZE];
int maxChars=StrSZE-1, cont=1, numOfToken=0, i=0;
int* data;
char* tokenArray[50]; // Declared correctly
strInput(str, maxChars);
tokenArray[i] = strtok(str, " \t"); // Also made a change here!
while (tokenArray[i])
{
printf("token: %s\n", tokenArray[i]);
i++;
tokenArray[i] = strtok(NULL, " \t");
numOfToken++;
}
data = (int *) malloc(numOfToken * sizeof(int));
custatoi(tokenArray, data, numOfToken);
printf("data\n");
for(i=0;i<numOfToken;i++){
printf(" %d\n",data[i]);
}
system("PAUSE");
return 0;
}
void strInput (char str[], int maxChars)
{
char garbage;
int k=0;
str[0]='\0';
printf("Please type a string of whole numbers (intigers).\n\n");
while ((k<80) && ((str[k] = getchar()) != '\n'))
k++;
/* Clears the keyboard buffer. */
if (k==80)
while((garbage = getchar()) != '\n')
;
/* Place null at the end of the line read in from user */
str[k]='\0';
printf("str after input is: %s\n\n", str);
}
void custatoi(char* tokenArray[], int * data, int numOfTok)
{
int i;
for (i=0; i < numOfTok; i++)
data[i] = atoi(tokenArray[i]);
}
At the end of the strtok loop, tokenArray will be set to NULL. You then pass it to custatoi, which presumably crashes when it tries to dereference it.
Note that tokenArray is not an array of strings; it's just a single string pointer (or a pointer to an array of characters). If you want to accumulate the tokens into an array, you'll have to create a separate array for that purpose.
The main problem is that custatoi() expects to work with an array of pointers to char, while tokenArray in main() is a mere pointer to char. The original code never collects all pointers to tokens in the input string into an array that custatoi() expects, there isn't such an array in the original code.
Please study the fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define StrSZE 81
void custatoi(char* tokenArray[], int* data, int numOfTok);
int main(void)
{
char str[StrSZE];
char** tokenArray;
int numOfToken = 0, i;
int* data;
//strInput(str, maxChars);
strcpy(str, "1 345 44 23");
tokenArray = malloc(sizeof(char*));
tokenArray[numOfToken] = strtok(str, " \t");
while (tokenArray[numOfToken] != NULL)
{
printf("token: %s\n", tokenArray[numOfToken]);
numOfToken++;
tokenArray = realloc(tokenArray, sizeof(char*) * (numOfToken + 1));
tokenArray[numOfToken] = strtok(NULL, " \t");
}
data = malloc(numOfToken * sizeof(int));
custatoi(tokenArray, data, numOfToken);
for (i = 0; i < numOfToken; i++)
printf("data[%d]=%d\n", i, data[i]);
return 0;
}
void custatoi(char* tokenArray[], int* data, int numOfTok)
{
int i;
for (i=0; i < numOfTok; i++)
data[i] = atoi(tokenArray[i]);
}
Output (idone):
token: 1
token: 345
token: 44
token: 23
data[0]=1
data[1]=345
data[2]=44
data[3]=23

Using strtok in c

I need to use strtok to read in a first and last name and seperate it. How can I store the names where I can use them idependently in two seperate char arrays?
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="test string.";
char * test;
test = strtok (str," ");
while (test != NULL)
{
printf ("%s\n",test);
test= strtok (NULL, " ");
}
return 0;
}
Here is my take at a reasonably simple tokenize helper that
stores results in a dynamically growing array
null-terminating the array
keeps the input string safe (strtok modifies the input string, which is undefined behaviour on a literal char[], at least I think in C99)
To make the code re-entrant, use the non-standard strtok_r
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** tokenize(const char* input)
{
char* str = strdup(input);
int count = 0;
int capacity = 10;
char** result = malloc(capacity*sizeof(*result));
char* tok=strtok(str," ");
while(1)
{
if (count >= capacity)
result = realloc(result, (capacity*=2)*sizeof(*result));
result[count++] = tok? strdup(tok) : tok;
if (!tok) break;
tok=strtok(NULL," ");
}
free(str);
return result;
}
int main ()
{
char** tokens = tokenize("test string.");
char** it;
for(it=tokens; it && *it; ++it)
{
printf("%s\n", *it);
free(*it);
}
free(tokens);
return 0;
}
Here is a strtok-free reimplementation of that (uses strpbrk instead):
char** tokenize(const char* str)
{
int count = 0;
int capacity = 10;
char** result = malloc(capacity*sizeof(*result));
const char* e=str;
if (e) do
{
const char* s=e;
e=strpbrk(s," ");
if (count >= capacity)
result = realloc(result, (capacity*=2)*sizeof(*result));
result[count++] = e? strndup(s, e-s) : strdup(s);
} while (e && *(++e));
if (count >= capacity)
result = realloc(result, (capacity+=1)*sizeof(*result));
result[count++] = 0;
return result;
}
Do you need to store them separately? Two pointers into a modified char array will yield two separate perfectly usable strings.
That is we transform this:
char str[] ="test string.";
Into this:
char str[] ="test\0string.";
^ ^
| |
char *s1 ----- |
char *s2 -----------
.
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="test string.";
char *firstname = strtok(str, " ");
char *lastname = strtok(NULL, " ");
if (!lastname)
lastname = "";
printf("%s, %s\n", lastname, firstname);
return 0;
}
What about using strcpy:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_NAMES 2
int main ()
{
char str[] ="test string.";
char *names[MAX_NAMES] = { 0 };
char *test;
int i = 0;
test = strtok (str," ");
while (test != NULL && i < MAX_NAMES)
{
names[i] = malloc(strlen(test)+1);
strcpy(names[i++], test);
test = strtok (NULL, " ");
}
for(i=0; i<MAX_NAMES; ++i)
{
if(names[i])
{
puts(names[i]);
free(names[i]);
names[i] = 0;
}
}
return 0;
}
It contains much clutter to maintain a complete program and clean its resources, but the main point is to use strcpy to copy each token into its own string.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** split(const char *str, const char *delimiter, size_t *len){
char *text, *p, *first, **array;
int c;
char** ret;
*len = 0;
text=strdup(str);
if(text==NULL) return NULL;
for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
if(c==0) first=p; //first token top
ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
if(ret==NULL){
free(text);
return NULL;
}
strcpy(text, str+(first-text));//skip until top token
array=ret;
for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
*array++=p;
}
*array=NULL;
*len=c;
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
free(array[0]);//for text
free(sa); //for array
}
}
int main(void){
char str[] ="test string.";
char **words;
size_t len=0;
int i;
words = split(str, " \t\r\n,.", &len);
/*
for(char **wk = words; *wk ;wk++){
printf("%s\n", *wk);
}
*/
for(i = 0;i<len;++i){
printf("%s\n", words[i]);
}
free4split(words);
return 0;
}
/* result:
test
string
*/
Copy the results from strtok to a new buffer using a function such as
/*
* Returns a copy of s in freshly allocated memory.
* Exits the process if memory allocation fails.
*/
char *xstrdup(char const *s)
{
char *p = malloc(strlen(s) + 1);
if (p == NULL) {
perror("memory allocation failed");
exit(1);
}
strcpy(p, s);
return p;
}
Don't forget to free the return values when you're done with them.
IMO, you don't need (and probably don't want) to use strtok at all (as in, "for this, or much of anything else"). I think I'd use code something like this:
#include <string.h>
#include <stdlib.h>
static char *make_str(char const *begin, char const *end) {
size_t len = end-begin;
char *ret = malloc(len+1);
if (ret != NULL) {
memcpy(ret, begin, len);
ret[len]='\0';
}
return ret;
}
size_t tokenize(char *tokens[], size_t max, char const *input, char const *delims) {
int i;
char const *start=input, *end=start;
for (i=0; *start && i<max; i++) {
for ( ;NULL!=strchr(delims, *start); ++start)
;
for (end=start; *end && NULL==strchr(delims, *end); ++end)
;
tokens[i] = make_str(start, end);
start = end+1;
}
return i;
}
#ifdef TEST
#define MAX_TOKENS 10
int main() {
char *tokens[MAX_TOKENS];
int i;
size_t num = tokenize(tokens, MAX_TOKENS, "This is a longer input string ", " ");
for (i=0; i<num; i++) {
printf("|%s|\n", tokens[i]);
free(tokens[i]);
}
return 0;
}
#endif
U can do something like this too.
int main ()
{
char str[] ="test string.";
char * temp1;
char * temp2;
temp1 = strtok (str," ");
temp2 = strchr(str, ' ');
if (temp2 != NULL)
temp2++;
printf ("Splitted string :%s, %s\n" , temp1 , temp2);
return
}

Resources