我有一个字符串,我希望它的子字符串从第 5 个位置到最后一个位置。我应该使用哪个功能?
7 回答
如果您不会将原始字符串用于其他任何内容,则可以直接使用&s[4]
。如果您需要副本,请执行
char new_str[STR_SIZE + 1] = {0};
strncpy(new_str, &s[4], STR_SIZE);
您可以使用头文件memcpy()
中的函数。string.h
memcpy()
在内存块之间复制字节数据,有时称为缓冲区。这个函数不关心被复制的数据类型——它只是进行精确的逐字节复制。函数原型是
void *memcpy(void *dest, void *src, size_t count);
参数 dest 和 src 分别指向目标和源内存块。count 指定要复制的字节数。返回值为 dest。
如果两个内存块重叠,该函数可能无法正常运行—— src 中的某些数据可能在被复制之前被覆盖。使用memmove()
下面讨论的函数来处理重叠的内存块。memcpy()
将在下面的程序中演示。
您还可以在此处找到这些函数的示例: http ://www.java-samples.com/showtutorial.php?tutorialid=591
如果您还知道要从中获取子字符串的字符串中的字符,则可以使用 strstr 函数。它定位子字符串。但是,如果您不知道要从中检索的字符,那么您可以使用 strcpy 或 strncpy 来获取 Eric 提到的字符串。
void substr(char *s, int a, int b, char *t)
{
strncpy(t, s+a, b);
}
最简单但高效的解决方案。声明一些 t char 变量来保存结果,然后只需将 s 作为要操作的字符串传递,a 作为初始偏移量,b 作为要提取的字符串的长度。
char t[255]="";
substr(s, a, b, t);
s+4
这提供了问题中要求的子字符串,而不是子字符串的副本。' s+4
' 返回字符串 's' 的第 5 个位置的子字符串。这是 C 中的一种有效的原始操作,不使用任何函数调用。
如果应用程序需要制作结果的本地副本,例如,如果结果将被修改:
char substring[strlen(s)-3] ;
strcpy(substring, s+4) ;
请注意,这需要一个允许可变大小数组的现代 C 编译器。对于非本地副本,使用 malloc 分配子字符串(例如char *substring = (char *)malloc(strlen(s)-3) ;
),这适用于任何 C 编译器。
我将解释为什么 C 没有标准的子字符串函数,而不是告诉您如何提取子字符串(其他答案已经完成)。
如果 C 确实有一个子字符串函数,它的声明可能看起来像这样:
char *substr(const char *instring, size_t pos, size_t len);
这将获取输入 string ,提取从 position 开始instring
的长度子字符串,并将其作为新字符串返回。len
pos
但 64,000 美元的问题是,它如何返回新字符串?
它可以为新字符串动态分配空间,但 C 的实用程序函数通常不会这样做。(我想到的唯一例外是strdup
,它甚至不是标准的 C 函数。)
它可以在其中插入一个 '\0' 字符instring
,然后返回一个指向 的指针instring
,但这显然会修改instring
,这样的函数不应该这样做。(事实上,这就是为什么我推测substr
这里的假设函数会接受一个const char *
指针。)
所以事实证明,在 C 中,实际上不可能编写一个适当的“实用”子字符串函数,它不进行任何动态内存分配,也不修改原始字符串。
所有这一切都是由于 C 没有一流的字符串类型这一事实造成的。
修改原始字符串是否可以接受完全是调用者的决定。如何为提取的子字符串分配内存完全由调用者决定。substr
因此,假设函数几乎没有什么可做的了。它只是一些指针运算,将它封装在“substr”函数中可能会很好,但它并没有真正为调用者节省任何工作,所以调用者在决定如何做之后最好自己做指针运算它想要处理那些更难的问题。
如果调用者愿意修改原始字符串,那么这样做很简单:
char instring[] = "marshmallow";
int pos = 3, len = 5;
instring[pos + len] = '\0';
char *substr = &instring[pos];
printf("%s\n", substr;
如果调用者想要分配单独的内存,无论是作为数组还是通过调用malloc
,这也很简单:
char *substr = malloc(len + 1);
strncpy(substr, &instring[pos], len);
substr[len] = '0';
因此,如果 C 有一流的字符串类型,它substr
的标准库中肯定会有一个函数——但既然没有,那就没有。(相比之下,C++确实有一个 first-clssstring
类型,并且它有一个与之配套的substr
方法。)
如果我理解正确,您需要使用一些分隔符,以便将字符串分解为子字符串。例如“one#two#three”分为一二三。如果是这样的话:
#include <stdio.h>
#include <string.h>
int main()
{
char test[] = "one#two#three";
char* res;
res = strtok(test, "#");
while(res) {
printf("%s\n", res);
res = strtok(NULL, "#");
}
return 0;
}
您使用要标记的字符串调用 strtok() 一次。以下每个调用都应传递 NULL,以便继续使用第一次调用的字符串。另请注意,strtok 可能会修改原始指针,因此如果它是动态分配的,则应在将其传递给 strtok 之前将其保存。