C 将不同字符类型的字符串拆分为单独的字符串

C 将不同字符类型的字符串拆分为单独的字符串,c,C,有没有办法将不同类型字符的字符串拆分为单独的字符串 char str[] ="(I) 44like22 .cookies. ,This, /is\ ?tricky?"; 像这样的 ( I ) 44 like 22 . cookies . , This , / is \ ? tricky ? 奥拉夫 char *a; char *strings[100] = {0}; int k = 0; a = strtok (line_storage," "); k = 0; while (a != NU

有没有办法将不同类型字符的字符串拆分为单独的字符串

char str[] ="(I) 44like22 .cookies. ,This, /is\ ?tricky?";
像这样的

( I ) 44 like 22 . cookies . , This , / is \ ? tricky ?
奥拉夫

char *a;
char *strings[100] = {0};
int k = 0;
a = strtok (line_storage," ");
k = 0;
while (a != NULL)
{
    strings[k] = malloc(strlen(a)+1);
    strcpy(strings[l], a);
    a = strtok (NULL," ");
    k++;
}
修改了乔纳森·莱夫勒,但不是很好。我正在试图找到一种方法,每次在文件的每一行上运行
fgets
时,都可以重用它

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

int main(void)
{
    char  str[] = "(I) 44like22 .cookies. ,This, /is\\ ?tricky?";
    char *s = (char *)str;
    char  str1[] = "(I) 44like22 .cookies. ,This, /is\\ ?tricky? 1122Keep.. (giving) 13me09 %more% 1magic1";

    char   out[2 * sizeof(str)];
    char  *ptr[sizeof(str)];
    char **p = ptr;
    char  *o = out;
    int    n = 0;
    int    i = 0;


    int c = 0;


    printf("Whole string: <<%s>>\n", str);

    while ((c = (unsigned char)*s++) != '\0')
    {
        if (isdigit(c))
        {
            *p++ = o;
            *o++ = c;
            while (isdigit((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (isalpha(c))
        {
            *p++ = o;
            *o++ = c;
            while (isalpha((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (ispunct(c))
        {
            printf("o is %d \n", *o);
            printf("c is %d \n", c);
            *p++ = o;
            *o++ = c;
            while (ispunct((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (!isspace(c))
        {
            printf("Hmmm: don't know how to classify %d (%c)\n", c, c);
        }
    }

    for (i = 0; i < n; i++)
    {
        printf("Fragment[%2d] = %s\n", i, ptr[i]);
    }

    free(p);
    free(o);
    //free(out);
    //free(ptr);

    s = str1;
    out[2 * sizeof(str1)];
    *ptr[sizeof(str1)];
    **p = (char **)ptr;
    *o = out;
    n = 0;
    i = 0;

    printf("Whole string: <<%s>>\n", str);

    while ((c = (unsigned char)*s++) != '\0')
    {
        if (isdigit(c))
        {
            *p++ = o;
            *o++ = c;
            while (isdigit((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (isalpha(c))
        {
            *p++ = o;
            *o++ = c;
            while (isalpha((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (ispunct(c))
        {
            printf("o is %d \n", *o);
            printf("c is %d \n", c);
            *p++ = o;
            *o++ = c;
            while (ispunct((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (!isspace(c))
        {
            printf("Hmmm: don't know how to classify %d (%c)\n", c, c);
        }
    }

    return 0;
}

我对这段代码并不完全满意,但它相对来说比较干净,似乎可以胜任这项工作

splitit.c
样本运行:

Whole string: <<(I) 44like22 .cookies. ,This, /is\ ?tricky?>>
Fragment[ 0] = (
Fragment[ 1] = I
Fragment[ 2] = )
Fragment[ 3] = 44
Fragment[ 4] = like
Fragment[ 5] = 22
Fragment[ 6] = .
Fragment[ 7] = cookies
Fragment[ 8] = .
Fragment[ 9] = ,
Fragment[10] = This
Fragment[11] = ,
Fragment[12] = /
Fragment[13] = is
Fragment[14] = \
Fragment[15] = ?
Fragment[16] = tricky
Fragment[17] = ?
$ ./splitit
Whole string: <<(I) 44like22 .cookies. ,This, /is\ ?tricky?>>
Fragment[ 0] = (
Fragment[ 1] = I
Fragment[ 2] = )
Fragment[ 3] = 44
Fragment[ 4] = like
Fragment[ 5] = 22
Fragment[ 6] = .
Fragment[ 7] = cookies
Fragment[ 8] = .
Fragment[ 9] = ,
Fragment[10] = This
Fragment[11] = ,
Fragment[12] = /
Fragment[13] = is
Fragment[14] = \
Fragment[15] = ?
Fragment[16] = tricky
Fragment[17] = ?
Californian(*) Avocados--a joyous fruit--are "wonderful!" to eat.
Whole string: <<Californian(*) Avocados--a joyous fruit--are "wonderful!" to eat.
>>
Fragment[ 0] = Californian
Fragment[ 1] = (*)
Fragment[ 2] = Avocados
Fragment[ 3] = --
Fragment[ 4] = a
Fragment[ 5] = joyous
Fragment[ 6] = fruit
Fragment[ 7] = --
Fragment[ 8] = are
Fragment[ 9] = "
Fragment[10] = wonderful
Fragment[11] = !"
Fragment[12] = to
Fragment[13] = eat
Fragment[14] = .
$
样本输出:

Whole string: <<(I) 44like22 .cookies. ,This, /is\ ?tricky?
But (as he said, "Isn't it delicous fun!"), he vanished.>>
Fragment[ 0] = (
Fragment[ 1] = I
Fragment[ 2] = )
Fragment[ 3] = 44
Fragment[ 4] = like
Fragment[ 5] = 22
Fragment[ 6] = .
Fragment[ 7] = cookies
Fragment[ 8] = .
Fragment[ 9] = ,
Fragment[10] = This
Fragment[11] = ,
Fragment[12] = /
Fragment[13] = is
Fragment[14] = \
Fragment[15] = ?
Fragment[16] = tricky
Fragment[17] = ?
Fragment[18] = But
Fragment[19] = (
Fragment[20] = as
Fragment[21] = he
Fragment[22] = said
Fragment[23] = ,
Fragment[24] = "
Fragment[25] = Isn
Fragment[26] = '
Fragment[27] = t
Fragment[28] = it
Fragment[29] = delicous
Fragment[30] = fun
Fragment[31] = !"),
Fragment[32] = he
Fragment[33] = vanished
Fragment[34] = .
函数中的第一个
printf()
(定义函数本身除外)之前和之后有四个更改;函数的其余部分与前面的代码相同。这四项更改使修订后的代码引用函数(
buffer
buflen
)的参数,而不是
str
变量及其在
main()中的大小

请注意,在这个函数中使用重复性较小的代码会很简单。您将以相同的方式更改函数顶部的相同行,并保持其余行不变-并且修改后的
main()
不会对机制中的更改更明智

样本运行:

Whole string: <<(I) 44like22 .cookies. ,This, /is\ ?tricky?>>
Fragment[ 0] = (
Fragment[ 1] = I
Fragment[ 2] = )
Fragment[ 3] = 44
Fragment[ 4] = like
Fragment[ 5] = 22
Fragment[ 6] = .
Fragment[ 7] = cookies
Fragment[ 8] = .
Fragment[ 9] = ,
Fragment[10] = This
Fragment[11] = ,
Fragment[12] = /
Fragment[13] = is
Fragment[14] = \
Fragment[15] = ?
Fragment[16] = tricky
Fragment[17] = ?
$ ./splitit
Whole string: <<(I) 44like22 .cookies. ,This, /is\ ?tricky?>>
Fragment[ 0] = (
Fragment[ 1] = I
Fragment[ 2] = )
Fragment[ 3] = 44
Fragment[ 4] = like
Fragment[ 5] = 22
Fragment[ 6] = .
Fragment[ 7] = cookies
Fragment[ 8] = .
Fragment[ 9] = ,
Fragment[10] = This
Fragment[11] = ,
Fragment[12] = /
Fragment[13] = is
Fragment[14] = \
Fragment[15] = ?
Fragment[16] = tricky
Fragment[17] = ?
Californian(*) Avocados--a joyous fruit--are "wonderful!" to eat.
Whole string: <<Californian(*) Avocados--a joyous fruit--are "wonderful!" to eat.
>>
Fragment[ 0] = Californian
Fragment[ 1] = (*)
Fragment[ 2] = Avocados
Fragment[ 3] = --
Fragment[ 4] = a
Fragment[ 5] = joyous
Fragment[ 6] = fruit
Fragment[ 7] = --
Fragment[ 8] = are
Fragment[ 9] = "
Fragment[10] = wonderful
Fragment[11] = !"
Fragment[12] = to
Fragment[13] = eat
Fragment[14] = .
$
$。/splitit
整串:
片段[0]=(
片段[1]=I
片段[2]=)
片段[3]=44
片段[4]=类似
片段[5]=22
片段[6]=。
片段[7]=cookies
片段[8]=。
片段[9]=,
片段[10]=这个
片段[11]=,
片段[12]=/
片段[13]=is
片段[14]=\
片段[15]=?
片段[16]=复杂的
片段[17]=?
加利福尼亚(*)鳄梨——一种令人愉悦的水果——吃起来“棒极了”。
整串:
片段[0]=加利福尼亚语
片段[1]=(*)
片段[2]=鳄梨
片段[3]=--
片段[4]=a
片段[5]=欢乐的
片段[6]=果实
片段[7]=--
片段[8]=是
片段[9]=”
片段【10】=精彩
片段[11]=!”
片段[12]=到
片段[13]=吃
片段[14]=。
$

要收集包含或排除字符的范围,请使用
strspn
(包含)或
strcspn
(排除;两者都有描述)。它们都返回满足条件的字符数,您可以打印此范围,或以任何其他方式处理它,然后跳过该部分继续其余部分

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

void print_range (char *input, int start, int length)
{
    putchar ('"');
    while (length--)
        putchar (input[start++]);
    printf ("\"\n");
}

void print_continuous (char *input, int start, int length)
{
    while (length--)
        putchar (input[start++]);
    printf (" ");
}

void split_string (char *input, void(*process)(char *,int,int) )
{
    int current_pos = 0, next_length;

    while (input[current_pos])
    {
        /* 1. letters? */
        next_length = strspn (input+current_pos, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
        if (next_length)
        {
            process (input, current_pos, next_length);
            current_pos += next_length;
            continue;
        }
        /* 2. digits? */
        next_length = strspn (input+current_pos, "0123456789");
        if (next_length)
        {
            process (input, current_pos, next_length);
            current_pos += next_length;
            continue;
        }
        /* 3. neither letters nor digits */
        /* first, skip spaces. These don't need processing (apparently?) */
        next_length = strspn (input+current_pos, " ");
        current_pos += next_length;

        /* then skip all others as well */
        next_length = strcspn (input+current_pos, " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
        if (next_length)
        {
            process (input, current_pos, next_length);
            current_pos += next_length;
        }
    }

}

int main(void)
{
    char str[] ="(I) 44like22 .cookies. ,This, /is\x5C ?tricky?";

    printf ("input: [%s]\n", str);

    split_string (str, print_range);
    split_string (str, print_continuous);


    return 0;
}
#包括
#包括
#包括
#包括
#定义缓冲区大小为100
无效拆分(常量字符**p,字符*out){
如果(**p){
while(isspace(**p))
++*p;
如果(isalpha(**p)){
while(isalpha(**p))
*out++=*(*p)+;
}否则如果(isdigit(**p)){
while(isdigit(**p))
*out++=*(*p)+;
}否则{
而(**p&!isalpha(**p)和&!isdigit(**p)和&!isspace(**p))
*out++=*(*p)+;
}
}
*out='\0';
}
内部主(空){
char str[BUFFER_SIZE]=“(I)44like22.cookies.,这个,/很棘手吗?”;
字符*字符串[缓冲区大小]={0};
字符块[缓冲区大小];
常量char*p=&str[0];
int k=0;
而(*p){
一件一件(p&p,件);
如果(!*件)
持续
字符串[k++]=strdup(个);
}
对于(int i=0;i
有。你自己都做了些什么来找出答案?抱歉,这不是代码编写服务。欢迎使用堆栈溢出。请尽快阅读这一页。你应该向我们展示你的尝试,因为它会向我们展示你所期待的东西。如何为子字符串分配指针?您如何分配将字符复制到的空间?您是否熟悉malloc()
?你只是单独打印单位吗?你看过
了吗。当心strtok();这不是你需要的。事实上,什么是解决问题的最佳方法并不完全清楚,主要是因为你没有展示或陈述(但展示的更好)你想要什么。但这是可行的。我能想到的唯一办法是斯特克。不幸的是,strtok丢弃了它所看到的匹配项。或者你可以逐个字符地解析字符串char,并将每个字符(的类别)与前一个字符进行比较。正如我已经告诉过你的,你不能使用
strtok()
——因为它会将找到的内容作为定界符进行分解,你需要知道什么是定界符。您的字符类是字母、数字、标点符号还是空格?使用strspn()在创建每个类中的字符列表时会出现问题。使用
isalpha()
isdigit()
ispunt()
isspace()
似乎更好,但很难避免重复。顺便说一句,源字符串需要使用
\\
来代替单个反斜杠。这种方法很有趣。一目了然,只需将下一个字符的
ctype
与当前字符的
ctype
进行比较,就可以避免使用
isspace
isdigit
等显式测试每个字符。(有些字符设置了不止一个位,因此这需要一点掩蔽。)您能告诉我当我试图修改它时有什么错误吗?我希望每次在文件上运行fgets时都能重用它以获取一行内容。感谢您为fgets添加更多信息:)。我想做一个小调整,将
“]“
”;“
分开。所以像这样“
”];“
”;“
”。我不想碰你的代码,因为我知道它能用。你能解释一下为什么我要用malloc来做这个吗?我很惊讶我不得不使用malloc,而你却没有。我添加了我上面所做的。我不需要使用
malloc()
,因为我使用了可变长度数组。在函数中,我有:
charout[2*buflen];char*ptr[buflen]
第一个(
out
)分配足够的空间来存储输入字符串中的每个单独字符和后面的空字节。第二个(
ptr#include <ctype.h>
#include <stdio.h>
#include <string.h>

 static void split_string(const char *buffer, size_t buflen)
 {
    const char *s = buffer;
    char   out[2 * buflen];
    char  *ptr[buflen];
    char **p = ptr;
    char  *o = out;
    int    n = 0;
    int c;

    printf("Whole string: <<%s>>\n", buffer);

    while ((c = (unsigned char)*s++) != '\0')
    {
        if (isdigit(c))
        {
            *p++ = o;
            *o++ = c;
            while (isdigit((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (isalpha(c))
        {
            *p++ = o;
            *o++ = c;
            while (isalpha((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (ispunct(c))
        {
            *p++ = o;
            *o++ = c;
            while (ispunct((unsigned char)*s))
                *o++ = *s++;
            *o++ = '\0';
            n++;
        }
        else if (!isspace(c))
        {
            printf("Hmmm: don't know how to classify %d (%c)\n", c, c);
        }
    }

    for (int i = 0; i < n; i++)
        printf("Fragment[%2d] = %s\n", i, ptr[i]);
}

int main(void)
{
    const char  str[] = "(I) 44like22 .cookies. ,This, /is\\ ?tricky?";
    split_string(str, sizeof(str));

    char buffer[4096];
    while (fgets(buffer, sizeof(buffer), stdin) != 0)
        split_string(buffer, strlen(buffer)+1);

    return 0;
}
$ ./splitit
Whole string: <<(I) 44like22 .cookies. ,This, /is\ ?tricky?>>
Fragment[ 0] = (
Fragment[ 1] = I
Fragment[ 2] = )
Fragment[ 3] = 44
Fragment[ 4] = like
Fragment[ 5] = 22
Fragment[ 6] = .
Fragment[ 7] = cookies
Fragment[ 8] = .
Fragment[ 9] = ,
Fragment[10] = This
Fragment[11] = ,
Fragment[12] = /
Fragment[13] = is
Fragment[14] = \
Fragment[15] = ?
Fragment[16] = tricky
Fragment[17] = ?
Californian(*) Avocados--a joyous fruit--are "wonderful!" to eat.
Whole string: <<Californian(*) Avocados--a joyous fruit--are "wonderful!" to eat.
>>
Fragment[ 0] = Californian
Fragment[ 1] = (*)
Fragment[ 2] = Avocados
Fragment[ 3] = --
Fragment[ 4] = a
Fragment[ 5] = joyous
Fragment[ 6] = fruit
Fragment[ 7] = --
Fragment[ 8] = are
Fragment[ 9] = "
Fragment[10] = wonderful
Fragment[11] = !"
Fragment[12] = to
Fragment[13] = eat
Fragment[14] = .
$
#include <stdio.h>
#include <string.h>

void print_range (char *input, int start, int length)
{
    putchar ('"');
    while (length--)
        putchar (input[start++]);
    printf ("\"\n");
}

void print_continuous (char *input, int start, int length)
{
    while (length--)
        putchar (input[start++]);
    printf (" ");
}

void split_string (char *input, void(*process)(char *,int,int) )
{
    int current_pos = 0, next_length;

    while (input[current_pos])
    {
        /* 1. letters? */
        next_length = strspn (input+current_pos, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
        if (next_length)
        {
            process (input, current_pos, next_length);
            current_pos += next_length;
            continue;
        }
        /* 2. digits? */
        next_length = strspn (input+current_pos, "0123456789");
        if (next_length)
        {
            process (input, current_pos, next_length);
            current_pos += next_length;
            continue;
        }
        /* 3. neither letters nor digits */
        /* first, skip spaces. These don't need processing (apparently?) */
        next_length = strspn (input+current_pos, " ");
        current_pos += next_length;

        /* then skip all others as well */
        next_length = strcspn (input+current_pos, " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
        if (next_length)
        {
            process (input, current_pos, next_length);
            current_pos += next_length;
        }
    }

}

int main(void)
{
    char str[] ="(I) 44like22 .cookies. ,This, /is\x5C ?tricky?";

    printf ("input: [%s]\n", str);

    split_string (str, print_range);
    split_string (str, print_continuous);


    return 0;
}
#include <stdio.h> 
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define BUFFER_SIZE 100

void split_one(const char **p, char *out){
    if(**p){
        while(isspace(**p))
            ++*p;
        if(isalpha(**p)){
            while(isalpha(**p))
                *out++ = *(*p)++;
        } else if(isdigit(**p)){
            while(isdigit(**p))
                *out++ = *(*p)++;
        } else {
            while(**p && !isalpha(**p) && !isdigit(**p) && !isspace(**p))
                *out++ = *(*p)++;
        }
    }
    *out = '\0';
}

int main (void){
    char str[BUFFER_SIZE] = "(I) 44like22 .cookies. ,This, /is\\ ?tricky?";
    char *strings[BUFFER_SIZE] = {0};
    char piece[BUFFER_SIZE];
    const char *p = &str[0];

    int k = 0;

    while(*p){
        split_one(&p, piece);
        if(!*piece)
            continue;
        strings[k++] = strdup(piece);
    }
    for(int i = 0; i < k; ++i){
        printf("'%s'\n", strings[i]);
        free(strings[i]);
    }
    return 0; 
}