Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C strtok:如何在两个不同的缓冲区中存储令牌_C_Buffer_Strtok - Fatal编程技术网

C strtok:如何在两个不同的缓冲区中存储令牌

C strtok:如何在两个不同的缓冲区中存储令牌,c,buffer,strtok,C,Buffer,Strtok,我有一个字符串,其中包含变量的数据类型和地址。这些值由“//”分隔,它们是交替的(type///address///type///address…)。这些元组的数量是不固定的,可以根据执行情况而变化 现在我的问题是如何在循环中处理字符串,因为strtok需要先用原始字符串调用,然后用NULL参数调用,但在循环中必须调用两次。因此,在第一个循环之后,strtok被调用三次,这导致strtok执行的计数不均匀,而它应该是偶数。我试图通过处理循环外的第一个元组(因为必须使用原始字符串调用strtok)

我有一个字符串,其中包含变量的数据类型和地址。这些值由“//”分隔,它们是交替的(type///address///type///address…)。这些元组的数量是不固定的,可以根据执行情况而变化

现在我的问题是如何在循环中处理字符串,因为strtok需要先用原始字符串调用,然后用NULL参数调用,但在循环中必须调用两次。因此,在第一个循环之后,strtok被调用三次,这导致strtok执行的计数不均匀,而它应该是偶数。我试图通过处理循环外的第一个元组(因为必须使用原始字符串调用strtok)并处理循环内的其余元组来解决这个问题

char mystring[128];
char seperator[] = "///";
char *part;
int type [128];
int address [128];
number_of_variables = 0;

part = strtok(mystring, seperator);
type[number_of_variables] = (int) atoi(part);
part = strtok(NULL, seperator);
address[number_of_variables] = (int)strtol(part, NULL, 16);

while(part != NULL){
    part = strtok(NULL, seperator);
    type[number_of_variables] = (int) atoi(part);


    part = strtok(NULL, seperator);
    address[number_of_variables] = (int)strtol(part, NULL, 16);

    number_of_variables++;
}
所以现在我有一个偶数的strtok执行,但是如果我的字符串包含例如2个元组,它将第二次进入循环,因此第五次调用strtok,这会导致程序崩溃,因为atoi()得到了一个错误的指针

编辑: mystring的示例:

"1///0x37660///2///0x38398"

1和2是进一步程序的类型标识符。

我可以建议如下循环,如下面的演示程序所示

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

int main(void) 
{
    char mystring[128] = "1///0x37660///2///0x38398";
    char separator[] = "/ ";
    int type [128];
    int address [128];

    size_t number_of_variables = 0;

    for ( char *part = strtok( mystring, separator ); part; part = strtok( NULL, separator ) )
    {
        type[number_of_variables] = atoi(part);
        part = strtok( NULL, separator );
        address[number_of_variables] = part ? (int)strtol(part, NULL, 16) : 0;
        ++number_of_variables;
    }

    for ( size_t i = 0; i < number_of_variables; i++ )
    {
        printf( "%d\t%x\n", type[i], address[i] );
    }

    return 0;
}

您可以编写一个健壮、快速的解析器,它保证能够正常工作,并且没有像这样的bug

文件:lexer.l

用gcc、bison和flex编译这篇文章相当简单

bison-d解析器.y
灵活词汇量
gcc-Wno未使用的函数-Wall-Werror lex.yy.c parser.tab.c-o parserparser
当然,这个程序需要一些调整,根据您的需要进行调整应该很简单


只要找到一个关于bison和flex的简单教程,就可以帮助您完全理解这段代码。

您可以提供一些输入字符串的示例吗?为什么不检查
part=strtok(NULL,分隔符)的结果atoi
之前,code>是否为NULL?您知道
strtok
将第二个参数视为要查找的单个字符的delimeter列表,而不是可能是字符串的单个delimeter?因此,delimeters为
“///”
,string为
“1///0x37660/…”将看到一个1,然后是NULL,然后是NULL,然后是“0x37660”。请参阅手册页中的
strtok`。添加到@Lougler的注释中,您可能希望使用
strstrstr()
,它与
strtok()
不同,是可重入的,可用于常量字符串(不修改其参数),并且可以使用任何字符串作为分隔符。是,Vlad的解决方案将起作用,因为他正确地处理了strtok
。原始字符串包含5个值。所以它不是元组字符串,因为原始字符串必须包含偶数个values@Gora没关系。它与您的解决方案配合使用,即使我不理解它。尤其是那个?接线员和电话:0我不知道unterstand@Gora看起来你指的是条件运算符,或者换句话说,三元运算符。如果strtok返回NULL,则默认情况下数组地址的元素值设置为0。您可以选择任何其他值或发出错误信号,而不是0。@Gora它们在C中称为三元运算符。感谢您提供详细的解决方案。不幸的是,我的代码运行在一个更大项目的MatlabS函数中,因此我无法更改编译器或项目指南。我不喜欢当前的解决方案,我不确定是否有一些情况下它不起作用(尽管我还没有找到),但我无能为力;)@Gora我明白了,要找到适合您的情况的其他解析器生成器并不难。虽然我一点也不懂matlab,但对于手头的问题来说,这可能是过火了。
1   37660
2   38398
%{
#include <stdio.h>
#include "parser.tab.h"
int yyerror(const char *const message);
%}

%option noyywrap
%x IN_ADDRESS

DECIMAL [0-9]+
HEX "0x"[a-fA-F0-9]+
DELIMITER "///"
%%

<*>{DELIMITER} { return DELIMITER; }

<INITIAL>{DECIMAL} {
        char *endptr;
        // Make the lexer know that we are expecting a
        // hex number
        BEGIN(IN_ADDRESS);
        // Asign the value to use by bison
        yylval = strtol(yytext, &endptr, 10);
        // Check conversion's success
        if (*endptr != '\0')
            return ERROR;
        return TYPE;
    }

<IN_ADDRESS>{HEX} {
        char *endptr;
        // Restore the initial state
        BEGIN(INITIAL);
        // Asign the value to use by bison
        yylval = strtol(yytext, &endptr, 16);
        // Check conversion's success
        if (*endptr != '\0')
            return ERROR;
        return ADDRESS;
    }

%%
%{
#include <stdio.h>
extern int yylex();
extern FILE *yyin;

int yyerror(const char *const message);

#define YYSTYPE int
%}


%token TYPE
%token DELIMITER
%token ADDRESS
%token ERROR

%%

program:
       | program statement
       ;

command: TYPE DELIMITER ADDRESS { 
           fprintf(stdout, "type %d, address 0x%08x\n", $1, $3); 
       }
       ;

statement: command
         | statement DELIMITER command;
         ;

%%

int
yyerror(const char *const message)
{
    return fprintf(stdout, "error: %s\n", message);
}

int
main(void)
{
    yyin = fopen("program.txt", "r");
    if (yyin == NULL)
        return -1;
    yyparse();
}