获取不修改原始字符串的单个标记的一种简单方法是使用两次对strcspn() 的调用,建立指向第一个分隔符(在本例中为'$')的起始指针和指向令牌中的最后一个字符(第二个 '$' 之前的字符或字符串结尾,如果不存在第二个 '$')。然后验证开始指针和结束指针之间是否存在字符,并使用memcpy() 复制令牌。
一个简短的例子是:
#include <stdio.h>
#include <string.h>
int main (void) {
char txt[80] = "Some text before $11/01/2017$",
*sp = txt + strcspn (txt, "$"), /* start ptr to 1st '$' */
*ep = sp + strcspn (*sp ? sp + 1 : sp, "$\n"), /* end ptr to last c in token */
result[sizeof txt] = ""; /* storage for result */
if (ep > sp) { /* if chars in token */
memcpy (result, sp + 1, ep - sp); /* copy token to result */
result[ep - sp] = 0; /* nul-termiante result */
printf ("%s\n", result); /* output result */
}
else
fputs ("no characters in token\n", stderr);
}
(注意:三元只处理txt是空字符串的情况。'\n'被添加为第二个分隔符的一部分来处理字符串从fgets() 或POSIX getline() 过去,其中不存在第二个'$','\n' 是字符串中的最后一个字符。)
也适用于空字符串、零、一个或两个'$' 的任意组合,并且不会修改原始字符串,因此可以安全地与 String-Literals 一起使用。
使用/输出示例
$ ./bin/single_token
11/01/2017
如果您还有其他问题,请告诉我。
允许有效空字符串作为结果的变体
@chqrlie 提供的一个巧妙的改进是对(*sp == '$') 的测试而不是(ep > sp) 将允许空字符串(令牌中没有字符)成为有效结果——我同意)。更改将是:
if (*sp == '$') { /* if chars in token */
memcpy (result, sp + 1, ep - sp); /* copy token to result */
result[ep - sp] = 0; /* nul-termiante result */
printf ("%s\n", result); /* output result */
}
因此,如果您想将空令牌(如 .csv 中的空字段,例如 "one,,three,four")视为有效令牌,请使用此替代方法。