0

我可以有包含随机 10 位数字的字符串, 例如"abcgfg1234567890gfggf""fgfghgh3215556890ddf"

基本上是 10 位数字加字符在一个字符串中的任意组合,所以我需要检查字符串以确定是否存在 10 位数字。我使用 strspn 但它返回 0

char str_in[] = "abcgfg1234567890gfggf";
char cset[] = "1234567890";    
int result;

result = strspn(str_in, cset);   // returns 0   need it to return 10

以下代码返回 0 而不是 10 的事实突出了这个问题。我之前问过这个问题,但大多数回复都是为了检查一个已知的 10 位数字。在我的情况下,这个数字将是随机的。还有比这更好的方法strspn吗?

4

6 回答 6

3

它返回 0,因为字符串的开头没有数字。

strspn() 函数计算 s 的初始段的长度(以字节为单位),该段完全由 accept 中的字节组成。

您需要跳过非数字 - strcspn- 然后调用strspn字符串 + 该偏移量。你可以试试:

/* Count chars to skip. */
skip = strcspn(str_in, cset);

/* Measure all-digit portion. */
length = strspn(str_in + skip, cset)

编辑

我应该提到这必须在一个循环中完成。例如,如果您的字符串是 "abcd123abcd1234567890"第一个strspn将仅匹配 3 个字符,您需要进一步查看。

于 2013-10-04T13:47:44.900 回答
1

只需使用sscanf()

unsigned long long value;

const char *str_in = "abcgfg1234567890gfggf";
if(sscanf(str_in, "%*[^0-9]%uL", &value) == 1)
{
  if(value >= 1000000000ull)  /* Check that it's 10 digits. */
  {
   /* do magic here */
  }
}

上面假设它unsigned long long足够大以容纳 10 位十进制数字,实际上这意味着它假设它是 64 位类型。

%*[^0-9]转换说明符告诉sscanf()忽略一堆不是(十进制)数字的初始字符,然后直接转换一个 unsigned long long ( ) %uL。尾随字符被忽略。

于 2013-10-04T13:48:22.370 回答
0

替代使用sscanf()

(@unwind 的明显变体)

const char *str_in = "abcgfg0123456789gfggf";
int n1 = 0;
int n2 = 0;
// %*[^0-9]  Scan any non-digits.  Do not store result.
// %n        Store number of characters read so far.
// %*[0-9]   Scan digits.  Do not store result.
sscanf(str_in, "%*[^0-9]%n%*[0-9]%n", &n1, &n2);
if (n2 == 0) return 0;
return n2 - n1;

将前导0字符计数为数字计数的一部分。


如果想避免sscanf()

char str_in[] = "abcgfg1234567890gfggf";
const char *p1 = str_in;
while (*p1 && !isdigit(*p1)) p1++;
const char *p2 = p1;
while (isdigit(*p2)) p2++;
result = p2 - p1;
于 2013-10-04T14:01:53.123 回答
0

使用正则表达式怎么样?

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

int
main(int argc, char **argv)
{
    char str_in[] = "abcgfg1234567890gfggf";
    int result = 0;
    const char *pattern = "[0-9]{10}";
    regex_t re;
    char msg[256];

    if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) {
            perror("regcomp");
            return(EXIT_FAILURE);
    }

    result = regexec(&re, str_in, (size_t)0, NULL, 0);
    regfree(&re);

    if (!result) {
            printf("Regex got a match.\n");
    } else if (result == REG_NOMATCH) {
            printf("Regex got no match.\n");
    } else {
            regerror(result, &re, msg, sizeof(msg));
            fprintf(stderr, "Regex match failed: %s\n", msg);
            return(EXIT_FAILURE);
    }

    return(EXIT_SUCCESS);
}
于 2013-10-04T14:07:59.917 回答
0

strspn对此似乎很方便,但是您必须将其包含在循环中并多次搜索。鉴于特定要求,最简单的方法可能是制作自己的自定义函数。

int find_digits (const char* str, int n);
/* Searches [str] for a sequence of [n] adjacent digits.
   Returns the index of the first valid substring containing such a sequence,
   otherwise returns -1.
*/


#include <ctype.h>  

int find_digits (const char* str, int n)
{
  int result = -1;
  int substr_len = 0;
  int i = 0;

  for(int i=0; str[i] != '\0'; i++)
  {
    if(isdigit(str[i]))
    {
      substr_len++;
    }
    else
    {
      substr_len=0;
    }

    if(substr_len == n)
    {
      result = i;
      break;
    }
  }

  return result;
}

(我只是在这里和现在破解了这个,没有经过测试,但你明白了。这很可能是该任务最快的算法,也就是说,如果性能很重要的话)

于 2013-10-04T14:08:22.860 回答
0

要在字符串中测试“0123456789”套装,您可以执行以下操作:

int             main()
{
  char str_in[] = "abcgfg1234567890gfggf";
  char cset[] = "1234567890";
  int result;
  int i;
  int f;

  i = 0;
  f = 0;
  while (str_in[i])
    {
      if (str_in[i] == cset[f])
        {
          f++;
          if(f == strlen(cset))
            return (f);
        }
      else
        f = 0;
      i++;
    }
}
于 2013-10-04T14:24:20.767 回答