2

例如,如果我有一个字符串:Hi:my:name:is:lacrosse1991:我怎么能用它strtok来检索is(换句话说,第四个字段)?这将类似于您在 bash 中使用 cut 的方式,而我只是这样做cut -d ":" -f 4。如果这是做这种事情的错误功能,请告诉我,非常感谢任何帮助,谢谢!(我最近才开始自学 C,如果这些是我要问的明显问题,我提前道歉)

这是我将使用的 cut 命令的示例

x=$(echo "$death" | cut -d ':' -f 4)
y=$(echo "$death" | cut -d ':' -f 5)
z=$(echo "$death" | cut -d ':' -f 6)
4

3 回答 3

6

如果您知道这是第 4 个字段,您只需调用 strtok() 4 次 - 如果不扫描整个字符串,就无法跳转到第 4 个字段(这就是 strtok 正在做的事情)

于 2012-05-09T03:37:14.483 回答
1

提取第Nth 字段的一种方法(同时在调用后将字符串保持在原始状态)是使用以下getFld函数。首先,必要的标题:

#include <stdio.h>
#include <string.h>
#include <malloc.h>

现在函数本身,我希望记录得足够好:

char *getFld (char *srchStr, char delim, int numFld) {
    char *copyStr, *retStr, *tmpStrPtr, delims[2];

    // Make a copy so as to not damage original.

    if ((copyStr = strdup (srchStr)) == NULL) return NULL;

    // Create delimiter string from character.

    delims[0] = delim; delims[1] = '\0';
    retStr = NULL;

    // Start loop, extracting fields.

    tmpStrPtr = strtok (copyStr, delims);
    while (tmpStrPtr != NULL) {
        // If this is the field we want, make a copy.

        if (numFld == 0) retStr = strdup (tmpStrPtr);

        // Get next field.

        tmpStrPtr = strtok (NULL, delims);
        numFld--;
    }

    // Clean up, return field copy (must be freed eventually) or NULL.

    free (copyStr);
    return retStr;
}

最后,还有一个测试程序:

int main (void) {
    int i = 0;
    char str[] = "Hi:my:name:is:lacrosse1991";
    char *fld;
    while ((fld = getFld (str, ':', i)) != NULL) {
        printf ("Field %d is '%s'\n", i, fld);
        free (fld);
        i++;
    }
    return 0;
}

编译并运行后,我得到:

Field 0 is 'Hi'
Field 1 is 'my'
Field 2 is 'name'
Field 3 is 'is'
Field 4 is 'lacrosse1991'

现在,请记住,这strdup不是标准 C,但是,如果您的实现没有它,您可以使用这个。您可能还想更改strdup失败时的行为,因为当前案例无法与超出范围的字段区分开来。

但是,这个代码应该可以作为开始的基线。

于 2012-05-09T04:10:50.580 回答
1

我会避免strtok为此目的(以及大多数其他人,就此而言)。在这种情况下,我想我只会使用sscanf转换scanset

char field_four[128];   
sscanf(input_string, "%*[^:]:%*[^:]:%*[^:]:%127[^:]:", field_four);

在此,我们从重复%*[^:]:三遍开始。其中每一个都读取一个字符串,包括除冒号之外的任何字符,然后是冒号。*应该从输入中读取但被忽略(未分配给任何东西)的方法。然后,对于第四个字段,我们有相同的内容,除了我们包含*,因此该字段确实被分配,在本例中为field_four(尽管您显然应该使用更有意义的名称)。

对于第四个字段,我还添加了最大长度的规范。由于sscanf总是包含 a\0来终止字符串,但不包含在计数中,我们需要指定一个比缓冲区大小小一的大小。

于 2012-05-09T04:21:36.053 回答