2012-07-20 56 views
1

我有一個很難理解我應該怎麼做到以下幾點:C:字符串和指針。改變字符串中的子串在一個特定的模式

我有一個像這樣定義的單詞列表:

typedef struct _StringNode { 
    char *str; 
    struct _StringNode* next; 
} StringNode; 

現在我需要編寫一個函數來接收一個字符串和兩個相同長度的單詞列表,並且我需要將字符串中第一個列表中的單詞的每一個外觀與第二個列表中的相應單詞替換掉。

例子:

 text: "stack overflow siteoverflow oveflow stack" 
    patterns: [ "stack", "overflow", "site" ] 
replacements: [ "Hello", "guys", "here" ] 
     result: "Hello guys hereguys guys Hello" 

對於每個字:我試圖使用strstr()所以我會獲得一個指向這個詞的出現在字符串的一個副本,然後再換個詞,並提升文本字符串副本的指針。

char* replace(const char *text, 
       const StringNode *patterns, 
       const StringNode *replacements); 
+0

每個節點都有一個字,這兩個列表包含相同數量的節點。我刪除了代碼,我感覺這是不正確的。 – Numerator 2012-07-20 08:36:54

+1

請注意,不要使用以'_'開頭的名字,後跟大寫字母。它們是[保留](http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html)。在C中,你可以安全地寫'typedef struct StringNode {...} StringNode;' – Shahbaz 2012-07-20 09:07:44

+0

我給列表添加了Python風格的語法,並引用了字符串,以使其更清晰。 – unwind 2012-07-20 09:11:27

回答

1

您可以使用此

char *strnreplace(char *st,const int length, 
        const char *orig,const char *repl) { 

    static char buffer[length]; 
    char *ch; 

    if (!(ch = strstr(st, orig))) 
     return st; 

    strncpy(buffer, st, ch-st); 
    buffer[ch-st] = 0; 
    sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig)); 
    return buffer; 
} 


void replace(const char *text, 
       const StringNode *patterns, 
       const StringNode *replacements) 
{ 
    StringNode *pat, *rep; 
    char *temp = text; 
    int length = strlen(text); 
    for(pat = patterns, rep = replacements; 
     pat->next != NULL; 
     pat = pat->next, rep = rep->next) { 
     temp = strnreplace(temp, length, pat->str, rep->str); 
    } 
} 
0

也許是這樣的:

char* replace(const char *text, 
       const StringNode *patterns, 
       const StringNode *replacements) 
{ 
    char *out = malloc(1024), *put = out; 

    while(*text != '\0) 
    { 
    const StringNode *piter, *riter; 
    int found = 0; 

    /* Check if current start of text matches any pattern. */ 
    for(piter = patterns, riter = replacements; 
     piter != NULL; 
     piter = piter->next, riter = riter->next) 
    { 
     const size_t plen = strlen(piter->str); 
     if(strncmp(text, piter->str, plen) == 0) 
     { 
     /* Hit found, emit replacement. */ 
     const size_t rlen = strlen(riter->str); 
     memcpy(out, riter->str, rlen); 
     out += rlen; 
     text += plen; 
     found = 1; 
     break; 
     } 
    } 
    if(!found) 
     *put++ = *text++; 
    } 
    *put = '\0'; 

    return out; 
} 

注意上面確實手柄緩衝區溢出,不再贅述。我建議在動態字符串數據類型的基礎上實現類似這樣的操作,以使核心操作(追加)根據需要自動增長目標字符串。

UPDATE在迴應的意見,上述正試圖實現的算法是:

set output to empty string 
while text remaining 
    if start of text matches pattern[i] 
    append replacement[i] to output 
    remove len(pattern[i]) characters from start of text 
    else 
    append first character of text to output 
    remove first character of text 

所以,反覆檢查圖案匹配,只要有東西留在text

+1

謝謝你的回答。但是看起來像是每當你找到一個匹配piter-> str的子字符串時,你就改變它並繼續下一個單詞,但是如果文本中有更多的單詞piter-> str子字符串呢? – Numerator 2012-07-20 10:29:35

+0

@Numerator我添加了算法的大綱,希望它可以幫助你理解它。簡而言之,它會檢查「text」的每個單個字符的模式匹配,因此它會在後續匹配中找到它們。 – unwind 2012-07-20 10:58:01

+0

非常感謝@unwind。很有幫助。我會努力:) – Numerator 2012-07-20 11:03:16