我想知道我们会将字符串拆分为令牌或任何其他有效的方法。
即。我有......
char string1[] = "hello\tfriend\n";
我如何在他们自己的独立变量中获得“你好”和“朋友”?
答案 0 :(得分:2)
这是一个非常简单的示例,使用开始和结束指针将字符串拆分为保存在字符数组数组中的部分。 MAXL
和MAXW
定义只是一种方便的方法来定义用于将单个字长限制为32(31个字符+空终止符)和最多3个字(部分)的常量。原始字符串:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 32
#define MAXW 3
int main (void) {
char string1[] = "hello\tfriend\n";
char *sp = string1; /* start pointer */
char *ep = string1; /* end pointer */
unsigned c = 0; /* temp character */
unsigned idx = 0; /* index for part */
char strings[MAXW][MAXL] = {{0}}; /* array to hold parts */
while (*ep) /* for each char in string1 */
{
if (*ep == '\t' || *ep == '\n') /* test if \t or \n */
{
c = *ep; /* save character */
*ep = 0; /* replace with null-termator */
strcpy (strings[idx], sp); /* copy part to strings array */
*ep = c; /* replace w/original character */
idx++; /* increment index */
sp = ep + 1; /* set start pointer */
}
ep++; /* advance to next char */
}
printf ("\nOriginal string1 : %s\n", string1);
unsigned i = 0;
for (i = 0; i < idx; i++)
printf (" strings[%u] : %s\n", i, strings[i]);
return 0;
}
<强>输出强>
$ ./bin/split_hello
Original string1 : hello friend
strings[0] : hello
strings[1] : friend
使用strtok
只需用函数调用替换手动指针逻辑即可拆分字符串。
更新了行结束处理示例
正如您所发现的,当您单步执行字符串时,您可以创建一个简单的示例,因为您需要适应当前字符串,但只需稍加努力就可以扩展代码以处理更广泛的情况。在您的评论中,您注意到上述代码无法处理字符串末尾没有newline
的情况。通过一些思考,您可以改进代码,以便处理这两种情况,而不是更改代码来处理这种情况。一种方法是:
while (*ep) /* for each char in string1 */
{
if (*ep == '\t' || *ep == '\n') /* test if \t or \n */
{
c = *ep; /* save character */
*ep = 0; /* replace with null-termator */
strcpy (strings[idx], sp); /* copy part to strings array */
*ep = c; /* replace w/original character */
idx++; /* increment index */
sp = ep + 1; /* set start pointer */
}
else if (!*(ep + 1)) { /* check if next is ending */
strcpy (strings[idx], sp); /* handle no ending '\n' */
idx++;
}
ep++; /* advance to next char */
}
打破任何格式/非打印字符
继续扩展可用于分隔字符串的字符,而不是使用离散值来识别哪些字符划分字,您可以使用一系列ASCII值将所有非打印或格式字符标识为分隔符。可以使用稍微不同的方法:
char string1[] = "\n\nhello\t\tmy\tfriend\tagain\n\n";
char *p = string1; /* pointer to char */
unsigned idx = 0; /* index for part */
unsigned i = 0; /* generic counter */
char strings[MAXW][MAXL] = {{0}}; /* array to hold parts */
while (*p) /* for each char in string1 */
{
if (idx == MAXW) { /* test MAXW not exceeded */
fprintf (stderr, "error: MAXW (%d) words in string exceeded.\n", MAXW);
break;
}
/* skip each non-print/format char */
while (*p && (*p < ' ' || *p > '~'))
p++;
if (!*p) break; /* if end of s, break */
while (*p >= ' ' && *p <= '~') /* for each printable char */
{
strings[idx][i] = *p++; /* copy to strings array */
i++; /* advance to next position */
}
strings[idx][i] = 0; /* null-terminate strings */
idx++; /* next index in strings */
i = 0; /* start at beginning char */
}
这将处理您的测试字符串,无论行结束如何,无论包含的标签或换行符的数量如何。请查看ASCII Table and Description作为所用字符范围的参考。