如果我有搜索的字符串:C:在文件
const char *mystr = "cheesecakes";
FILE *myfile = fopen("path/to/file.exe","r");
我需要編寫一個函數來確定myfile
是否含有任何mystr
出現。任何人都可以幫我嗎?謝謝!
更新:所以原來我需要部署的平臺沒有memstr
。有誰知道我可以在我的代碼中使用的免費實現?
如果我有搜索的字符串:C:在文件
const char *mystr = "cheesecakes";
FILE *myfile = fopen("path/to/file.exe","r");
我需要編寫一個函數來確定myfile
是否含有任何mystr
出現。任何人都可以幫我嗎?謝謝!
更新:所以原來我需要部署的平臺沒有memstr
。有誰知道我可以在我的代碼中使用的免費實現?
如果無法適應整個文件到內存中,你可以訪問GNU memmem()
擴展,則:
memmem(buffer, len, mystr, strlen(mystr) + 1)
搜索緩衝區;strlen(mystr)
個字符以外的所有字符,並將其移動到開頭;如果沒有memmem
做,那麼你就可以在普通的C使用memchr
和memcmp
實現它,就像這樣:
/*
* The memmem() function finds the start of the first occurrence of the
* substring 'needle' of length 'nlen' in the memory area 'haystack' of
* length 'hlen'.
*
* The return value is a pointer to the beginning of the sub-string, or
* NULL if the substring is not found.
*/
void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
{
int needle_first;
const void *p = haystack;
size_t plen = hlen;
if (!nlen)
return NULL;
needle_first = *(unsigned char *)needle;
while (plen >= nlen && (p = memchr(p, needle_first, plen - nlen + 1)))
{
if (!memcmp(p, needle, nlen))
return (void *)p;
p++;
plen = hlen - (p - haystack);
}
return NULL;
}
謝謝;我最終將整個內容加載到內存中,然後使用memmem找到針。 – igul222 2010-02-03 03:03:20
因爲沒有將memmem或memstr要查找一個字符串二進制數組(其他人建議將它讀入內存並使用strstr - 不行這不行),你必須用「fgetch」逐字節地讀取它,並在讀取時寫一個小型狀態機來匹配它。
如果你在Linux上,不關心可移植性,glibc確實有memmem。 – 2010-02-03 00:56:52
逐字節加載會損害性能。將其加載到內存中,然後在內存中搜索它。 – EvilTeach 2010-02-03 03:05:06
chat match = "findthis";
int depth = 0;
while(not eof)
{
char ch = getonebyte();
if(ch == match[depth])
{
if (depth == strlen(match))
break;
else
depth++;
}
else
depth = 0;
}
粗略(我相信有是關閉那些在那裏)
不錯的嘗試。不幸的是,這有一個邊緣情況下,當你有一個搜索字符串像「112」,並在文件中,你有「1112」 – 2010-02-03 01:03:42
它會失敗,我不這麼認爲,我開始在匹配字符串的開始,當我遇到不匹配 – pm100 2010-02-03 01:19:16
pm100,是的,你重置你的針頭索引,但你已經失去了你需要的草垛的一部分。 – 2010-02-03 03:08:00
這裏是它的一個拼湊版。它沒有錯誤檢查,可能有溢出錯誤。但我認爲它找到了所需的字符串並說明了部分子字符串匹配所需的回溯。我懷疑還有超過15個錯誤。
編輯:第一個答案中至少有一個。我半夜醒來,意識到回溯檢查是錯誤的。它沒有在'1212123'中找到'12123'。它可能仍然是錯誤的,但至少它現在找到了一個。
int main(int argc, char* argv[])
{
FILE *fp;
char *find, *hist;
int len, pos=0, hl=0, i;
char c;
fp = fopen(argv[1], "r");
find = argv[2];
len = (int)strlen(find);
hist = malloc(len);
memset(hist, 0, len);
while (!feof(fp)) {
c = fgetc(fp);
if (find[pos++] == c) {
if (pos == len) {
printf("Found it\n");
return 1;
}
}
else {
// check history buffer (kludge for backtracking)
if (pos > 0) {
pos = 0;
for (i = 0; i < len - 1; i++)
if (0 == memcmp(hist+len-i-1, find, i + 1)) {
// we had a mismatch, but the history matches up to len i
pos = i;
}
}
}
// update history buffer - this is innefficient - better as circular buffer
memmove(hist, hist + 1, len - 1);
hist[len-1] = c;
}
printf("Not found\n");
}
在這裏看到:
http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
在C99一博耶摩爾定律的實現。這是一個非常常見的字符串搜索算法,並以O(n)運行。
這是一個函數,它將搜索緩衝區中的字符串。
限制:它不處理寬字符(在國際化的情況下)。您必須編寫自己的代碼才能將文件讀入內存。如果模式在2個讀緩衝區之間分割,它將不會找到模式。
/*****************************************************
const char *buffer pointer to your read buffer (the larger, the better).
size_t bufsize the size of your buffer
const char *pattern pattern you are looking for.
Returns an index into the buffer if pattern is found.
-1 if pattern is not found.
Sample:
pos = findPattern (buffer, BUF_SIZE, "cheesecakes");
*****************************************************/
int findPattern (const char *buffer, size_t bufSize, const char *pattern)
{
int i,j;
int patternLen;
// minor optimization. Determine patternLen so we don't
// bother searching buffer if fewer than patternLen bytes remain.
patternLen = strlen (pattern);
for (i=0; i<bufSize-patternLen; ++i)
{
for (j=0; j<patternLen; ++j)
{
if (buffer[i+j] != pattern[j])
{
break;
}
}
if (j == patternLen)
{
return i;
}
}
return -1;
}
你可以加載整個文件到內存中嗎? – 2010-02-03 00:44:42
這不是太大(<2MB),但我不知道(我到目前爲止已經有大約30分鐘的C經驗) – igul222 2010-02-03 00:55:49
我已經在我的答案中加入了memmem的實現 - 並且memstr(mem,memlen ,str)'只是'memmem(mem,memlen,str,strlen(str)+ 1)'。 – caf 2010-02-03 01:29:40