我有以下代码
char inputs []="3,0,23.30,3,30/55,55,55,55,55,55,55,55,55,55,55,55,55,64,64,64,100,100,100,100,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,55,55,70/1.5,0.5,0.2,0.2,0.3,0.1";
char parameters[18];
strcpy(parameters,strtok(inputs,"/"));
然后是一些代码通过uart传输我的角色并在监视器上看到它们。当我发送输入时,我看到它们很好,但是当我发送参数时,我看不到字符串是空的。
我见过strtok的例子,它使用该代码来分割字符串。我也在visual studio上尝试过这种代码,当我打印它们时,它向我展示了很好的字符串。有没有机会strtok不能用微处理器很好地运行????
答案 0 :(得分:1)
我没有使用strtok,如果有的话,但这似乎是将strtok()的结果存储在char []中的正确方法:
const int NUM_PARAMS = 18;
const int MAX_CHARS = 64;
char parameters[NUM_PARAMS][MAX_CHARS];
char delims[] = "/";
char *result = NULL;
int count = 0;
result = strtok(inputs, delims);
while(result != NULL && count < NUM_PARAMS){
strncpy(parameters[count++], result, MAX_CHARS);
result = strtok(NULL, delims);
}
或者如果您不想为较小的令牌分配不必要的内存:
const int NUM_PARAMS = 18;
char* parameters[NUM_PARAMS];
char delims[] = "/";
char *result = NULL;
int count = 0;
result = strtok(inputs, delims);
while(result != NULL && count < NUM_PARAMS){
parameters[count] = malloc(strlen(result) + 1);
strncpy(parameters[count++], result, MAX_CHARS);
result = strtok(NULL, delims);
}
参数现在应该包含所有令牌。
答案 1 :(得分:1)
使用微控制器时,您必须注意正在处理的内存区域。在PC上运行的软件上,所有内容都存储在RAM中并运行。但是,在闪存微控制器上,代码从闪存(也称为程序存储器)运行,而数据则从RAM(也称为数据存储器)处理。
在你正在处理的情况下,inputs
变量存储一个硬编码的字符数组,它可以是const,我们不知道编译器选择放在哪个区域。因此,我们可以重写您的小程序,以确保所有数据都存储在程序数据中,我们将使用&#34; _P&#34;用于操纵此数据的功能。
#include <avr/pgmspace.h > // to play in program space
const char inputs PROGMEM []="3,0,23.30,3,30/55,55,55,55,55,55,55,55,55,55,55,55,55,64,64,64,100,100,100,100,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,55,55,70/1.5,0.5,0.2,0.2,0.3,0.1"; // Now, we are sure this is in program memory space
char buffer[200]; // should be long enough to contain a copy of inputs
char parameters[18];
int length = strlen_P(inputs); // Should contains string length of 186 (just to debug)
strcpy_P(buffer,inputs); // Copy the PROGMEM data in data memory space
strcpy(parameters,strtok_P(buffer,"/")); // Parse the data now in data memory space
有关avr gcc的程序空间的更多信息:http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
答案 2 :(得分:1)
strtok()
故意修改源字符串,随着终结符替换令牌。只要源字符串是可变的,就没有理由将内容存储在辅助存储器中。
将字符串拆分为连接的常量(由编译器汇编,因此它们最终将是一个终止的字符串):
char inputs []="3,0,23.30,3,30/"
"55,55,55,55,55,55,55,55,55,55,55,55,55,64,64,64,100,100,100,100,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,55,55,70/"
"1.5,0.5,0.2,0.2,0.3,0.1";
显然,'/'
分隔的第二个和第三个序列接近 17个字符宽(记住,你的副本需要一个更多的位置用于终结符,因此只能合法地复制17个字符)。
除非有令人信服的理由不这样做,否则我认为没有理由不这样做:
char *param = strtok(inputs, "/");
while (param != NULL)
{
// TODO: do something with param...
// ... then advance to next param
param = strtok(NULL, "/");
}
您对// TODO do something with param...
的处理取决于您自己。例如,可以通过strlen(param)
检索参数的长度。您可以制作副本,前提是您有足够的存储空间作为目标(在第二种和第三种情况下,您不要提供足够的存储空间,在您的示例中只有18个字符的缓冲区)
无论如何,请记住,strtok()
修改了源 inputs[]
数组。如果这是不可接受的,那么替代方案将是:
char *tmp_inputs = strdup(inputs);
if (tmp_inputs != NULL)
{
char *param = strtok(tmp_inputs, "/");
while (param != NULL)
{
// TODO: do something with param...
// ... then advance to next param
param = strtok(NULL, "/");
}
// done with copy of inputs. free it.
free(tmp_inputs);
}
还有相当多的线程决策,这就是strtok()
版本需要调用者(你)在调用之间围绕上下文的原因。有关详细信息,请参阅strtok_r()
。
答案 3 :(得分:-1)
您必须以这种方式初始化parameters
:
char parameters[18] = {'\0'};
因此,它将使用空字符而不是变量值进行初始化。这很重要,因为strcpy会尝试找到一个空字符来标识字符串的结尾。
只是为了说清楚......
初始化后的参数:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
strtok之后的参数:['3',',','0',',','2','3','.','3','0',',','3',',','3','0',0,0,0,0]