检查字符串在C中的格式是否正确

检查字符串在C中的格式是否正确,c,string,formatting,string-formatting,C,String,Formatting,String Formatting,我在函数中有以下代码,用于检查字符串“datestr”的格式是否正确(dd/mm/yyyy): 虽然它适用于格式正确的字符串,如“02/10/2015”,但它也适用于格式不正确的字符串,如“2/10/2015”,因为日期和月份的长度必须为2位,年份的长度必须为4位。 有没有办法在sscanf功能中检查这一点? 或者我必须先检查它是否符合以下条件 if (!(strlen(datestr) == 10 && isdigit(datestr[0]) && isdigi

我在函数中有以下代码,用于检查字符串“datestr”的格式是否正确(dd/mm/yyyy):

虽然它适用于格式正确的字符串,如“02/10/2015”,但它也适用于格式不正确的字符串,如“2/10/2015”,因为日期和月份的长度必须为2位,年份的长度必须为4位。 有没有办法在sscanf功能中检查这一点? 或者我必须先检查它是否符合以下条件

if (!(strlen(datestr) == 10 && isdigit(datestr[0]) && isdigit(datestr[1]) && ...)) return NULL;

谢谢大家!

我不相信你能在sscanf内部做到你所要求的。格式说明符指定最大宽度,但不是最小宽度。因此,例如“%2d/%2d/%4d”将不允许“100/10/2014”,但不允许“1/10/2015”

正如你在文章中提到的,你可以进行数字计数。这将消除许多虚假的答案。如果您只需要一条语句,而不想执行边界检查(即检查以确保数据是有效的日期,因此月份不是32或类似的日期),则可以使用正则表达式。这将使用类似std::regex_match(C++11或更高版本)的东西。您可以找到有关正确正则表达式的更多信息

否则,在解析之后,您将无法进行自己的检查

  • 我不清楚上面的内容。据我所知,C没有标准的正则表达式库,但有几种可用的正则表达式库。当我指向C++中的STD::ReExxIn匹配时,它会给你一个你需要的正则库函数的例子。通常有可用的正则表达式库(如posix正则表达式),但它们不易于移植

正如评论中所建议的那样,使用正则表达式可能是最好的选择,尽管您可以使用
if
条件,但这样做不太简洁

我不使用C编写代码,所以我不知道这是否完全正确,但用于此的正则表达式应该类似于:

\d{2}\/\d{2}\/\d{4}

如果您不知道如何使用正则表达式,请参阅。您可以在web上找到许多关于C正则表达式的教程,以及更复杂的算法。

要使用
sscanf()
进行学究式的检查,请使用
“%[]”
“%n”

各种各样的日期测试,现代日期很容易。允许历史日期是很棘手的。怎么样

让代码使用计算机能理解的日期

int ValidDate(int year, int month, int day) {
  struct tm tm1 = { 0 };
  tm1.tm_year = year - 1900;
  tm1.tm_mon = month + 1;
  tm1.tm_mday = day;
  struct tm tm2 = tm1;
  if (mktime(&tm1) == -1) return 0; // failed conversion.
  // Did mktime() adjust fields?
  if (tm1.tm_year != tm2.tm_year) return 0;
  if (tm1.tm_mon != tm2.tm_mon) return 0;
  return tm1.tm_mday == tm2.tm_mday;
}

或者使用一个正则表达式,例如,实际上,没有办法让
sscanf()
执行您想要的检查。你得自己做。当然,
sscanf()
将允许
“99/7/-201”
通过;您必须验证数字是否在所需的范围内。是什么让您相信“dd/mm/yyyy”是“正确的格式”?美国使用mm/dd/yyyy,日本使用yyyy-mm-dd,欧洲(并非所有国家!)使用dd/mm/yyyy。最好是坚持ISO 8601格式的兼容性。这是大学分配的一部分,我知道日期将是这样的:“为什么当提到OP的问题被清晰地标记为C,代码是相同的时,你会提到C++吗?抱歉-我会编辑得更清楚。我本来想指出的是,他需要一个不同的库,但可以通过std::regex_match查看他需要的示例。有像posix正则表达式这样的可用库可以工作。更像是一个标准定义,而不是一个库。虽然该标准设计为可移植的,但实现并不总是在各种操作系统上可用,而且默认情况下肯定不会安装。在linux系统上,他可能会假设posix正则表达式是可用的。我不会在Windows机器上做这样的假设。引用上面标记的答案“如果您使用一些未作为Posix一部分标准化的Linux API,您可以很容易地将它们移植到一大系列Unix衍生产品中(包括Linux,但不限于它!)”我也没有担任任何职务,谢谢!示例中有一个小错误(应该是“n[2]!=10”而不是“n[2]!=9”,以适合我指定的格式),但是,做得很好@小丑的回答被修正了。
// if (sscanf(datestr, "%d/%d/%d", &day, &month, &year) != 3) return NULL;
int n[3] = { 0 };
sscanf(datestr, "%*[0-9]%n/%*[0-9]%n/%*[0-9]%n", &n[0], &n[1], &n[2]); 
if (n[0] != 2 || n[1] != 5 || n[2] != 10) return NULL;

// Good To Go
sscanf(datestr, "%d/%d/%d", &day, &month, &year);

if (!ValidDate(year, month, day)) return NULL;
int ValidDate(int year, int month, int day) {
  struct tm tm1 = { 0 };
  tm1.tm_year = year - 1900;
  tm1.tm_mon = month + 1;
  tm1.tm_mday = day;
  struct tm tm2 = tm1;
  if (mktime(&tm1) == -1) return 0; // failed conversion.
  // Did mktime() adjust fields?
  if (tm1.tm_year != tm2.tm_year) return 0;
  if (tm1.tm_mon != tm2.tm_mon) return 0;
  return tm1.tm_mday == tm2.tm_mday;
}