C子串/ C字符串切片?

时间:2014-10-28 23:38:34

标签: c

大家好! 我正在尝试编写一个程序,检查给定的文本字符串是否为回文(为此我创建了一个名为is_palindrome的函数),如果它的任何子字符串是回文,我可以'找出最佳方法:

例如,对于字符串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中以类似的方式使用哪种功能/方法?

6 个答案:

答案 0 :(得分:6)

这个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()函数时,输出:

paul@horus:~/src/sandbox$ ./allsubstr
Polly
Poll
Pol
Po
P
olly
oll
ol
o
lly
ll
l
ly
l
y
paul@horus:~/src/sandbox$ 

答案 1 :(得分:5)

没有;你必须自己写。

答案 2 :(得分:2)

为了检查字符串,您需要提供要检查的字符数以便检查回文:

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))
    {
    ...
    }
 }

免责声明:未编译。

答案 3 :(得分:1)

老实说,你不需要字符串切片功能来检查子串中的回文:

/* 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_t转换为int),并且你仍然希望能够格式化输出很容易,Paul Griffiths的答案应该足够好,或者你可以使用我的,甚至是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个字节要求您传递n + 1 as缓冲区大小。
  • strncpy可能根本不会终止字符串,dest[n - 1]等于src[n - 1],因此您需要自己添加一个空终结符以防万一。如果n大于src字符串长度,dest将使用空终止符填充,直到写入n字节为止。
  • 如果需要,
  • strslice将复制到n个字节,如strncpy,并且将需要额外的字节用于空终止符,这意味着最多n+1个字节是必要。它不会浪费时间编写不必要的空终止符strncpy。这可以被认为是“轻量级strlcpy”,n的含义差别很小,可以在结果字符串长度无关紧要的情况下使用。

如果需要,您还可以创建一个memslice函数,这将允许嵌入的空字节,但它已经存在为memcpy

答案 4 :(得分:0)

任何标准C库中都没有可以处理此问题的内置函数/方法。但是,您可以提出自己的方法来完成此操作。

答案 5 :(得分:0)

这是我用来在C中获取字符串切片的一个衬里。

void slice(const char *str, char *result, size_t start, size_t end)
{
    strncpy(result, str + start, end - start);
}

非常简单。 鉴于您已经检查了边界并确保结束>开始。