【问题标题】:Sscanf ignoring date '-' in date stringSscanf 忽略日期字符串中的日期“-”
【发布时间】:2020-10-09 18:49:44
【问题描述】:

当我尝试验证日期字符串的信息时遇到问题 代码是

  char date[] = "1990-01-01";

  sscanf(date, "%d %d %d", &year, &month, &day)
  printf("%d-%d-%d", year, month, day);   

  //expected 1990-01-01
  // actual output 1990--1--1

它将“-”字符作为月份和日期的减号,在取值时如何忽略它? 我尝试使用 %*- 但它忽略了整数输入 提前致谢

【问题讨论】:

  • "%d %d %d" 是否匹配 "1990-01-01"
  • 我将值解析为 3 个整数,然后打印结果以查看它是否有效@NathanOliver
  • 我再问一遍,"%d %d %d" 匹配 "1990-01-01" 吗?一个字符串和另一个字符串有区别吗?

标签: c string parsing scanf


【解决方案1】:

您可以尝试使用 sscanf 转换:

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

int main()
{

    char date[] = "1990-01-01";

    char year[4];
    char month[2];
    char day[2];
    char m1[1];
    char m2[1];
    
    sscanf(date, "%[^-]%[-]%[^-]%[-]%s", year, m1, month, m2, day);
    printf("%s %s %s \n", year, month, day);

    return 0;
}

执行说:

gcc -o vd -Wall -pedantic -Wextra  vd.c
./vd
1990 01 01 

这是一个更好的程序,它允许在命令行上进行更多的输入检查:

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

int main(int argc, char **argv)
{

    char year[4];
    char month[2];
    char day[2];
    char m1[1];
    char m2[1];
    int rc;

    if (argc != 2)
    {
        printf("usage: vd YYYY-MM-DD\n");
        return 1;
    }
    
    rc = sscanf(argv[1], "%4[0-9^-]%[-]%2[0-9^-]%[-]%2[0-9]", 
                             year, m1, month, m2, day);
    if (rc == 5)
        printf("%d %d %d \n", atoi(year), atoi(month), atoi(day));
    else
    {
        printf("Incorrect date format\n");
        return 1;
    }

    return 0;
}

执行说:

./vd 1990-01-01
1990 1 1 
./vd 1990-12-12
1990 12 12 
./vd 1990-01
Incorrect date format
./vd 1990-ab-13
Incorrect date format

这是考虑到@rici cmets 的改进版本:

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

int main(int argc, char **argv)
{

        char year[4];
        char month[2];
        char day[2];
        int rc;

    if (argc != 2)
    {
        printf("usage: vd YYYY-MM-DD\n");
        return 1;
    }
    
    rc = sscanf(argv[1], "%4[0-9]-%2[0-9]-%2[0-9]", 
                             year, month, day);
    if (rc == 3)
        printf("%d %d %d \n", atoi(year), atoi(month), atoi(day));
    else
    {
        printf("Incorrect date format\n");
        return 1;
    }

    return 0;
}

执行:

./vd 1990-01-02
1990 1 2 
./vd 1990-12-12
1990 12 12 
./vd 1990-01
Incorrect date format
./vd 1990-db-13
Incorrect date format
./vd 1990--01-02
Incorrect date format

【讨论】:

  • 使用%[-] 而不仅仅是- 有什么意义?如果用户输入1990--01-02,那么第一个%[-] 将匹配两个破折号,但由于结果将是m1 上的缓冲区溢出,我认为这不是一个优势。
  • 是的,你是对的。我修改了我的代码。谢谢。
  • 还有[0-9^-]? %4[0-9] 表示“最多四位数”。 %4[0-9^-] 表示“最多四个(数字或^-)”。这并不意味着“排除破折号”,这不是必需的,因为- 不在0-9 中,因此被排除在外。
  • 是的,你是对的。我修改了我的代码。再次感谢。
【解决方案2】:

尝试在sscanf()printf() 中使用填充。

#include <stdio.h>

int main(void) {
    char date[] = "1990-01-01";
    int year;
    int month;
    int day;

    sscanf(date, "%d %03d %03d", &year, &month, &day);
    printf("%d%03d%03d", year, month, day);

    return 0;
}

请注意,我没有在 printf() 语句中使用 -。使用填充后,此处不需要。

你会得到类似的东西:

1990-01-01

您试图将01 视为01,但由于它是一个整数,而不是八进制,正数之前的所有零都将被删除,这就是您得到1 的原因而不是01。这就是我在上面的示例中使用填充零修复的问题。

【讨论】:

  • 问题是当我选择第一个 %03d 时,scanf 采用 -(分隔符作为减号)并将值转换为 -01,我需要它是正数,有没有办法忽略将“-”作为负数并获得正值?
  • 尝试abs() 可能有帮助?我不确定,但它将任何数字转换为正整数。
  • 这会将错误的值放入变量中。printf("%d %d %d", year, month, day); 输出 1990 -1 -1。所以它不起作用,它只是给人一种它起作用的错觉
猜你喜欢
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 2020-04-26
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
相关资源
最近更新 更多