【问题标题】:Separating a string into smaller strings将字符串分成更小的字符串
【发布时间】:2016-05-04 04:42:00
【问题描述】:

我有以下字符串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,我在输出上只取e,x 是0。

【问题讨论】:

  • 你想要的破解标准是什么?
  • 除非有某种分隔符,否则不能使用 strtok。

标签: c string


【解决方案1】:

我意识到我在这个方面已经很晚了,但这是为了如果有人有类似的情况

假设所有输入字符串都像您的示例,则此方法将起作用。

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 语句。这会检查 fgets 是否读取了换行符,并将其转换为 NUL 字符。 (本质上是截断字符串)。
• 至于strpbrk(),它只是一个函数,它返回指向第一个字符串中第二个字符串中任何字符第一次出现的指针。我在这里使用它来查找数字序列的开头。
• 为了安全起见,我还会将atoi() 替换为strtol()
letters[] 数组大小是strpbrk()(第一个数字的地址)的返回值,减去数组的开头(以字节为单位给出字母字符串的长度),再加上我稍后添加的 NUL 字符.

【讨论】:

    【解决方案2】:
    • 试试下面的代码。希望对你有帮助。

      #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);
      }
      

    【讨论】:

      【解决方案3】:
      #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;你有...conversion to ‘size_t’ from ‘long int’ may change the sign of the result
      • @Michi 不会出现阴性结果。
      • 我很确定,可能只指出警告:D...任何不错的方法。
      • OP 没有提到hallo12-3 存在时应该输出什么,这意味着他 100% 确定字符串确实包含字母和数字
      • 是的,目前还不清楚。但在 OP 的示例代码中不考虑负数。
      【解决方案4】:

      按照strtok()man page

      对 strtok() 的每次调用都返回一个指向包含下一个标记的以空字符结尾的字符串的指针。 此字符串不包含分隔字节。 [...]

      所以,第一次使用"0123456789 \t\n"作为分隔符时,1会被当作实际的分隔符,在后续的解析中不会考虑。

      您可能希望使用strcspn() 和/或strpbrk() 找出所需子字符串的索引并进行相应的解析。

      【讨论】:

      • strpbrk(input, "0123456789"); 将效率低下,因为strpbrk 无法知道它正在寻找数字。使用isdigit 的手动解决方案会更有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多