C语言中从字符串提取并格式化时钟小时和分钟变量问题
问题描述
我使用一个返回char*类型的库函数,它返回调制解调器的日期字符串,格式为"+QLTS: \"2022/11/16,09:51:56+32,0\""。我想通过strtok提取小时和分钟,存储为int类型变量t_hour和t_min(后续会设为全局变量)。24小时制的令牌能正常获取,但处理"09"这类带前导0的格式转成数字9时,遇到了字符串类型转换的编译错误,附上尝试的代码:
char * time_buffer = (char *)fona.getTime(); char hour_tok[2]; char min_tok[2]; int t_hour; int t_min; if (strcmp(time_buffer, "ERROR") != 0) // { strtok(time_buffer, ","); hour_tok = strtok(NULL, ","); strtok(hour_tok, ":"); min_tok = strtok(NULL, ":"); if(hour_tok[0] == "0") { t_hour = atoi(hour_tok[1]); } else { t_hour = atoi(hour_tok); } if(min_tok[0] == "0") { t_min = atoi(min_tok[1]); } else { t_min = atoi(min_tok); } Serial.println(F("<<<<<TIME HR>>>>>")); Serial.println(String(t_hour)); Serial.println(F("<<<<<TIME MIN>>>>>")); Serial.println(String(t_min)); }
代码中的错误点
- 数组不能直接赋值:
hour_tok = strtok(NULL, ",");这类写法错误,数组名是常量指针,不能作为左值赋值,需用strcpy复制字符串内容。 - 字符与字符串比较错误:
hour_tok[0] == "0"中,"0"是字符串常量,hour_tok[0]是单个字符,应该用单引号包裹字符:hour_tok[0] == '0'。 - atoi参数类型错误:
atoi(hour_tok[1])传递的是单个字符,而atoi需要的是字符串指针,正确写法是atoi(&hour_tok[1]),或者直接用字符减'0'转数字。 - 数组长度不足:
hour_tok[2]无法容纳"09"这类2字符的字符串,C字符串需要末尾的\0结束符,所以数组至少要定义为char hour_tok[3];。
修正后的代码
方法1:保留前导0判断逻辑
char * time_buffer = (char *)fona.getTime(); // 定义足够长度的数组,容纳2字符+结束符 char hour_tok[3]; char min_tok[3]; int t_hour; int t_min; if (strcmp(time_buffer, "ERROR") != 0) { // 跳过日期部分,获取时间段字符串 strtok(time_buffer, ","); char* time_segment = strtok(NULL, ","); // 分割时间字符串,提取小时 strtok(time_segment, ":"); strcpy(hour_tok, strtok(NULL, ":")); // 提取分钟 strcpy(min_tok, strtok(NULL, ":")); // 处理小时前导0 if(hour_tok[0] == '0') { // 字符转数字,等价于atoi(&hour_tok[1]) t_hour = hour_tok[1] - '0'; } else { t_hour = atoi(hour_tok); } // 处理分钟前导0 if(min_tok[0] == '0') { t_min = min_tok[1] - '0'; } else { t_min = atoi(min_tok); } Serial.println(F("<<<<<TIME HR>>>>>")); Serial.println(String(t_hour)); Serial.println(F("<<<<<TIME MIN>>>>>")); Serial.println(String(t_min)); }
方法2:利用atoi自动处理前导0(更简洁)
其实atoi会自动忽略前导0,直接将"09"转换为9,所以可以省去前导0的判断逻辑:
char * time_buffer = (char *)fona.getTime(); int t_hour; int t_min; if (strcmp(time_buffer, "ERROR") != 0) { // 跳过日期部分 strtok(time_buffer, ","); char* time_segment = strtok(NULL, ","); // 直接分割提取小时和分钟字符串 char* hour_str = strtok(time_segment, ":"); char* min_str = strtok(NULL, ":"); // atoi自动处理前导0,直接转成int t_hour = atoi(hour_str); t_min = atoi(min_str); Serial.println(F("<<<<<TIME HR>>>>>")); Serial.println(String(t_hour)); Serial.println(F("<<<<<TIME MIN>>>>>")); Serial.println(String(t_min)); }
内容的提问来源于stack exchange,提问作者Tyranus
相关产品推荐
相关产品推荐

