2014-10-28 36 views
0

大家好! 我想寫一個程序,檢查給定的文本字符串是否是迴文(爲此我做了一個名爲is_palindrome的函數),如果它的任何子字符串是迴文,我不知道什麼是最佳方式:C子串/ C串切片?

例如,對於字符串s =「abcdefg」,應首先檢查「a」,然後「ab」,「abc」,「abcd」等等,對於每個字符

In Python this is the equivalent of 
s[:1], s[:2], ...  (a, ab, ...) 
s[1:2], s[1:3] ...  (b, bc, ...) 

有什麼功能/方法可以在C中以類似的方式使用?

+1

如果您不想(或不能)更改源字符串,您需要製作每個子字符串的副本,例如如果你在Linux上使用[strndup(s + start,length)](http://linux.die.net/man/3/strndup)。你需要提取子字符串嗎?你能比較一下人物序列嗎? – Rup 2014-10-28 23:42:03

+2

C不是我爲花哨的字符串處理選擇的語言。你將不得不手動索引所有的子串。 – 2014-10-28 23:44:22

回答

4

沒有;你必須自己寫。

2

slice_str()功能就可以了,與end實際上正在結束字符,而不是一個過去最端如在Python切片:

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

void slice_str(const char * str, char * buffer, size_t start, size_t end) 
{ 
    size_t j = 0; 
    for (size_t i = start; i <= end; ++i) { 
     buffer[j++] = str[i]; 
    } 
    buffer[j] = 0; 
} 

int main(void) { 
    const char * str = "Polly"; 
    const size_t len = strlen(str); 
    char buffer[len + 1]; 

    for (size_t start = 0; start < len; ++start) { 
     for (int end = len - 1; end >= (int) start; --end) { 
      slice_str(str, buffer, start, end); 
      printf("%s\n", buffer); 
     } 
    } 

    return 0; 
} 

其中,從上述main()函數一起使用時,輸出:

[email protected]:~/src/sandbox$ ./allsubstr 
Polly 
Poll 
Pol 
Po 
P 
olly 
oll 
ol 
o 
lly 
ll 
l 
ly 
l 
y 
[email protected]:~/src/sandbox$ 
1

爲了檢查一個字符串,你就需要提供到的字符數,以檢查是否有迴文檢查:

int palindrome(char* str, int len) 
{ 
    if (len < 2) 
    { 
    return 0; 
    } 
    // position p and q on the first and last character 
    char* p = str; 
    char* q = str + len - 1; 
    // compare start char with end char 
    for (; p < str + len/2; ++p, --q) 
    { 
    if (*p != *q) 
    { 
     return 0; 
    } 
    } 
    return 1; 
} 

現在您需要爲每個子字符串調用上面的函數(如您所描述的那樣,即始終從頭開始),例如

char candidate[] = "wasitaratisaw"; 
for (int len = 0; len < strlen(candidate); ++len) 
{ 
    if (palindrome(candidate, len)) 
    { 
    ... 
    } 
} 

免責聲明:未編譯。

0

老實說,你並不需要一個字符串切割功能只是爲了子內檢查迴文:

/* start: Pointer to first character in the string to check. 
* end: Pointer to one byte beyond the last character to check. 
* 
* Return: 
* -1 if start >= end; this is considered an error 
* 0 if the substring is not a palindrome 
* 1 if the substring is a palindrome 
*/ 
int 
ispalin (const char *start, const char *end) 
{ 
    if (start >= end) 
    return -1; 

    for (; start < end; ++start) 
    if (*start != *--end) 
     return 0; 

    return 1; 
} 

有了這一點,你可以創建以下文件:

int 
main() 
{ 
    const char *s = "madam"; 

    /* i: index of first character in substring 
    * n: number of characters in substring 
    */ 
    size_t i, n; 

    size_t len = strlen (s); 

    for (i = 0; i < len; ++i) 
    { 
     for (n = 1; n <= len - i; ++n) 
     { 
      /* Start of substring. */ 
      const char *start = s + i; 

      /* ispalin(s[i:i+n]) in Python */ 
      switch (ispalin (start, start + n)) 
      { 
      case -1: 
       fprintf (stderr, "error: %p >= %p\n", (void *) start, (void *) (start + n)); 
       break; 
      case 0: 
       printf ("Not a palindrome: %.*s\n", (int) n, start); 
       break; 
      case 1: 
       printf ("Palindrome: %.*s\n", (int) n, start); 
       break; 
      } /* switch (ispalin) */ 
     } /* for (n) */ 
    } /* for (i) */ 
} 

當然,如果你真的只想輸出字符串切片功能(因爲你在技術上不應該投size_tint),你仍然希望能夠容易地格式化輸出,Paul Griffiths的答案應該足夠qui忒好了,或者你可以用我的或者strncpy或非標準strlcpy連一個,但他們都有自己的長處和短處:

/* dest must have 
*  1 + min(strlen(src), n) 
* bytes available and must not overlap with src. 
*/ 
char * 
strslice (char *dest, const char *src, size_t n) 
{ 
    char *destp = dest; 

    /* memcpy here would be ideal, but that would mean walking the string twice: 
    * once by calling strlen to determine the minimum number of bytes to copy 
    * and once for actually copying the substring. 
    */ 
    for (; n != 0 && *src != 0; --n) 
    *destp++ = *src++; 

    *destp = 0; 

    return dest; 
} 

strslice實際工作像strncpy和非標準strlcpy組合,雖然有這三個函數之間的差異:

  • strlcpy將削減被複制字符串短於在dest[n - 1]添加空終止子,所以複製完全相同n字節添加空TE之前rminator要求您將n + 1作爲緩衝區大小。
  • strncpy可能根本不會終止字符串,因此dest[n - 1]等於src[n - 1],所以您需要自己添加空終止符以防萬一。如果n大於src字符串長度,則dest將填充空終止符,直到寫入n個字節。
  • strslice將根據需要複製到n字節,如strncpy,並且將需要額外的空字符作爲空終止符,這意味着最大需要n+1字節。它不會浪費時間寫入不必要的空終止符,如strncpy所做的那樣。這可以被認爲是「輕量級strlcpy」,其中n的含義差別很小,並且可以在產生的字符串長度無關緊要的情況下使用。

如果需要,您也可以創建memslice函數,這將允許嵌入的空字節,但它已經存在爲memcpy