forked from portfoliocourses/c-example-code
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsplit.c
155 lines (133 loc) · 5.19 KB
/
split.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*******************************************************************************
*
* Program: Split Function
*
* Description: A split function that splits a string into an array of substrings
* based on separator characters using C. This function is very similar to the
* split function in Python and JavaScript.
*
* YouTube Lesson: https://www.youtube.com/watch?v=GpATOKdvgLs
*
* Author: Kevin Browne @ https://portfoliocourses.com
*
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char **split(char *string, char *seperators, int *count);
int main()
{
// test the function
char s[] = "To be, or not to be, that is the question.";
int count_strings = 0;
char **split_strings = split(s, " ,.", &count_strings);
// print out the substrings, which should be each word of the sentence above
for (int i = 0; i < count_strings; i++)
printf("%s\n", split_strings[i]);
// free the dynamically allocated space for each string
for (int i = 0; i < count_strings; i++)
free(split_strings[i]);
// free the dynamically allocated space for the array of pointers to strings
free(split_strings);
return 0;
}
// Separates the string into substrings, splitting the string into substrings
// based on the separator characters (i.e separators). The function returns an
// array of pointers to strings, dynamically allocated on the heap, and it
// effectively "returns" the number of these strings via pass-by-pointer using
// the parameter count.
char **split(char *string, char *seperators, int *count)
{
// get the length of the string
int len = strlen(string);
// use count to keep a count of the number of substrings
*count = 0;
// We make one pass of the string to first determine how many substrings
// we'll need to create, so we can allocate space for a large enough array
// of pointer to strings. The variable i will keep track of our current
// index in the string
int i = 0;
while (i < len)
{
// skip over the next group of separator characters
while (i < len)
{
// keep incrementing i until the character at index i is NOT found in the
// separators array, indicating we've reached the next substring to create
if (strchr(seperators, string[i]) == NULL)
break;
i++;
}
// skip over the next group of substring (i.e. non-separator characters),
// we'll use old_i to verify that we actually did detect non-separator
// characters (perhaps we're at the end of the string)
int old_i = i;
while (i < len)
{
// increment i until the character at index i IS found in the separators
// array, indicating we've reached the next group of separator
// character(s)
if (strchr(seperators, string[i]) != NULL)
break;
i++;
}
// if we did encounter non-seperator characters, increase the count of
// substrings that will need to be created
if (i > old_i) *count = *count + 1;
}
// allocate space for a dynamically allocated array of *count* number of
// pointers to strings
char **strings = malloc(sizeof(char *) * *count);
// we'll make another pass of the string using more or less the same logic as
// above, but this time we'll dynamically allocate space for each substring
// and store the substring into this space
i = 0;
// buffer will temporarily store each substring, string_index will keep track
// of the current index we are storing the next substring into using the
// dynamically allocated array above
char buffer[16384];
int string_index = 0;
while (i < len)
{
// skip through the next group of separators, exactly the same as above
while (i < len)
{
if (strchr(seperators, string[i]) == NULL)
break;
i++;
}
// store the next substring into the buffer char array, use j to keep
// track of the index in the buffer array to store the next char
int j = 0;
while (i < len)
{
if (strchr(seperators, string[i]) != NULL)
break;
buffer[j] = string[i];
i++;
j++;
}
// only copy the substring into the array of substrings if we actually
// read in characters with the above loop... it's possible we won't if
// the string ends with a group of separator characters!
if (j > 0)
{
// add a null terminator on to the end of buffer to terminate the string
buffer[j] = '\0';
// calculate how much space to allocate... we need to be able to store
// the length of buffer (including a null terminator) number of characters
int to_allocate = sizeof(char) *
(strlen(buffer) + 1);
// allocate enough space using malloc, store the pointer into the strings
// array of pointers at hte current string_index
strings[string_index] = malloc(to_allocate);
// copy the buffer into this dynamically allocated space
strcpy(strings[string_index], buffer);
// advance string_index so we store the next string at the next index in
// the strings array
string_index++;
}
}
// return our array of strings
return strings;
}