I'm fairly new to C and therefore encountering quite a bit of confusion with using pointers.
I'm trying to extract words from a string of ASCII characters. For instance, if I have the string @@Hello..world>>, I want to get the words "Hello" and "world" out of the string and add them to my linked list.
A word is defined as any sequence of letters, and each word is at most 64 bytes. Also, any character where the function isspace() returns a non-zero value is considered whitespace.
Basically, I'm scanning in the strings from a file using fscanf, then for each string calling my function read_words(char *s) to get the proper words out of the string and add them to my linked list for further use.
Here is my code which seems to be throwing an error that has to do with a pointer.
struct node {
char *val;
struct node *next;
int count;
} *words = NULL;
void read_words(char *s)
{
struct node *tmp;
char word[64+1];
int i, check, wordStarted = 0, count = 0;
for (i = 0; s[i] != '\0'; i++)
{
if ((isspace(s[i]) != 0) || !isalpha(s[i]))
{
if (wordStarted == 1)
{
check = check_list(word);
if (check != 1) {
word[count] = '\0';
tmp = malloc(sizeof(struct node));
tmp->val = word;
tmp->count = 1;
tmp->next = words;
words = tmp;
}
count = 0;
wordStarted = 0;
}
}
else
{
word[count++] = s[i];
wordStarted = 1;
}
}
}
Any help with this would be much appreciated!
Thank you!
You'll want to tokenize the string instead of implementing your own algorithm and append the parts to your linked list. Use strtok
(ref).
From the link above.. example:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
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;
}
Output:
Splitting string "- This, a sample string." into tokens: This a sample string
Better solution for The ANSI C.
Usage strtok() it is not always good:
Try next and read comments for details:
#include <stdio.h> // printf
#include <string.h> // strlen, strncpy
#include <ctype.h> // isalnum
#include <stdlib.h> // malloc, calloc
/*
A logical type
*/
typedef enum {
false,
true,
} bool;
/*
A Struct for hold 2D-array with count items
*/
typedef struct _ListWithLength {
char **list;
size_t length;
} ListWithLength;
/*
Parse a text and return pointer to a ListWithLength words and count it
*/
ListWithLength* getWords(char *text) {
// a variable for count words
int count = 0;
// keep length of the text
size_t text_len = strlen(text);
// a flag indicating the a beginning of a word
bool new_word = false;
// an index of a start found a word
int index_start_word = 0;
// 2D-array for found word
// it will be same memory size as the original text
char **words = malloc(text_len * sizeof(char));
for (int i = 0; i <= text_len; ++i) {
// if found ascii letter or digits and new no traced early
// keep index of beginning a new word
// and change the flag
if (isalnum(text[i]) != 0) {
if (new_word == false) {
new_word = true;
index_start_word = i;
}
// if it is not ascii letter or digits and a word traced early
// it means the word ended
} else {
if (new_word == true) {
// allocate a memory for a new word in the array of words
words[count] = malloc(i - index_start_word * sizeof(char) + 1);
// copy the found word from the text by indexes
strncpy(words[count], text + index_start_word, i - index_start_word);
// change the flag
new_word = false;
// increase the counter of words
count++;
}
};
}
// bind the found words and it count to a structure and return it
ListWithLength *list_with_length = malloc(sizeof(ListWithLength));
list_with_length->length = count;
list_with_length->list = words;
return list_with_length;
}
/*
Print information of a ListWithLength
*/
void printListWithLength(ListWithLength *list_with_length) {
printf("Total items: %li\n", list_with_length->length);
puts("----------------------");
for (int i = 0; i < list_with_length->length; ++i) {
printf("%d. %s\n", i + 1, list_with_length->list[i]);
}
}
int main(int argc, char const *argv[])
{
char c_keywords[300] = "auto else long switch\
break\t enum \t register typedef\
\ncase extern, return union\
?char float. short unsigned\
const !for signed void\
continue goto sizeof volatile\
.default???? if static while\
do int struct,,,, _Packed\
double.......";
ListWithLength *list_with_length = getWords(c_keywords);
printListWithLength(list_with_length);
return 0;
}
Compile and see result:
$ gcc -Wall -ansi -std=c11 -o main main.c
$ ./main
Total items: 33
----------------------
1. auto
2. else
3. long
4. switch
5. break
6. enum
7. register
8. typedef
9. case
10. extern
11. return
12. union
13. char
14. float
15. short
16. unsigned
17. const
18. for
19. signed
20. void
21. continue
22. goto
23. sizeof
24. volatile
25. default
26. if
27. static
28. while
29. do
30. int
31. struct
32. Packed
33. double
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With