在 C 中实现 Split 函数
Implementing Split function in C
我正在尝试编写一个类似于 Java 中的 split
的 C 函数。当我在 main 做我做的事情时,而不是添加功能,它工作得很好。但是我不明白为什么它不能与添加功能一起使用。
#include <stdio.h>
#include <string.h>
char *words[50] = { NULL };
void add(const char *word) {
static int i = 0;
words[i] = word;
i++;
}
int main( void )
{
char string[65];
char *tokenPtr;
fgets(string, 65, stdin);
tokenPtr = strtok( string, " " );
add(tokenPtr);
int i = 0;
while ( tokenPtr != NULL ) {
add(tokenPtr);
tokenPtr = strtok( NULL, " " );
}
int i;
for(i = 0; words[i] != NULL; i++)
puts(words[i]);
return 0;
}
这只是我实际代码的一小部分,出于某些原因我需要在另一个函数中执行它。
删除第一个 add
呼叫。
fgets(string, 65, stdin);
tokenPtr = strtok( string, " " );
// add(tokenPtr); // remove
因为您将在下一个 while
循环中添加第一个标记。
此外,您应该删除 int i
的重复项。
// int i; // <-- why is it there?
for(i = 0; words[i] != NULL; i++)
puts(words[i]);
除了删除对 add
的第一次调用和 i
的重复声明外,还有一些其他注意事项。虽然使用 while
来解析标记没有任何问题,特别是 strtok
,但 for
循环可以很好地处理初始调用和每个后续调用 NULL
.
类似地,虽然 add
中 i
的 static
声明没有任何问题,但将索引作为参数传递给函数可以提供对 i
中计数的访问=21=]。如果您以后决定 allocate/reallocate words
动态地增加令牌的确定数量以及灵活性。
虽然在指针上依赖 NULL
测试时使用 for
循环无限迭代没有错,但如果您确实将令牌索引作为参数传递给 add
,您可以迭代确定的范围 0 < i < token index
并确保在您拥有 49
令牌的情况下不会尝试读取超出 words
的末尾。 (可以添加测试)
最后,(这只是一个小问题),当声明变量用作正计数器、索引等时,请考虑使用 size_t
而不是 int
。
解决这个问题的方法有很多种,只要正确,没有比这更正确的。综合考虑,对代码稍作修改可能如下所示:
#include <stdio.h>
#include <string.h>
char *words[50] = { NULL };
void add (const char *word, size_t idx) {
words[idx] = word;
}
int main( void )
{
char string[65];
char *tokenPtr;
size_t tokIdx = 0; /* token index */
size_t i = 0; /* use size_t if non-negative counter */
fgets(string, 65, stdin);
for (tokenPtr = strtok (string, " "); tokenPtr && *tokenPtr; tokenPtr = strtok (NULL, " "))
add (tokenPtr, tokIdx++);
for (i = 0; i < tokIdx; i++)
printf (" words[%zu] %s\n", i, words[i]);
return 0;
}
输出
$ echo "how many tokens are in this line eight?" | ./bin/strtokadd
words[0] how
words[1] many
words[2] tokens
words[3] are
words[4] in
words[5] this
words[6] line
words[7] eight?
我正在尝试编写一个类似于 Java 中的 split
的 C 函数。当我在 main 做我做的事情时,而不是添加功能,它工作得很好。但是我不明白为什么它不能与添加功能一起使用。
#include <stdio.h>
#include <string.h>
char *words[50] = { NULL };
void add(const char *word) {
static int i = 0;
words[i] = word;
i++;
}
int main( void )
{
char string[65];
char *tokenPtr;
fgets(string, 65, stdin);
tokenPtr = strtok( string, " " );
add(tokenPtr);
int i = 0;
while ( tokenPtr != NULL ) {
add(tokenPtr);
tokenPtr = strtok( NULL, " " );
}
int i;
for(i = 0; words[i] != NULL; i++)
puts(words[i]);
return 0;
}
这只是我实际代码的一小部分,出于某些原因我需要在另一个函数中执行它。
删除第一个 add
呼叫。
fgets(string, 65, stdin);
tokenPtr = strtok( string, " " );
// add(tokenPtr); // remove
因为您将在下一个 while
循环中添加第一个标记。
此外,您应该删除 int i
的重复项。
// int i; // <-- why is it there?
for(i = 0; words[i] != NULL; i++)
puts(words[i]);
除了删除对 add
的第一次调用和 i
的重复声明外,还有一些其他注意事项。虽然使用 while
来解析标记没有任何问题,特别是 strtok
,但 for
循环可以很好地处理初始调用和每个后续调用 NULL
.
类似地,虽然 add
中 i
的 static
声明没有任何问题,但将索引作为参数传递给函数可以提供对 i
中计数的访问=21=]。如果您以后决定 allocate/reallocate words
动态地增加令牌的确定数量以及灵活性。
虽然在指针上依赖 NULL
测试时使用 for
循环无限迭代没有错,但如果您确实将令牌索引作为参数传递给 add
,您可以迭代确定的范围 0 < i < token index
并确保在您拥有 49
令牌的情况下不会尝试读取超出 words
的末尾。 (可以添加测试)
最后,(这只是一个小问题),当声明变量用作正计数器、索引等时,请考虑使用 size_t
而不是 int
。
解决这个问题的方法有很多种,只要正确,没有比这更正确的。综合考虑,对代码稍作修改可能如下所示:
#include <stdio.h>
#include <string.h>
char *words[50] = { NULL };
void add (const char *word, size_t idx) {
words[idx] = word;
}
int main( void )
{
char string[65];
char *tokenPtr;
size_t tokIdx = 0; /* token index */
size_t i = 0; /* use size_t if non-negative counter */
fgets(string, 65, stdin);
for (tokenPtr = strtok (string, " "); tokenPtr && *tokenPtr; tokenPtr = strtok (NULL, " "))
add (tokenPtr, tokIdx++);
for (i = 0; i < tokIdx; i++)
printf (" words[%zu] %s\n", i, words[i]);
return 0;
}
输出
$ echo "how many tokens are in this line eight?" | ./bin/strtokadd
words[0] how
words[1] many
words[2] tokens
words[3] are
words[4] in
words[5] this
words[6] line
words[7] eight?