将一个字符串拆分为较小的字符串

3

我有一个字符串abcd1234,我想找到一种方法将这个字符串分成两个不同的字符串,abcd1234。我尝试了以下代码:

char buf[100],*str1,*str2;
int x;
fgets(buf,sizeof(buf),stdin);
str1=strtok(buf,"0123456789 \t\n");
str2=strtok(NULL," \n\t\0");
puts(str1);
puts(str2);
x=atoi(str2);
printf("x=%d", x);

但输出结果是abcd 234。如果我尝试输入一个字母和一个数字,例如a2,则输出仅为ex为0。

2
你想要什么样的中断标准? - Ian
除非有某种分隔符,否则您无法使用strtok。 - Lundin
4个回答

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

size_t extract(const char **sp, char *out, int (*test)(int ch));

int main(void){
    char buf[100], str1[100], str2[100];
    int x;
    const char *p = buf;
    //size_t len;

    fgets(buf, sizeof(buf), stdin);
    while(*p){
        if(isalpha((unsigned char)*p)){
            extract(&p, str1, isalpha);
            puts(str1);
        } else if(isdigit((unsigned char)*p)){
            extract(&p, str2, isdigit);
            x = atoi(str2);
            printf("%s, x=%d\n", str2, x);
        } else {
            ++p;//skip one char
        }
    }
    return 0;
}

size_t extract(const char **sp, char *out, int (*test)(int ch)){
    const char *p = *sp;
    while(*p && test((unsigned char)*p)){
        *out++ = *p++;
    }
    *out = '\0';
    size_t len = p - *sp;
    *sp = p;
    return len;
}

在这里 size_t len = p - *sp; 你有...从‘long int’转换到‘size_t’可能会改变结果的符号 - Michi
1
@Michi 不会出现负面结果。 - BLUEPIXY
我很确定,我的意思只是警告一下 :D ... 无论如何,方法不错。 - Michi
无论如何,OP没有提到hallo12-3存在时应该输出什么,这意味着他百分之百确定该字符串包含字母和数字。 - Michi
是的,这很不清楚。但是在 OP 的示例代码中,负数并未被考虑在内。 - BLUEPIXY
请考虑没有负数。 - Vaggelis Spi

0
尝试使用以下代码。希望这能帮到您。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
   char string[]="abcd1234";
   char digitStr[10];
   char charStr[10];
   int i,j = 0,k = 0;

   for(i=0;string[i];i++)
   {
        if(isdigit(string[i]))
        {
                charStr[j++]=string[i];
        }
        else
        {
                digitStr[k++]=string[i];
        }
   }
   charStr[j] = '\0';
   digitStr[k] = '\0';
   printf("%s %s\n",digitStr,charStr);
}

0
根据strtok()man page,每次调用该函数都会返回一个指向下一个标记的以空字符结尾的字符串的指针。此字符串不包括定界字节。 [...] 因此,在第一次使用"0123456789 \t\n"作为分隔符时,1将被视为实际分隔符,并且不会在后续解析中考虑。您可能需要使用strcspn()和/或strpbrk()来查找所需子字符串的索引并进行相应的解析。

然而,strpbrk(input, "0123456789"); 是低效的,因为 strpbrk 不知道它正在寻找数字。使用 isdigit 的手动解决方案将更加有效。 - Lundin

0

我意识到我很晚才回复,但这是为了如果有人有类似的情况

假设所有输入字符串都像你的示例一样,这种方法将起作用。

char buf[100];
fgets(buf, sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n')
    buf[strlen(buf) - 1] = '\0';
int x = atoi(strpbrk(buf, "0123456789"));
char letters[number - buf + 1];
memcpy(letters, sizeof(letters) - 1, buf);
letters[sizeof(letters) - 1] = '\0';
//letters is the word
//x is the number as an int, not a string

• 注意在fgets后面的if语句。这个语句检查了newline字符是否被fgets读取,并将其转换为NUL字符(从而截断了字符串)。
• 至于strpbrk(),它只是一个函数,返回第二个字符串中任何字符第一次出现的指针。我在这里用它来找到数字序列的开头。
• 为了安全起见,我会将atoi()替换为strtol()
letters[]数组的大小是strpbrk()的返回值(第一个数字的地址)减去数组的起始位置(给出字母字符串的长度,以字节为单位),再加上我后来添加的NUL字符的长度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接