C 解析4个单字节的ip地址字符串
我正在用C在MCU上编程,我需要将包含IP地址的空终止字符串解析为4个字节。我用C++做了一个例子:C 解析4个单字节的ip地址字符串,c,parsing,pic18,c18,C,Parsing,Pic18,C18,我正在用C在MCU上编程,我需要将包含IP地址的空终止字符串解析为4个字节。我用C++做了一个例子: #include <iostream> int main() { char *str = "192.168.0.1\0"; while (*str != '\0') { if (*str == '.') { *str++; std::
#include <iostream>
int main()
{
char *str = "192.168.0.1\0";
while (*str != '\0')
{
if (*str == '.')
{
*str++;
std::cout << std::endl;
}
std::cout << *str;
*str++;
}
std::cout << std::endl;
return 0;
}
#包括
int main()
{
char*str=“192.168.0.1\0”;
而(*str!='\0')
{
如果(*str=='。)
{
*str++;
std::cout在C中实现这一点的一个好方法是使用字符串标记器。在下面的示例代码中,字节保存在字节数组中,并且也使用printf函数打印。希望对您有所帮助
#include <string.h>
int main()
{
char str[] = "192.168.0.1";
unsigned char bytes[4];
int i = 0;
char* buff = malloc(10);
buff = strtok(str,".");
while (buff != NULL)
{
//if you want to print its value
printf("%s\n",buff);
//and also if you want to save each byte
bytes[i] = (unsigned char)atoi(buff);
buff = strtok(NULL,".");
i++;
}
free(buff);
return 0;
}
#包括
int main()
{
字符str[]=“192.168.0.1”;
无符号字符字节[4];
int i=0;
char*buff=malloc(10);
buff=strtok(str,“.”);
while(buff!=NULL)
{
//如果要打印其值
printf(“%s\n”,浅黄色);
//如果你想保存每个字节
字节[i]=(无符号字符)atoi(buff);
buff=strtok(空,“.”);
i++;
}
免费(buff);
返回0;
}
<代码> > p>你可以按字符来做,就像你的问题中的C++版本一样。
/* ERROR CHECKING MISSING */
#include <ctype.h>
#include <stdio.h>
int main(void) {
char *str = "192.168.0.1", *str2;
unsigned char value[4] = {0};
size_t index = 0;
str2 = str; /* save the pointer */
while (*str) {
if (isdigit((unsigned char)*str)) {
value[index] *= 10;
value[index] += *str - '0';
} else {
index++;
}
str++;
}
printf("values in \"%s\": %d %d %d %d\n", str2,
value[0], value[1], value[2], value[3]);
return 0;
}
/*缺少错误检查*/
#包括
#包括
内部主(空){
char*str=“192.168.0.1”,*str2;
无符号字符值[4]={0};
尺寸指数=0;
str2=str;/*保存指针*/
while(*str){
if(isdigit((无符号字符)*str)){
数值[指数]*=10;
值[索引]+=*str-'0';
}否则{
索引++;
}
str++;
}
printf(“在\%s\”中的值:%d%d%d\n”,str2,
值[0]、值[1]、值[2]、值[3]);
返回0;
}
我想为解析ipv4地址提供更严格的版本
typedef struct ipv4_type {
uint8_t data[4];
} ipv4;
ipv4_error ipv4_parse ( const uint8_t * string, uint8_t string_length, ipv4 * result )
{
bool at_least_one_symbol = false;
uint8_t symbol, string_index = 0, result_index = 0;
uint16_t data = 0;
while ( string_index < string_length ) {
symbol = string[string_index];
if ( isdigit ( symbol ) != 0 ) {
symbol -= '0';
data = data * 10 + symbol;
if ( data > UINT8_MAX ) {
// 127.0.0.256
return ERROR_IPV4_DATA_OVERFLOW;
}
at_least_one_symbol = true;
} else if ( symbol == '.' ) {
if ( result_index < 3 ) {
if ( at_least_one_symbol ) {
result->data[result_index] = data;
data = 0;
result_index ++;
at_least_one_symbol = false;
} else {
// 127.0..1
return ERROR_IPV4_NO_SYMBOL;
}
} else {
// 127.0.0.1.2
return ERROR_IPV4_INPUT_OVERFLOW;
}
} else {
// 127.*
return ERROR_IPV4_INVALID_SYMBOL;
}
string_index ++;
}
if ( result_index == 3 ) {
if ( at_least_one_symbol ) {
result->data[result_index] = data;
return 0;
} else {
// 127.0.0.
return ERROR_IPV4_NOT_ENOUGH_INPUT;
}
} else {
// result_index will be always less than 3
// 127.0
return ERROR_IPV4_NOT_ENOUGH_INPUT;
}
}
typedef结构ipv4\u类型{
uint8_t数据[4];
}ipv4;
ipv4\u错误ipv4\u解析(常量uint8\u t*字符串、uint8\u t字符串长度、ipv4*结果)
{
bool至少一个符号=false;
uint8\u t符号,字符串索引=0,结果索引=0;
uint16_t数据=0;
while(字符串索引<字符串长度){
符号=字符串[字符串索引];
如果(isdigit(符号)!=0){
符号-='0';
数据=数据*10+符号;
如果(数据>UINT8_最大值){
// 127.0.0.256
返回错误\u IPV4\u数据\u溢出;
}
至少有一个符号=真;
}else if(符号='。){
如果(结果_指数<3){
如果(至少一个符号){
结果->数据[结果索引]=数据;
数据=0;
结果_指数++;
至少有一个符号=false;
}否则{
// 127.0..1
返回错误\u IPV4\u无\u符号;
}
}否则{
// 127.0.0.1.2
返回错误\u IPV4\u输入\u溢出;
}
}否则{
// 127.*
返回错误\u IPV4\u无效\u符号;
}
string_index++;
}
如果(结果_索引==3){
如果(至少一个符号){
结果->数据[结果索引]=数据;
返回0;
}否则{
// 127.0.0.
返回错误\u IPV4\u输入不足\u;
}
}否则{
//结果_索引将始终小于3
// 127.0
返回错误\u IPV4\u输入不足\u;
}
}
此代码不打印“字节”使用值192
..:它打印字符…3个字符代表1
9
2
…哦…刚刚实现了用户的要求。通过使用couts查看代码,我以为他只想打印字符。他实际上希望字节在字符串文本的末尾显式添加\0非常奇怪。通过初始化char*a=“foo\0”,您可以创建一个包含5个字符的字符串文字,其结尾有两个nul字节。tyvm的工作原理类似于一个符咒:)编辑:哦,等等,我的pic18也没有这个功能:(为什么你看不到你首先使用的pic微控制器支持C标准库的string.h头中的哪一个函数,然后告诉我们?sscanf和strtok(分别是perreal和my answer)是c标准库函数。我们必须知道有多少是可供您使用的。这是库:对不起,我是stackoverflow新手,因为我用pic18和c18标记了它。你们知道库,但后来我意识到我也用链接pdf的Cpage 131标记了它。strtokpgm、strtokpgmram、strtokrampgm都受支持。所以我的答案可以使用。你检查过了吗?(这是第三个)sscanf已知速度慢,在某些实现中甚至有bug。你应该避免使用它。如果我注释=malloc(10);
则此选项有效,因此只剩下char*buff;
了。如果我不注释,我会得到一个错误,“从void*到char*的转换无效”TyVMIT不按你的想法工作。如果你弄错了,它是错误的。如果你得到这个错误,那就是编译C++代码而不是C代码。确保1)要么改正编译器的标志2)如果它是C++,你只需要把它改为:char *buff =(char)Maloc(10)。;不,它的工作方式与您想象的不同。您正在使用malloc分配一个10字节的缓冲区。在下一行中,您将buff指向另一个位置。您分配的10字节缓冲区已丢失。C中没有垃圾收集。(在这个小程序中,这可能无关紧要,但在基于它的函数中,在一个程序中多次调用……)然后,在程序结束时,你试图释放-什么???当buff==NULL时你到达那里!这个也可以,tyvm!我花了一段时间,直到我明白了这个*=10
和+=*str-'0'
是如何做到的!:p初始化(无符号字符值[4]={0};
)是很重要的。别忘了。此代码在某些格式错误的字符串上会失败:“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa。。。
/* ERROR CHECKING MISSING */
#include <ctype.h>
#include <stdio.h>
int main(void) {
char *str = "192.168.0.1", *str2;
unsigned char value[4] = {0};
size_t index = 0;
str2 = str; /* save the pointer */
while (*str) {
if (isdigit((unsigned char)*str)) {
value[index] *= 10;
value[index] += *str - '0';
} else {
index++;
}
str++;
}
printf("values in \"%s\": %d %d %d %d\n", str2,
value[0], value[1], value[2], value[3]);
return 0;
}
typedef struct ipv4_type {
uint8_t data[4];
} ipv4;
ipv4_error ipv4_parse ( const uint8_t * string, uint8_t string_length, ipv4 * result )
{
bool at_least_one_symbol = false;
uint8_t symbol, string_index = 0, result_index = 0;
uint16_t data = 0;
while ( string_index < string_length ) {
symbol = string[string_index];
if ( isdigit ( symbol ) != 0 ) {
symbol -= '0';
data = data * 10 + symbol;
if ( data > UINT8_MAX ) {
// 127.0.0.256
return ERROR_IPV4_DATA_OVERFLOW;
}
at_least_one_symbol = true;
} else if ( symbol == '.' ) {
if ( result_index < 3 ) {
if ( at_least_one_symbol ) {
result->data[result_index] = data;
data = 0;
result_index ++;
at_least_one_symbol = false;
} else {
// 127.0..1
return ERROR_IPV4_NO_SYMBOL;
}
} else {
// 127.0.0.1.2
return ERROR_IPV4_INPUT_OVERFLOW;
}
} else {
// 127.*
return ERROR_IPV4_INVALID_SYMBOL;
}
string_index ++;
}
if ( result_index == 3 ) {
if ( at_least_one_symbol ) {
result->data[result_index] = data;
return 0;
} else {
// 127.0.0.
return ERROR_IPV4_NOT_ENOUGH_INPUT;
}
} else {
// result_index will be always less than 3
// 127.0
return ERROR_IPV4_NOT_ENOUGH_INPUT;
}
}