【问题标题】:Implementing Split function in C在 C 中实现拆分函数
【发布时间】:2015-03-21 00:20:22
【问题描述】:

我正在尝试编写一个类似于 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 的第一次调用,因为它会重复第一个单词。还有其他问题吗?如果是这样,您应该描述您遇到的问题。
  • @BinaryJudy i 是静态变量,所以初始化一次,不重复。
  • 我认为add函数没有理由。删除它会使程序更好。
  • @ikh 哎呀,你是对的。我看着“静态”。 i 将递增。
  • 1) int i 在 main 中的多重定义。 2) 由于调用 fgets 后第二行无关紧要,第一个令牌被添加了两次。同样有趣的是,幻数 '65' 应该是 #define'd 并且 fgets 第二个参数应该是 #define 名称或 sizeof 字符串。虽然当前代码永远不会溢出 words[] 数组,但这可能会随着代码的变化而发生。所以 add 函数应该检查这种可能性

标签: c arrays pointers split strtok


【解决方案1】:

删除第一个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]);

【讨论】:

  • 哦,是的。在我把它放在这里之前,我做了一些改变。最后一段代码在另一个函数中,所以忘记改变量名了。
【解决方案2】:

除了删除对add 的第一次调用和i 的重复声明之外,还有一些其他注意事项。虽然使用while 解析令牌并没有错,尤其是strtok,但for 循环很好地处理了初始调用和每个后续调用NULL

同样,虽然 static 声明 add 中的 i 没有任何问题,但将索引作为参数传递给函数可以提供对 main() 中计数的访问。如果您以后决定动态分配/重新分配words,这会增加令牌的确定数量以及灵活性。

虽然在依赖指针上的NULL 测试时使用for 循环无限迭代并没有错,但如果您确实将令牌索引作为参数传递给add,您可以遍历确定范围0 &lt; i &lt; 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?

【讨论】:

  • 我无法理解 for 循环中的“tokenPtr && *tokenPtr”部分。 tokenPtr 检查它是否为 NULL 但 *tokenPtr 是干什么用的?
  • *tokenPtr 确保它没有指向字符串末尾的 null-terminating 字符。 (取决于你传递的分隔符,这会成为一个问题)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 2011-10-27
  • 1970-01-01
  • 2023-01-28
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多