【发布时间】:2012-05-18 19:02:14
【问题描述】:
我有一个字符串,我希望它的子字符串从第 5 个位置到最后一个位置。我应该使用哪个功能?
【问题讨论】:
我有一个字符串,我希望它的子字符串从第 5 个位置到最后一个位置。我应该使用哪个功能?
【问题讨论】:
如果您不会将原始字符串用于其他任何内容,则可以直接使用&s[4]。如果您需要副本,请执行
char new_str[STR_SIZE + 1] = {0};
strncpy(new_str, &s[4], STR_SIZE);
【讨论】:
strncpy(),尽管它的名字,被设计用于未终止的字符数组。您的代码可能会留下 new_str 而没有 '\0'。添加new_str[STR_SIZE] = 0 或确保您有足够的空间并使用strcpy()。
您可以使用string.h 头文件中的memcpy() 函数。
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
【讨论】:
如果我理解正确,您需要使用一些分隔符,以便将字符串分解为子字符串。例如“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 之前将其保存。
【讨论】:
如果你也知道字符串中的字符,你想从中获取子字符串,那么你可以使用 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);
这将获取输入字符串instring,从位置pos 开始提取长度为len 的子字符串,并将其作为新字符串返回。
但 64,000 美元的问题是,它将如何返回新字符串?
它可以为新字符串动态分配空间,但 C 的实用函数通常不会这样做。 (我想到的唯一例外是strdup,它甚至不是标准的 C 函数。)
它可以在instring 中插入一个'\0' 字符,然后返回一个指向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-clss string 类型,并且它有一个 substr 方法与之配套。)
【讨论】: