問題很簡單,我的資料庫 postgres 中有一個日期列,它以yyyy-mm-dd格式將值作為字串回傳,為了將其存盤在我的代碼中,我需要決議該值。功能也很簡單:
int parse_date(const char * s, tbDate*res)
{
int yyyy, mm, dd;
if (sscanf(s, "%d %d %d", &yyyy, &mm, &dd) == 3
|| sscanf(s, "%d.%d.%d", &yyyy, &mm, &dd) == 3
|| sscanf(s, "%d/%d/%d", &yyyy, &mm, &dd) == 3
|| sscanf(s, "%d-%d-%d", &yyyy, &mm, &dd) == 3)
{
if (mm > 0 && mm < 13 && dd>0 && dd < 32)
{
res->day = dd;
res->month = mm;
res->year = yyyy;
return TB_PARSE_SUCCESS;
}
}
return TB_PARSE_FAILURE;
}
sscanf()的前三個版本運行良好,但是后面的 sscanf(s, "%d-%d-%d", &yyyy, &mm, &dd),資料庫回傳的格式,被讀取為負值,這意味著如果我傳遞一個像'2022-12-03'這樣的日期,yyyy是正確的 2022,但mm和dd是 -12 和 -3。我會避免在資料庫的查詢中放置日期格式函式,并且我會知道是否有辦法在sscanf()中轉義-字符。
uj5u.com熱心網友回復:
像“2022-12-03”這樣的日期,yyyy 是正確的 2022,但 mm 和 dd 是 -12 和 -3。
那是因為首先"2022-12-03"
匹配sscanf(s, "%d %d %d", &yyyy, &mm, &dd) == 3
。請注意," "
格式"%d %d %d"
匹配 0 個或多個空格。
只需更改順序
if ( sscanf(s, "%d-%d-%d", &yyyy, &mm, &dd) == 3 // swapped
|| sscanf(s, "%d.%d.%d", &yyyy, &mm, &dd) == 3
|| sscanf(s, "%d/%d/%d", &yyyy, &mm, &dd) == 3
|| sscanf(s, "%d %d %d", &yyyy, &mm, &dd) == 3) // swapped
uj5u.com熱心網友回復:
我想到sscanf()函式也可以作業,如果它是一個骯臟的答案,例如,如果你寫 '2022/09/12fooobar',它也會回傳 3,所以我決定更改函式并改進對有效日期的檢查,因為我沒有在互聯網上找到它,所以我發布了我自己的決議日期函式:
int parse_date(const char * s, tbDate*res)
{
res->year=res->month=res->day=0;
char separator;
int acc=0;
while (isspace(*s))
s ;
if(!(*s >= '0' && *s <= '9'))
return TB_PARSE_FAILURE;
while (*s >= '0' && *s <= '9')
acc = (acc << 3) (acc << 1) *s - '0';///fast way to multiply for 10
if(!*s) return TB_PARSE_FAILURE;
separator=*s;
s ;
res->year=acc;
acc=0;
if(!(*s >= '0' && *s <= '9'))
return TB_PARSE_FAILURE;
while (*s >= '0' && *s <= '9')
acc = (acc << 3) (acc << 1) *s - '0';
res->month=acc;
acc=0;
if(*s!=separator)
return TB_PARSE_FAILURE;
s ;
if(!(*s >= '0' && *s <= '9'))
return TB_PARSE_FAILURE;
while (*s >= '0' && *s <= '9')
acc = (acc << 3) (acc << 1) *s - '0';
res->day=acc;
while(isspace(*s))
s ;
if(*s) return TB_PARSE_FAILURE;
switch (res->month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if( res->day>0 && res->day<32)
return TB_PARSE_SUCCESS;
else
return TB_PARSE_FAILURE;
case 4:
case 6:
case 9:
case 11:
if( res->day>0 && res->day<31)
return TB_PARSE_SUCCESS;
else return TB_PARSE_FAILURE;
case 2:
if(res->day>0 && res->day<29)
return TB_PARSE_SUCCESS;
else if (res->day==29 &&(res->year%400==0 ||(res->year%4==0 && res->year%100!=0) ) )
return TB_PARSE_SUCCESS;
else
return TB_PARSE_FAILURE;
default:
return TB_PARSE_FAILURE;
}
return TB_PARSE_FAILURE;
}
它在開頭和結尾跳過空格,但不在數字內。它檢查您是否使用相同的分隔符并檢查日期是否有效或更少。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507335.html
標籤:C