簡體   English   中英

這是通過c中的指針編寫strstr代碼的正確方法嗎?

[英]Is this right approach to write the code of strstr through pointers in c?

char* fstrstr(char *s1,char *s2)
{
    int i=0,flag=0;
    char *s4,*s3;
//  s4 for retaining the value of s2
    s4 = s2;
    while(*s1 != '\0' && *s2 != '\0')
    {
        if(*s1 == *s2)
        {
            *(s3+i) = *s1;
            s2++;
            s1++;
            i++;
            flag = 1;
        }
        else
        {
            i = 0;
            s1++;
//          Initialize s2 again from its address
            s2 = s4;
            flag = 0;
        }
    }
    if(flag == 1)
    {
        while(*s1 != '\0')
        {
            *(s3+i) = *s1;
            i++;
            s1++;
        }
        *(s3+i) = '\0';
    }
    if(flag == 1)
        return (s3);

    if(flag==0)
    {
        *s3 = NULL;
        return (s3);
    }
}

正確的方法是構造測試用例(我認為最好是首先使用,但這不是絕對必要的)。 為成功和不成功的案例(包括任何棘手的邊緣案例)創建單元測試。

另一個建議是使用適當的變量名。 詳細程度不會使您的編譯后的代碼變慢,但確實會使它的可讀性和可維護性大大提高。

我可能還會使用索引而不是指針。 不是因為我不了解它們,而是因為我經常發現它們有助於提高可讀性,並且體面的編譯器會在幕后生成相同的代碼。

建議的測試用例(作為開始):

  • 在字符串開頭成功找到。
  • 在字符串中間成功找到。
  • 成功找到字符串末尾。
  • 找不到字符串。
  • 找到大部分的字符串。
  • 將NULL作為任一參數傳遞。
  • 空字符串作為參數。

從你的代碼的外觀上來看,它似乎你試圖將字符串復制到另一個位置(可能是空值終止),然后返回地址。 這實際上不是ISO strstr工作原理。 它只是返回內容字符串中與搜索字符串匹配的第一個字節的位置。

因此,一個簡單的實現(即使一個體面的編譯器無論如何也可以處理大部分優化,仍可以進行最小優化)如下:

#include <stdio.h>
#include <string.h>

char * fstrstr (char *needle, char *haystack) {
    int nlen, npos, hlen, hpos, hpos2;

    // If length of needle is 0, it's defined as found at start.

    if (*needle == 0) {
        return haystack;
    }

    // Ensure strlen only calculated once.

    nlen = strlen (needle);
    hlen = strlen (haystack);

    // Check every possible position in haystack.

    for (hpos = 0; hpos < hlen - nlen+1; hpos++) {
        // Check each character, ensuring common subexpression elimination.

        for (npos = 0, hpos2 = hpos; npos < nlen; npos++, hpos2++) {
            // No match, break early.

            if (needle[npos] != haystack[hpos2]) {
                break;
            }
        }

        // No early break, we found a match.

        if (npos == nlen) {
            return &(haystack[hpos]);
        }
    }

    // No match anywhere, return NULL.

    return NULL;
}

static char *xlat(char *p) {
    if (p == NULL) return "NULL";
    return p;
}

int main (void) {
    printf ("%s\n", xlat(fstrstr ("hel","hello world")));
    printf ("%s\n", xlat(fstrstr ("el","hello world")));
    printf ("%s\n", xlat(fstrstr ("orl","hello world")));
    printf ("%s\n", xlat(fstrstr ("rld","hello world")));
    printf ("%s\n", xlat(fstrstr ("d","hello world")));
    printf ("%s\n", xlat(fstrstr ("","hello world")));
    printf ("%s\n", xlat(fstrstr ("xyz","hello world")));
    printf ("%s\n", xlat(fstrstr ("xyz","")));
    return 0;
}

輸出:

hello world
ello world
orld
rld
d
hello world
NULL
NULL

請注意,這包括一些單元測試,雖然我尚未對其進行全面測試,但這應該是一個很好的起點。

您沒有初始化s3所以*(s3+i) = *s1是不確定的(讀:很可能是崩潰)。

我在代碼中嘗試了此功能,然后崩潰了。

問題是該行:

*(s3+i) = *s1;

由於尚未為s3分配任何內存,因此您在此處為垃圾位置分配值。

我會說不,這不是正確的方法。 它不僅存在重大錯誤(例如其他人提到的s3的使用),而且還存在

  1. 實現這種特殊的字符串搜索算法所需的時間更長,更復雜,所需的變量數量是其兩倍以上。
  2. 一個非常次優的算法, O(nm) ,其中n是要搜索的字符串的長度, m是模式字符串的長度。

這是字符串搜索算法的一個很好的參考:

http://www-igm.univ-mlv.fr/~lecroq/string/index.html

除非您要使用特別適合您的數據集的高性能數據庫之一,否則不僅僅使用標准庫的strstr函數可能是一個錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM