I'm programming a little programm in C wich should count unique words in c.
To do this, i'm having an wordbook to store all found words. Normaly it should only put words inside that aren't already in it but it keeps entering all writen words.
How can i fix this and how can i delete all the empty parts in my wordbook "woerterbuch" ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char lies_wort(char *Text);
char suche_wort(char *wort);
char neues_wort(char *wort);
char *woerterbuch[1000];
int main(void)
{
char Text[1000];
printf("Bitte Text eingeben : \n") ;
fgets (Text, 1000, stdin);
lies_wort(Text);
int i;
for(i=0;i<1000;i++){
printf("woerterbuch :%s\n",woerterbuch[i]);}
}
char lies_wort(char *Text){
char *wort;
int i=1;
wort = strtok(Text, " ,.!?;:");
while(wort != NULL) {
suche_wort(wort);
printf("gefunden %d: %s\n", i++, wort);
wort = strtok(NULL, " ,.!?;:");}
}
char suche_wort(char *wort)
{
int i;
for (i = 0; i>1000; i++){
if (!strcmp(woerterbuch[i],wort)){return 0;}}
neues_wort(wort);
return 0;
}
char neues_wort(char *wort)
{
int i;
for (i=0; i<1000; i++){
if(woerterbuch[i]==0){
woerterbuch[i]=wort;
return 0;}}
}
For Testing this programm is just printing all words in "woerterbuch" so i can check if it's working.
In suche_wort
for (i = 0; i>1000; i++)
It should be
for (i = 0; i<1000; i++)
Your loop is terminating right away everytime.
I believe you have some issues in your code:
Firstly, in this line:
woerterbuch[i]=wort;
Will only overwrite the address of woerterbuch[i], and this will lead to wrong results. Instead you need to allocate space for worterbuch[i], via malloc or strdup.
You can use allocate space for a single pointer like this:
worterbuch[i] = malloc(strlen(wort)+1);
Note: It is always good to check the return from malloc(), and free() these pointers at the end.
Now, since the pointer is pointing somewhere, you can copy stuff into it. You can use strcpy to do this. If you want to skip this copy step, you can just use strdup() instead.
Secondly, instead of globally defining char *woerterbuch[1000];, you can manage this array of pointers in a struct:
typedef struct {
char *woerterbuch[1000];
size_t n;
} worterbuch;
Which will make it easier to manage your array.
Thirdly, you are not checking the return of fgets(). This can return NULL if unsuccessful. You should also check for buffer overflow here.
Lastly, if their are a lot of words in your worterbuch, it might not be efficient to use linear search to check for duplicates. This process is O(N) time on average. Instead, you can use binary search, which is O(logN) on average, therefore much more efficient if n becomes very large.
Here is some code I wrote a while ago which does something similar:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEXTSIZE 1000
typedef struct {
char *dictionary[TEXTSIZE];
size_t numwords;
} dictionary_t;
void read_text(char *text);
void read_words(char *text, dictionary_t *dict);
int search_word(dictionary_t *dict, char *word);
void print_words(dictionary_t *dict);
int str_cmp(const void *a, const void *b);
int main(void) {
dictionary_t dict;
char text[TEXTSIZE];
read_text(text);
read_words(text, &dict);
print_words(&dict);
return 0;
}
void read_text(char *text) {
size_t slen;
printf("Please enter text: \n");
if (fgets(text, TEXTSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading text\n");
exit(EXIT_FAILURE);
}
/* removes '\n' character from fgets(), and checks for overflow */
slen = strlen(text);
if (slen > 0) {
if (text[slen-1] == '\n') {
text[slen-1] = '\0';
} else {
printf("Buffer overflow detected.\n");
exit(EXIT_FAILURE);
}
}
if (!*text) {
printf("No text entered.\n");
exit(EXIT_FAILURE);
}
}
void read_words(char *text, dictionary_t *dict) {
char *word;
const char *delim = " ,.!?;:";
dict->numwords = 0;
word = strtok(text, delim);
while (word != NULL) {
if (search_word(dict, word)) {
/* allocate space for ptr */
dict->dictionary[dict->numwords] = malloc(strlen(word)+1);
if (!dict->dictionary[dict->numwords]) {
printf("Cannot allocate word.\n");
exit(EXIT_FAILURE);
}
/* copy it into array */
strcpy(dict->dictionary[dict->numwords], word);
/* increment count, ready for next word */
dict->numwords++;
}
word = strtok(NULL, delim);
}
}
/* linear searching the word */
int search_word(dictionary_t *dict, char *word) {
size_t i;
for (i = 0; i < dict->numwords; i++) {
if (strcmp(dict->dictionary[i], word) == 0) {
return 0;
}
}
return 1;
}
/* cmp function for sorting dictionary */
int str_cmp(const void *a, const void *b) {
const char **str1 = (const char **)a;
const char **str2 = (const char **)b;
return strcmp(*str1, *str2);
}
void print_words(dictionary_t *dict) {
size_t i;
/* sort using qsort */
qsort(dict->dictionary, dict->numwords, sizeof(*(dict->dictionary)), str_cmp);
printf("\nDictionary:\n");
for (i = 0; i < dict->numwords; i++) {
printf("%s\n", dict->dictionary[i]);
/* freeing memory previosly allocated from malloc() */
free(dict->dictionary[i]);
dict->dictionary[i] = NULL;
}
}
Related
I'm fairly new to C. I'm trying to read a .CSV file, then parse each line, then store the data in a dynamic array of pointers to structs. Unfortunately I've gone wrong somewhere in my implementation which is resulting in an infinite loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct dataSet {
char ID;
char postcode;
int population;
char contact;
double x;
double y;
}data;
int main(int argc, char* argv[]) {
char line[100] = "";
int count = 0;
int each = 0;
data *allData = NULL;
data *temp = NULL;
FILE *file = fopen("dataset.csv", "r");
if (file == NULL)
{
printf("Error! File null");
return 1;
}
while (fgets(line, sizeof line, file))
{
if(NULL == (temp = realloc(allData, sizeof(*allData) * (count + 1))))
{
fprintf(stderr, "realloc problem\n");
fclose(file);
free(allData);
return 0;
}
allData = temp;
if (6 == scanf(line, "%s, %s, %d, %s, %lf, %lf",
&allData[count].ID,
&allData[count].postcode,
&allData[count].population,
&allData[count].contact,
&allData[count].x,
&allData[count].y)) {
count++;
}
else {
printf("Problem with data\n");
}
}
fclose(file);
for (each = 0; each < count; each++)
{
printf("%s, %s, %d, %s, %lf, %lf\n",
&allData[count].ID,
&allData[count].postcode,
&allData[count].population,
&allData[count].contact,
&allData[count].x,
&allData[count].y);
}
free(allData);
return 0;
}
Any help or tips would be greatly appreciated.
[s]scanf() is a nasty function. You don't have enough control once it fails. Problem is: there are too many conditions: the input can be incorrect, or the destination is not large enough. Even reading complete lines with fgets(), and parsing them afterwards, will only allow you to skip complete lines; also: the line buffer is mostly fixed sized, and fgets() could read incomplete lines. A way to keep complete control is to read character-based. This might imply a Finite State machine.
A simpler reader (using a zero-state machine) could be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct omg {
char o;
int m;
char g[11];
};
struct wtf {
unsigned size;
unsigned used;
struct omg *array;
};
#define INITIAL_SIZE 7
struct wtf read_stuff(char *name)
{
FILE *fp;
unsigned icol,irec,len;
char buff[123];
struct wtf this = {0,0,NULL};
fp = fopen(name, "rb" );
if (!fp) return this;
for (icol=irec=len=0; ; ) {
int ch;
if (this.used >= this.size) {
size_t newsize;
struct omg *tmp;
newsize = this.size? this.size*2: INITIAL_SIZE;
fprintf(stderr, "Realloc(%zu)\n", newsize);
tmp = realloc(this.array, sizeof *this.array * newsize);
this.array = tmp;
this.size = newsize;
}
ch = getc(fp);
switch(ch) {
case '\r' : continue;
/* End of field or record: terminate buffer */
#if 0
case ',' :
#else
case '\t' :
#endif
case '\n' :
buff[len] = 0;
break;
case EOF :
goto done;
/* Normal character: assign to buffer
** You may want to report too long fields here
*/
default:
if (len >= sizeof buff -2) continue;
buff[len++] = ch;
continue;
}
/* When we arrive here, we have a new field. Let's process it ...*/
switch (icol) {
case 0: /* Assign first field here from buff[], (dont forget to check len!) */
this.array[this.used].o = buff[0];
break;
case 1: /* Assign second field from buff[], this may need some additional checks
** You may want to avoid sscanf() here ...
*/
sscanf(buff, "%d", &this.array[this.used].m );
break;
case 2: /* Assign third field from buff[] */
if (len >= sizeof this.array[this.used].g)
len = sizeof this.array[this.used].g -1;
memcpy (this.array[this.used].g, buff, len);
this.array[this.used].g[len] = 0;
break;
default: /* Ignore excess fields
** You may want to report hem.
*/
break;
}
/* Do some bookkeeping */
len = 0;
if(ch == '\n') {
/* You may want to check if icol==2, here */
icol=0; irec++; this.used++;
}
else icol++;
}
done:
fclose(fp);
/* You could do a final realloc() here */
return this;
}
int main(int argc, char **argv)
{
struct wtf result;
unsigned idx;
result = read_stuff(argv[1] );
fprintf(stderr, "Result=%u/%u\n", result.used,result.size);
for (idx=0; idx < result.used; idx++) {
printf("%c %d %s\n"
, result.array[idx].o
, result.array[idx].m
, result.array[idx].g);
if (idx >= 10) break;
}
return 0;
}
You ask for tips...
1 - your struct is wrong if your plan was to use dynamic memory. The char members should be pointers to char, ( char * not char ) as shown below. But to reduce complexity, use char arrays instead of forcing dynamic allocation for struct members: i.e. do not use this:
typedef struct dataSet {
char *ID;
char *postcode;
int population;
char *contact;
double x;
double y;
}data;
Rather use this:
typedef struct dataSet {
char ID[80];
char postcode[11];
int population;
char contact[80];
double x;
double y;
}data;
If the lengths are not right, then make them bigger, but this will reduce calls to calloc() and free().
2 - suggested steps:
Count lines in file. (example here). This will essentially open the file, count the lines and close the file.
Use the count to allocate memory for that number of instances of data (i.e. data *records = malloc(sizeof(*records)*countOfLines); )
Open the file again. If file != NULL, then...
Begin to read file line by line in a loop, such as the fgets(...) loop you have.
In this loop, suggest replacing scanf() with a series of calls to strtok() making the appropriate conversion one-by-one. Its a few more lines of code, but is easier in the long run to see what parsing problems you might run into.
The following pseudo code illustrates...
data *record = malloc(CountOfLines*sizeof(*record));
if(record)
{
int i = 0;
while(fgets(line, sizeof line, file))
{
tok = strtok(line, ",");
if(tok)
{ //convert string
strncpy(record[i].ID, tok, sizeof(record[i].ID) - 1);
tok = strtok(NULL, ",");
if(tok)
{//convert string
strncpy(record[i].postcode, tok, sizeof(record[i].postcode) - 1);
tok = strtok(NULL, ",");
if(tok)
{//convert int
record[i].population = atoi(tok);
//and so on ...
I'm building a word counter program. To achieve this, I was thinking about saving the string the user inputted, and using strtok() to split the sentence with space as the delimiter. But first I want to allocate enough memory for each word. Let's say the sentence is "Hello World". I've already dynamically allocated memory for the string itself. Now I want to split Hello World into 2 strings, "Hello" and "World". My goal is to allocate enough memory so that there's not too much empty space but I also don't want to allocate too little space. Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
char *strmalloc(char **string);
char *user_input = NULL;
char *word_array[];
int main(void) {
printf("Enter a sentence to find out the number of words: ");
user_input = strmalloc(&user_input);
return 0;
}
char *strmalloc(char **string) {
char *tmp = NULL;
size_t size = 0, index = 0;
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
if (size <= index) {
size += 1;
tmp = realloc(*string, size);
if (!tmp) {
free(*string);
string = NULL;
break;
}
*string = tmp;
}
(*string)[index++] = ch;
}
return *string;
}
How would I go about doing this? Should I do the splitting first or allocate the space required for the array first?
You can count words without splitting the sentence, here is an example :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
// Change this to change the separator characters
static inline char isSeparator(char ch) { return isspace(ch) || ispunct(ch); }
char * jumpSeparator(char *string) {
while(string[0] && isSeparator(string[0])) string++;
return string;
}
char * findEndOfWord(char *string) {
while (string[0] && !isSeparator(string[0])) string++;
return string;
}
int countWords(char *string) {
char * ptr = jumpSeparator(string);
if (strlen(ptr) == 0) return 0;
int count = 1;
while((ptr = findEndOfWord(ptr)) && ptr[0]) {
ptr = jumpSeparator(ptr);
if (!ptr) break;
count++;
}
return count;
}
int main() {
char * sentence = "This is,a function... to||count words";
int count = countWords(sentence);
printf("%d\n", count); //====> 7
}
EDIT : Reusing the same functions here is another example that allocates substrings dynamically :
int main() {
char * sentence = "This is,a function... to||split words";
int count = countWords(sentence);
char * ptr = sentence, *start, *end;
char ** substrings = malloc(count * sizeof(char *));
int i=0;
while((ptr = jumpSeparator(ptr)) && ptr[0]) {
start = ptr;
ptr = findEndOfWord(ptr);
end = ptr;
int len = end-start;
char * newString = malloc(len + 1);
memcpy(newString, start, len);
newString[len] = 0;
substrings[i++] = newString;
}
// Prints the result
for(int i=0; i<count; i++) printf("%s\n", substrings[i]);
// Frees the allocated memory
for(int i=0; i<count; i++) free(substrings[i]);
free(substrings);
return 0;
}
Output :
This
is
a
function
to
split
words
While adding string to my pointer's array, it is being overwriten by the last one. Could anyone tell me, where's my mistake?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main (){
int ile = 3;
const char * slowa[ile];
for(int j = 0; j < ile; j++){
char string[30];
gets(string);
slowa[j] = string;
printf ("%s dodalem pierwsza\n",string);
}
for (int i = 0; i < ile; i++) {
printf ("%s numer %d\n",slowa[i],i);
}
return 0;
}
The answer is in the following two lines of code:
char string[30];
...
slowa[j] = string;
The assignment sets slowa[j] to the address of the same buffer, without making a copy. Hence, the last thing that you put in the buffer would be referenced by all elements of slowa[] array, up to position of j-1.
In order to fix this problem, make copies before storing values in slowa. You can use non-standard strdup, or use malloc+strcpy:
char string[30];
gets(string);
slowa[j] = malloc(strlen(string)+1);
strcpy(slowa[j], string);
In both cases you need to call free on all elements of slowa[] array to which you have assigned values in order to avoid memory leaks.
You're always pointing to array of chars which is stack variable it's locally allocated only in scope of function, possibly each declaration of string will be on the same address as previous iteration in your loop. You could either instead of using array of chars allocate memory each loop iteration or use array and then using i.e strdup allocate memory for your new string like
slowa[j] = strdup(string) :
As others have said, you need to create copies of the strings, otherwise you set the strings to the same address, and therefore they just overwrite each other.
Additionally, I think using fgets over gets is a much safer approach. This is because gets is very prone to buffer overflow, whereas with fgets, you can easily check for buffer overflow.
This is some code I wrote a while ago which is similar to what you are trying to achieve:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PTRS 3
#define STRLEN 30
int
string_cmp(const void *a, const void *b) {
const char *str1 = *(const char**)a;
const char *str2 = *(const char**)b;
return strcmp(str1, str2);
}
int
main(void) {
char *strings[PTRS];
char string[STRLEN];
int str;
size_t len, i = 0;
while (i < PTRS) {
printf("Enter a string: ");
if (fgets(string, STRLEN, stdin) == NULL) {
fprintf(stderr, "%s\n", "Error reading string");
exit(EXIT_FAILURE);
}
len = strlen(string);
if (string[len-1] == '\n') {
string[len-1] = '\0';
} else {
break;
}
strings[i] = malloc(strlen(string)+1);
if (strings[i] == NULL) {
fprintf(stderr, "%s\n", "Cannot malloc string");
exit(EXIT_FAILURE);
}
strcpy(strings[i], string);
i++;
}
qsort(strings, i, sizeof(*strings), string_cmp);
printf("\nSuccessfully read strings(in sorted order):\n");
for (str = 0; str < i; str++) {
printf("strings[%d] = %s\n", str, strings[str]);
free(strings[str]);
strings[str] = NULL;
}
return 0;
}
I am trying to build a program that uses dynamic allocation to build an array of strings.
After the user finishes to enter the words he wants into the array i want to print the array one word after the other. I am using pointers to pointers, however it doesn't seem to work:
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
char *curr_word;
while (flag)
{
_flushall();
printf("Enter a word:");
gets(buffer);
words = (char**)realloc(words,++count_words*sizeof(char*));
curr_word = (char*)malloc(strlen(buffer) + 1);
words[count_words - 1] = curr_word;
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int j = 0;
for (int i = 0; i < count_words; i++)
{
printf("%s\n", words[i][j]);
}
}
Copy buffer to your malloc'ed block with strcpy
strcpy(curr_word, buffer);
you are discarding the read word since you don't put it anywhere
Don't use gets use fgets instead
fgets(buffer, sizeof(buffer), stdin);
this would prevent a buffer overflow.
This is just the jst which in your case is the 0th character of the word
printf("%s\n", words[i][j]);
change it to
printf("%s\n", words[i]);
turn compiler warnings on, it would tell you about printf expecting a char * and recieving char instead.
Also consider the following:
main() should return int.
You don't need to cast malloc.
Don't overwrite your pointer with realloc, use a temporary pointer and assign it to array on success only. Otherwise if realloc returns NULL you will not be able to free(array) for example.
++count_words
words = realloc(words,count_words*sizeof(char*));
words[count_words-1] = malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
Later print the array
printf("%s\n",words[i]);
realloc() can fail so
char *temp = realloc(words,count_words*sizeof(char*));
if(temp != NULL)
words = temp;
Few other fixes will be
You shouldn't be using gets which is no more a standard. Use fgets() and note that fgets() comes with a newline character
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL,ch;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
//char *curr_word;
while (flag)
{
printf("Enter a word:");
fgets(buffer,sizeof(buffer),stdin);
words = (char**)realloc(words,++count_words*sizeof(char*));
words[count_words - 1] = (char*)malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
while((ch = getchar()) != '\n');
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int i;
for (i=0; i < count_words; i++)
{
printf("%s", words[i]);
}
}
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
}