在我的程序中,我使用sscanf
來檢查字符串是否具有給定的格式。爲此,我提供了格式字符串中的參數個數,並在分析輸入時檢查sscanf
是否返回相同的數字。sscanf - 不同數量的格式參數?
作爲原語解析器的一部分,我想檢查一個字符串是否與許多格式之一匹配。 sscanf
函數是可變的,所以我該如何處理需要傳遞的不同數量的參數?
目前,我只是將大量的參數(例如50)傳遞給該函數,並且希望格式化字符串不包含更多參數。
有沒有更好的方法來做到這一點?
在我的程序中,我使用sscanf
來檢查字符串是否具有給定的格式。爲此,我提供了格式字符串中的參數個數,並在分析輸入時檢查sscanf
是否返回相同的數字。sscanf - 不同數量的格式參數?
作爲原語解析器的一部分,我想檢查一個字符串是否與許多格式之一匹配。 sscanf
函數是可變的,所以我該如何處理需要傳遞的不同數量的參數?
目前,我只是將大量的參數(例如50)傳遞給該函數,並且希望格式化字符串不包含更多參數。
有沒有更好的方法來做到這一點?
您確實需要比scanf
更重的東西。你必須告訴scanf
你輸入的格式是什麼;它無法自行解決任何問題。
如果你有權訪問POSIX,看看regex.h
這可能是你需要的一切。
否則,你卡在自己的身上。 lex
和yacc
很好,如果格式比較複雜的話,或者strtok
或者(getchar
+ switch
)可能是要走的路。
編輯: 既然你可以使用POSIX,下面是一個簡單的例子,說明如何從c中的正則表達式提取數據。 (檢查排除錯誤簡潔。)
char txt[] = "232343341235898dfsfgs/.f";
regex_t reg;
regmatch_t refs[MAX_REFS]; //as in, the maximum number of data you want to extract
regcomp(®, "3433\\([0-5]*\\).*", 0); //replace 0 with REG_EXTENDED if desired
regexec(®, txt, MAX_REFS, refs, 0);
regfree(®);
txt[refs[0].rm_eo+1] = '\0';
int n = atoi(txt+refs[0].rm_so);
printf("%d\n", n);
打印
41235
您應該使用lex/yacc來構建適當的解析器。或者,首先使用strtok
標記字符串可能會簡化您的問題。 (注意:正確使用strtok
非常棘手 - 仔細閱讀其文檔。)
我不知道它回答你的問題,但you use varargs
in C允許可變數量的參數的函數。
void myscanf(const char *fmt, ...)
{
}
無益的答案是「不這樣做,正確地寫一個解析器,也許使用lex
和/或yacc
或bison
」。
你問的問題的答案是「是的,你可以做到這一點」。我不相信有什麼理由可以讓更多的可變參數比格式要求,儘管很少會是一件壞事。我假設你有一個數組或可能的格式列表,並且你正在循環中調用sscanf。
您可以使用可變長度參數使用stdarg.h
中提供的宏編寫驗證函數。
例如,
int my_validation_func(const char *format, ...) {
va_list ap;
char *p, *sval;
int ival;
float fval;
va_start(ap, format);
for(p=format; *p ; p++) {
if (*p != '%') {
continue;
}
switch(*++p) {
case 'd':
ival = va_arg(ap, int);
break;
case 'f':
fval = va_arg(ap, float);
break;
case 's':
for (sval = va_arg(ap, char *); *sval; sval++);
break;
default:
break;
}
}
va_end(ap);
}
希望這有助於!
如果你不知道當你寫代碼參數的數量和類型,sscanf()
不能安全地做你想做的事情。
將50個參數傳遞給sscanf()
是可以的(格式字符串不消耗的參數會被求值,但會被忽略),但對應于格式字符串的參數在提升後必須是預期的類型;否則,行爲是不確定的。因此,如果您想要檢測是否可以使用"%d"
或"%f"
掃描字符串,則無法通過單個sscanf()
調用安全地執行此操作。 (很可能,你可以逃脫傳遞void*
指向一個足夠大的緩衝區,但行爲仍是不確定的。)
另一個討厭的問題sscanf()
的是,它不處理數字溢出。這:
char *s = "9999999999999999999999999";
int n;
int result = sscanf(s, "%d", &n);
printf("result = %d, n = %d\n", result, n);
是未定義行爲(假設9999999999999999999999999是太大而不能存儲在int
)。
你的東西可能能夠做的就是找到一個開源sscanf
實施和修改它,它只是驗證對格式字符串,沒有任何存儲。 (處理執行許可留作練習。)如果您發現sscanf
格式的字符串對您的問題特別方便,這很有意義。否則,正則表達式可能是要走的路(不是在C標準中,但很容易找到一個實現)。
正則表達式可能會有幫助。 – Hogan 2011-12-29 21:23:35
@Hogan:Afaik正則表達式不是C標準庫的一部分。 – ryyst 2011-12-29 21:26:12
@ryyst他們不是標準的c,但他們是POSIX – Dave 2011-12-29 21:27:40