C语言中的拆分和连接字符串

时间:2011-11-14 06:58:43

标签: c

我在大学里学过C但是已经好几年没用了。最近我开始研究一种使用C作为编程语言的工具。现在我坚持一些非常基本的功能。其中有如何使用分隔符拆分和连接字符串? (我非常想念Python,甚至是Java或C#!)

下面是我为分割字符串而创建的函数,但它似乎无法正常工作。此外,即使此功能有效,分隔符也只能是单个字符。如何使用字符串作为分隔符?

有人可以提供一些帮助吗?

理想情况下,我希望有两个功能:

//  Split a string into a string array
char** fSplitStr(char *str, const char *delimiter);

//  Join the elements of a string array to a single string
char* fJoinStr(char **str, const char *delimiter);

谢谢,

阿伦

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char** fSplitStr(char *str, const char *delimiters)
{
    char * token; 
    char **tokenArray;
    int count=0;
    token = (char *)strtok(str, delimiters); // Get the first token
    tokenArray = (char**)malloc(1 * sizeof(char*));

    if (!token) {       
        return tokenArray;  
} 

    while (token != NULL ) { // While valid tokens are returned     
        tokenArray[count] = (char*)malloc(sizeof(token));
        tokenArray[count] = token;
        printf ("%s", tokenArray[count]);    
        count++;
        tokenArray = (char **)realloc(tokenArray, sizeof(char *) * count);      
        token = (char *)strtok(NULL, delimiters); // Get the next token     
} 
    return tokenArray;
}

int main (void)
{
    char str[] = "Split_The_String";
    char ** splitArray = fSplitStr(str,"_");
    printf ("%s", splitArray[0]);
    printf ("%s", splitArray[1]);
    printf ("%s", splitArray[2]);
    return 0;
}

答案:(感谢Moshbear,Joachim和sarnold):

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char** fStrSplit(char *str, const char *delimiters)
{
    char * token; 
    char **tokenArray;
    int count=0;
    token = (char *)strtok(str, delimiters); // Get the first token
    tokenArray = (char**)malloc(1 * sizeof(char*));
    tokenArray[0] = NULL;
    if (!token) {       
        return tokenArray;  
    } 
    while (token != NULL) { // While valid tokens are returned
        tokenArray[count] = (char*)strdup(token);
        //printf ("%s", tokenArray[count]);
        count++;
        tokenArray = (char **)realloc(tokenArray, sizeof(char *) * (count + 1));
        token = (char *)strtok(NULL, delimiters); // Get the next token
    }
    tokenArray[count] = NULL;  /* Terminate the array */
    return tokenArray;
}

char* fStrJoin(char **str, const char *delimiters)
{
    char *joinedStr;
    int i = 1;
    joinedStr = realloc(NULL, strlen(str[0])+1);
    strcpy(joinedStr, str[0]);
    if (str[0] == NULL){
        return joinedStr;
    }
    while (str[i] !=NULL){
        joinedStr = (char*)realloc(joinedStr, strlen(joinedStr) + strlen(str[i]) + strlen(delimiters) + 1);
        strcat(joinedStr, delimiters);
        strcat(joinedStr, str[i]);
        i++;
    }
    return joinedStr;
}


int main (void)
{
    char str[] = "Split_The_String";
    char ** splitArray = (char **)fStrSplit(str,"_");
    char * joinedStr;
    int i=0;
    while (splitArray[i]!=NULL) {
        printf ("%s", splitArray[i]);
        i++;
    }
    joinedStr = fStrJoin(splitArray, "-");
    printf ("%s", joinedStr);
    return 0;
}

3 个答案:

答案 0 :(得分:7)

使用strpbrk代替strtok,因为strtok有两个弱点:

  • 它不是可重入的(即线程安全的)
  • 修改字符串

要加入,请使用strncat加入,realloc调整大小。 操作顺序非常重要。

在执行realloc;strncat循环之前,将目标字符串的第0个元素设置为'\0',以便strncat不会导致未定义的行为。

答案 1 :(得分:3)

对于初学者,请勿使用sizeof来获取字符串的长度。 strlen是要使用的功能。在这种情况下,strdup会更好。

并且您实际上并不复制strtok返回的字符串,而是复制指针。改变你的循环:

while (token != NULL) { // While valid tokens are returned
    tokenArray[count] = strdup(token);
    printf ("%s", tokenArray[count]);
    count++;
    tokenArray = (char **)realloc(tokenArray, sizeof(char *) * count);
    token = (char *)strtok(NULL, delimiters); // Get the next token
}
tokenArray[count] = NULL;  /* Terminate the array */

此外,不要忘记在完成数组时释放数组中的条目,以及数组本身。

修改fSplitStr开头,等待分配tokenArray,直到您检查token不是NULL为止,如果token NULL为什么不返回NULL

答案 2 :(得分:1)

我不确定最好的解决方案,但我确实有一些注意事项:

token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));

if (!token) {       
    return tokenArray;  
}

此时,如果您无法在字符串中找到任何标记,则返回指向“数组”的指针,该数组足以容纳单个字符指针。它是未初始化的,因此以任何方式使用这个数组的内容都不是一个好主意。 C几乎从未将内存初始化为0x00。 (calloc(3)会为你做到这一点,但是因为你需要覆盖每个元素,所以似乎不值得切换到calloc(3)。)

此外,(char **)来电之前的malloc(3)案例向我表明,您可能已经忘记了#include <stdlib.h>正确原型malloc(3)。 (演员在大约1989年之前是必要的。)

请注意,您的while() { }循环正在将指针设置为tokenArray元素的原始输入字符串的部分。 (这是moshbear在他的回答中提到的 cons 之一 - 虽然它并不总是一个弱点。)如果你改变tokenArray[1][1]='H',那么你的原始输入字符串也是更改。 (除了用ASCII NUL字符替换每个分隔符之外。)