如果我们有多个分隔符,如何提取字符串?

时间:2014-04-03 04:40:17

标签: c string

如果我有这段代码:

int main ()
{
char *sentence = "Wisteria#Tunnel";
char stringA[50];
char stringB[50];
char stringC[50];
pDelim = strstr(sentence,"#");
*pDelim = '\0';
strcpy(stringA,sentence);
strcpy(stringB,(pDelim+1));
    return(0);
}

运行后,stringA将是" Wisteria"而stringB将是"隧道",对吗?

如果:

char *sentence = "Wisteria#Tunnel#Japan";

如何将其提取为三部分,stringA将是" Wisteria" ,stringB将是"隧道" stringC将是"日本"

感谢。

3 个答案:

答案 0 :(得分:1)

标准字符串函数strtokstrstrstrchr都可以使用,前提是周围的代码也是正确的。也就是说,如果要在同一源字符串中多次搜索,则需要在源的开头指向一个Start-at指针,并在每次(成功!)搜索之后将其更新为之后你的分隔符。默认情况下,strtok可以正常工作 - 单个字符分隔符。您可以在任何好的参考资料中阅读strtok(我不打算为您查找)。

事实上,这是一个如此简单的操作,我刚才做了这个。除了vanilla strtok之外,我的strcpyUpTo接受任何分隔符字符串。我可以先使用strstr进行检查,但我更喜欢立即复制。复制循环内的strncmpstrlen可能效率低下;然而,一般来说,这些低级别的字符串操作应该非常快。

#include <stdio.h>
#include <string.h>

char *strcpyUpTo (const char *source, char *dest, const char *delim)
{
    while (*source && strncmp (source, delim, strlen(delim)))
        *dest++ = *source++;
    *dest = 0;

    if (*source)
        return (char *)(source+strlen(delim));
    return (char *)source;
}

int main (void)
{
    char *sentence = "Wisteria#any#Tunnel#any#Japan";
    char stringA[50];
    char stringB[50];
    char stringC[50];
    char *pDelim;

    pDelim = strcpyUpTo (sentence, stringA, "#any#");
    pDelim = strcpyUpTo (pDelim, stringB, "#any#");
    pDelim = strcpyUpTo (pDelim, stringC, "#any#");

    printf ("stringA = \"%s\"\n", stringA);
    printf ("stringB = \"%s\"\n", stringB);
    printf ("stringC = \"%s\"\n", stringC);

    return 0;
}

加成

对于未知数量的子字符串,您可以使用while循环,如下所示。 (对于生产代码,它需要进行各种检查。为了简洁起见,为了清晰起见,并将其作为读者的练习。)这基本上就是你如何使用strtok

char resultList[10][50];
int i, n_result;

pDelim = sentence;
n_result = 0;
do
{
    pDelim = strcpyUpTo (pDelim, resultList[n_result], "#any#");
    n_result++;
} while (*pDelim && n_result < 10);

printf ("number of strings: %d\n", n_result);
for (i=0; i<n_result; i++)
    printf ("string %d = \"%s\"\n", i, resultList[i]);

答案 1 :(得分:0)

对于更复杂的事情,使用strtok是可行的方法,但您可以使用strstr。我没有费心将生成的子串复制到新的字符串,只是将它们打印到控制台。如果您想保存它们,可以将所有b指针保存到数组中,或使用strcpy进行复制。

#include <stdio.h>
#include <string.h>


int main ()
{
  char *sentence = "Wisteria#Tunnel#foo#bar";
  char* b = sentence;
  while(1) {
    char*a = strstr(b,"#");
    if (a) *a = 0;
    printf("%s\n",b);
    if (!a) break;
    b = a+1;
  }
}

输出

Wisteria Tunnel foo bar

答案 2 :(得分:0)

#include <stdio.h>

int main (){
    char *sentence = "Wisteria#Tunnel#Japan";
    char stringA[50];
    char stringB[50];
    char stringC[50];
    sscanf(sentence, "%49[^#]#%49[^#]#%49[^#]", stringA, stringB, stringC);
    puts(stringA);puts(stringB);puts(stringC);
    return(0);
}

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

char **split(const char *str, char delimiter){
    char **words = malloc(sizeof(char*));
    const char *p = str;
    int wc = 0;

    for(;;){
        char *pos;
        int len;
        if((pos = strchr(p, delimiter))!=NULL){
            len = pos - p;
            words[wc] = malloc(len+1);
            strncpy(words[wc], p, len);
            words[wc][len] = '\0';
            words=realloc(words, (++wc+1)*sizeof(char*));
        } else {
            pos = strchr(p, '\0');
            len = pos - p + 1;
            words[wc] = malloc(len);
            strncpy(words[wc], p, len);
            words=realloc(words, (++wc+1)*sizeof(char*));
            words[wc] = NULL;//End Mark
            break;
        }
        p = pos + 1;
    }
    return words;
}

int main (){
    char **sentences = split("Wisteria#Tunnel#Japan", '#');
    int i;
    for(i=0;sentences[i];++i){
        puts(sentences[i]);
        free(sentences[i]);
    }
    free(sentences[i]);
    free(sentences);

    return(0);
}