strtok is不按预期返回,我在使用错误吗?

发布于 2025-01-17 13:45:12 字数 1548 浏览 1 评论 0原文

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

// fiter string to the first |
char* filterstringfirst(char* command, int i){
    char *tok = command;
    int x = 0;
    while ((tok = strtok(tok, "|")) != NULL && x <= i)
    {
        if( x == i){
            return tok;
        }
        x++;
        printf(" ===  Parsed: --%s-- ===\n", tok);
        tok = NULL;
    }
    return tok;
        
}


int main () {
    char command[]  = "ls -a | sort -h | grep h | wc -l";
    
    char command2[]  = "ls -a | sort -h | grep h | wc -l";
    char* temp = command;

    char* x =  filterstringfirst(temp, 0);
    printf("%s\n",x);
    char* temp2 = command;

    char* x2 =  filterstringfirst(temp2, 1);
    printf("%s\n",x2);
    
    
   
    temp = command;
    

   return 0;
}

我拥有的功能应该只是返回字符串的一部分。原始字符串应类似于“ LS -L | Grep Temp | Sort”。

这个想法是将其用字符串和一个数字调用,然后返回该细分市场。例如。 0-&GT; 现在, “ LS -L”

这是我第一次称呼它的时候起作用,但是再次打电话给它似乎在segfault中打破并结束。

char command[]  = "ls -a | sort -h | grep h | wc -l";
char* temp = command;

char* x =  filterstringfirst(temp, 0);
printf("%s\n",x);
char* temp2 = command;

char* x2 =  filterstringfirst(temp2, 1);
printf("%s\n",x2);`

这是我的测试代码

和输出:

ls -a  
===  Parsed: --ls -a -- === 
[1]    1126 segmentation fault  ./templ
 ➜  Current gcc -o templ templ.c
 ➜  Current ./templ ls -a  
===  Parsed: --ls -a -- === [1]   
 1136 segmentation fault  ./templ

编辑:更新以具有主(根据注释)

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

// fiter string to the first |
char* filterstringfirst(char* command, int i){
    char *tok = command;
    int x = 0;
    while ((tok = strtok(tok, "|")) != NULL && x <= i)
    {
        if( x == i){
            return tok;
        }
        x++;
        printf(" ===  Parsed: --%s-- ===\n", tok);
        tok = NULL;
    }
    return tok;
        
}


int main () {
    char command[]  = "ls -a | sort -h | grep h | wc -l";
    
    char command2[]  = "ls -a | sort -h | grep h | wc -l";
    char* temp = command;

    char* x =  filterstringfirst(temp, 0);
    printf("%s\n",x);
    char* temp2 = command;

    char* x2 =  filterstringfirst(temp2, 1);
    printf("%s\n",x2);
    
    
   
    temp = command;
    

   return 0;
}

I have this function I made which is supposed to just return part of a string. The original string should be similar to "ls -l | grep temp | sort".

The idea was that it would be called with the string and a number, and return that segment. Eg. 0 -> "ls -l"

Now this works the first time I call it, but calling it again seems to break and end in a segfault.

char command[]  = "ls -a | sort -h | grep h | wc -l";
char* temp = command;

char* x =  filterstringfirst(temp, 0);
printf("%s\n",x);
char* temp2 = command;

char* x2 =  filterstringfirst(temp2, 1);
printf("%s\n",x2);`

This was my testing code

And the output:

ls -a  
===  Parsed: --ls -a -- === 
[1]    1126 segmentation fault  ./templ
 ➜  Current gcc -o templ templ.c
 ➜  Current ./templ ls -a  
===  Parsed: --ls -a -- === [1]   
 1136 segmentation fault  ./templ

Edit: Updated to have main too (based on comments)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断桥再见 2025-01-24 13:45:12

strtok IS 破坏性 - 它通过替换定界符将无效字节来修改传递的缓冲区。

命令

char* x =  filterstringfirst(temp, 0);

将有效地为“ LS -A”

如果您想在此处使用strtok,则需要:

  • 模拟strtok在包装函数中,通过传递null和从随后的电话或

    开始的位置

  • 通过传递null以及从 令牌。

第二个示例,没有错误处理:

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

char *get_token_at(char *command, size_t n) {
    size_t position = 0;
    char *copy = strdup(command);
    char *token = strtok(copy, "|");
    char *output = NULL;

    while (token && position < n) {
        token = strtok(NULL, "|");
        position++;
    }

    if (token && position == n)
        output = strdup(token);

    free(copy);

    return output;
}

int main(void) {
    char command[]  = "ls -a | sort -h | grep h | wc -l";

    char *x = get_token_at(command, 0);
    puts(x);
    free(x);

    x = get_token_at(command, 1);
    puts(x);
    free(x);
}

stdout

ls -a 
 sort -h

(请注意这些令牌中的空格。)

strtok is destructive - it modifies the buffer passed in by replacing delimiters will null bytes.

After

char* x =  filterstringfirst(temp, 0);

command will effectively be "ls -a ".

If you want to use strtok here, you will either need to:

  • mimic strtok in your wrapping function, by passing NULL and the position to start from in subsequent calls, or

  • duplicate the string before using it, and return a copy of the token.

An example of the second, with no error handling:

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

char *get_token_at(char *command, size_t n) {
    size_t position = 0;
    char *copy = strdup(command);
    char *token = strtok(copy, "|");
    char *output = NULL;

    while (token && position < n) {
        token = strtok(NULL, "|");
        position++;
    }

    if (token && position == n)
        output = strdup(token);

    free(copy);

    return output;
}

int main(void) {
    char command[]  = "ls -a | sort -h | grep h | wc -l";

    char *x = get_token_at(command, 0);
    puts(x);
    free(x);

    x = get_token_at(command, 1);
    puts(x);
    free(x);
}

stdout:

ls -a 
 sort -h

(Note the whitespace in these tokens.)

很快妥协 2025-01-24 13:45:12

函数strtok通过在分界符的位置插入零字符'\ 0'来更改传递的字符串。

因此,在函数的第一个调用filterstringfirst

char* x =  filterstringfirst(temp, 0);

字符阵列命令看来

"ls -a \0 sort -h | grep h | wc -l";
       ^^^

实际上您具有以下字符串“ ls -a”存储在数组命令中。

因此,第二次调用第二个参数大于0的函数,因此您将获得无效指针。

如果要提取指定索引的子字符串,则应使用函数strspnstrcspn,然后从函数返回一个动态分配的包含目标基因的数组。

这是一个演示程序,该程序显示如何使用标准字符串函数strspnstrcspn and 而无需动态创建源字符串的副本(该功能每次调用函数时效率低下且不安全)。

#include <string.h>
#include <stdlib.h>
#include <string.h>

char * filterstringfirst( const char *command, const char *delimiters, size_t i ) 
{
    char *substring = NULL;

    const char *p = command;
    size_t n = 0;

    do
    {
        p += n;
        p += strspn( p, delimiters );
        n = strcspn( p, delimiters );
    } while (*p && i--);

    if ( *p && ( substring = malloc( n + 1 ) ) != NULL )
    {
        memcpy( substring, p, n );
        substring[n] = '\0';
    }

    return substring;
}

int main( void )
{
    char command[] = "ls -a | sort -h | grep h | wc -l";
    const char *delimiters = "|";

    char *substring = NULL;

    for (size_t i = 0;
        ( substring = filterstringfirst( command, delimiters, i ) ) != NULL;
        i++)
    {
        printf( "%zu: \"%s\"\n", i, substring );
        free( substring );
    }
}

程序输出是

0: "ls -a "
1: " sort -h "
2: " grep h "
3: " wc -l"

您可以将此功能与用于分离字符串的任何定界器一起使用。

The function strtok changes the passed string by inserting zero characters '\0' in the positions of delimiters.

So after the first call of the function filterstringfirst

char* x =  filterstringfirst(temp, 0);

the character array command looks like

"ls -a \0 sort -h | grep h | wc -l";
       ^^^

That is in fact you have the following string "ls -a " stored in the array command.

So calling the function the second time with the second argument greater than 0 you will get as a result a null pointer.

If you want to extract substrings specifying an index then you should use functions strspn and strcspn and return from the function a dynamically allocated array containing the target substring.

Here is a demonstration program that shows how the function can be defined using the standard string functions strspn and strcspn and without creating dynamically a copy of the source string (that is inefficient and unsafe) each time when the function is called.

#include <string.h>
#include <stdlib.h>
#include <string.h>

char * filterstringfirst( const char *command, const char *delimiters, size_t i ) 
{
    char *substring = NULL;

    const char *p = command;
    size_t n = 0;

    do
    {
        p += n;
        p += strspn( p, delimiters );
        n = strcspn( p, delimiters );
    } while (*p && i--);

    if ( *p && ( substring = malloc( n + 1 ) ) != NULL )
    {
        memcpy( substring, p, n );
        substring[n] = '\0';
    }

    return substring;
}

int main( void )
{
    char command[] = "ls -a | sort -h | grep h | wc -l";
    const char *delimiters = "|";

    char *substring = NULL;

    for (size_t i = 0;
        ( substring = filterstringfirst( command, delimiters, i ) ) != NULL;
        i++)
    {
        printf( "%zu: \"%s\"\n", i, substring );
        free( substring );
    }
}

The program output is

0: "ls -a "
1: " sort -h "
2: " grep h "
3: " wc -l"

You can use this function with any delimiters used to separate a string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文