C语言 C 子字符串/C 字符串切片?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26620388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C substrings / C string slicing?
提问by guest1
Hy everybody! I am trying to write a program that checks if a given string of text is a palindrome (for this I made a function called is_palindrome that works) and if any of it's substrings is a palindrome, and I can't figure out what is the optimal way to do this:
大家好!我正在尝试编写一个程序来检查给定的文本字符串是否是回文(为此,我创建了一个名为 is_palindrome 的函数,该函数有效),并且如果其中的任何子字符串是回文,我无法弄清楚是什么执行此操作的最佳方法:
For example, for the string s = "abcdefg" it should first check "a", then "ab", "abc", "abcd" and so on, for each character
例如,对于字符串 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, ...)
What function/method is there that I can use in a similar way in C ?
我可以在 C 中以类似的方式使用什么函数/方法?
回答by Crowman
This slice_str()function will do the trick, with endactually being the end character, rather than one-past-the-end as in Python slicing:
这个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;
}
which, when used from the above main()function, outputs:
当从上述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$
回答by Scott Hunter
There isn't; you'll have to write your own.
没有;你必须自己写。
回答by AndersK
In order to check a string, you would need to supply to the number of characters to check in order to check for a palindrome:
为了检查字符串,您需要提供要检查的字符数以检查回文:
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;
}
now you would need to call the function above for each substring (as you described it, i.e. always starting from the beginning) e.g.
现在您需要为每个子字符串调用上面的函数(如您所描述的,即总是从头开始)例如
char candidate[] = "wasitaratisaw";
for (int len = 0; len < strlen(candidate); ++len)
{
if (palindrome(candidate, len))
{
...
}
}
disclaimer: not compiled.
免责声明:未编译。
回答by AndersK
Honestly, you don't need a string slicing function just to check for palindromes within substrings:
老实说,您不需要字符串切片函数来检查子字符串中的回文:
/* 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;
}
With that, you can create the following:
有了它,您可以创建以下内容:
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) */
}
Of course, if you really wanted a string slicing function merely for output (since you technically shouldn't cast a size_tto int), and you still want to be able to format the output easily, the answer by Paul Griffithsshould suffice quite well, or you can use mine or even one of strncpyor the nonstandard strlcpy, though they all have their strengths and weaknesses:
当然,如果您真的想要一个仅用于输出的字符串切片函数(因为从技术上讲您不应该将 a 强制转换为size_tto 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;
}
strsliceactually works like a combination of strncpyand the nonstandard strlcpy, though there are differences between these three functions:
strslice实际上就像是strncpy和 nonstandard的组合strlcpy,尽管这三个函数之间存在差异:
strlcpywill cut the copied string short to add a null terminator atdest[n - 1], so copying exactlynbytes before adding a null terminator requires you to passn + 1as the buffer size.strncpymay not terminate the string at all, leavingdest[n - 1]equal tosrc[n - 1], so you would need to add a null terminator yourself just in case. Ifnis greater than thesrcstring length,destwill be padded with null terminators untilnbytes have been written.strslicewill copy up tonbytes if necessary, likestrncpy, and will require an extra byte for the null terminator, meaning a maximum ofn+1bytes are necessary. It doesn't waste time writing unnecessary null terminators asstrncpydoes. This can be thought of as a "lightweightstrlcpy" with a small difference in whatnmeans and can be used where the resulting string length won't matter.
strlcpy将缩短复制的字符串以在 处添加空终止符dest[n - 1],因此n在添加空终止符之前准确复制字节需要您将其n + 1作为缓冲区大小传递。strncpy可能根本不会终止字符串,留下dest[n - 1]等于src[n - 1],因此您需要自己添加一个空终止符以防万一。如果n大于src字符串长度,dest将用空终止符填充,直到n写入字节。strslicen如有必要,将最多复制字节,例如strncpy,并且需要额外的字节作为空终止符,这意味着需要最多n+1字节。它不会像那样浪费时间编写不必要的空终止符strncpy。这可以被认为是一种“轻量级strlcpy”,在n含义上有很小的差异,并且可以用于结果字符串长度无关紧要的地方。
You could also create a memslicefunction if you wanted, which would allow for embedded null bytes, but it already exists as memcpy.
memslice如果需要,您也可以创建一个函数,它允许嵌入空字节,但它已经作为memcpy.
回答by Coder_Uj
There is not any built-in function/method in any standard C library which can handle this. However, you can come up with your own method to do the same.
任何标准 C 库中都没有任何内置函数/方法可以处理这个问题。但是,您可以想出自己的方法来做同样的事情。

