如何在C语言中通过字母比较包含数字的字符串

3
我需要比较包含字母和数字的字符串,只比较字母和数字的出现次序。例如字符串"first%dsecond%dj"应当与任何形如"first[number]second[number]j"的字符串视为相等。我尝试了以下方法:
char *c_i
int i, j;
if (sscanf(c_i, "first%dsecond%dj", &i, &j) == 2 &&
    c_i[strlen(in) - 2] == 'j') {
    printf("%s", c_i);
}

但是sscanf会忽略最后一个数字后面的所有内容,所以像"first%dsecond%dthird%dj"这样的字符串也会给出正确的值并打印出来。

通常情况下,sscanf只关心最后一个指定符号之前的字母的值,我想找到一种方法来计算指定符号之后的字母的值,比如说一个比较器,它检查整个字符串并获取任何数字但不包括数字。

当然,我可以通过创建自己的char*扫描器来实现这一点,但如果有更简单的方法,我希望避免这样做。

2个回答

3
使用%n获取转换的长度,然后检查字符串是否确实在那里结束:
void checkString(const char *s)
{
  int i, j, n = 0;

  if (sscanf(s, "first%dsecond%dj%n", &i, &j, &n) == 2 && s[n] == '\0') 
  {
    printf("%s", s);
  }
}

1

@unwind的好答案的变体。

使用"%n"记录扫描中的当前位置,使用"*"来避免保存到int中的需要。

n...相应的参数应该是指向有符号整数的指针,用于写入到目前为止由此调用fscanf函数从输入流中读取的字符数。... C11 §7.21.6.2 12

可选的抑制赋值字符*。§7.21.6.2 3

// return true on match
bool IE_compare(const char *c_i) {
  int n = 0;
  sscanf(c_i, "first%*dsecond%*dj%n", &n);
  return n > 0 && c_i[n] == '\0';
}

注意:格式字符串可以编码为单独的字符串文字,以供备选阅读。
  sscanf(c_i, "first" "%*d" "second" "%*d" "j" "%n", &n);

上述内容将匹配数字前的空格,例如"first +123second -456j",因为"%d"允许。为避免这种情况:
  int n1, n2,
  int n = 0;
  sscanf(c_i, "first%n%*dsecond%n%*dj%n", &n1, &n2, &n);
  return n > 0 && !isspace((unsigned char) c_i[n1]) && 
      !isspace((unsigned char) c_i[n2]) && c_i[n] == '\0';

上面的代码将匹配带有前导符号的数字,例如"first+123second-456j",因为"%d"允许这样。为了避免这种情况:
  sscanf(c_i, "first%n%*dsecond%n%*dj%n", &n1, &n2, &n);
  return n > 0 && isdigit((unsigned char) c_i[n1]) && 
      isdigit((unsigned char) c_i[n2]) && c_i[n] == '\0';

  // or 
  int n = 0;
  sscanf(c_i, "first%*[0-9]second%*[0-9]j%n", &n);
  return n > 0 && c_i[n] == '\0';

有些不确定的是是否需要出现数字。 "...and appearance of a number" 意味着是必须的。那么 "firstsecondj" 是否匹配?上述答案假设不需要。

这是一个非常好的答案!你说得对,必须是数字,“firstsecondj”和“first 2 second 4 j”都是错误的。谢谢! :) - P Szuberski
1
@IpEsez 提示:与许多编码问题一样,良好的代码和效率源于精确的编码目标。 "数字" 太宽泛了。前导空格可以吗?不行 - 解决了。一个符号可以吗?什么范围是有效的?必须是整数吗?没有数字可以吗?对于这样一个小的编码任务,人们可以编写许多候选方案。在更大的程序中,这是不切实际的。有时简单地列出一些有效和无效的示例会有很大帮助。 - chux - Reinstate Monica
我会记住,我是编程新手,特别是在stackoverflow上发布任何内容。再次感谢您的建议! - P Szuberski

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