思路很清晰,见下面代码注释!


遇到的是atoi函数的返回值问题,atoi()函数用来将字符串转换成整数(int),其原型为:

int atoi (const char * str);

函数说明:atoi()函数会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过 isspace() 函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回。
返回值:返回转换后的整型数;如果 str 不能转换成 int 或者 str 为空字符串,那么将返回 0。


所以在atoi函数返回0时,要做进一步的检查确保输入的字符串中不是非数字字符!


参考代码如下:

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

int main()
{
    char res[30];      //存放检查结果的字符数组
    int  resindex = 0; //存放结果的字符数组下标

    char ip[30];       //存放当前输入的ip字符串
    while (fgets(ip, 30, stdin) != NULL) //如果在任何字符读取前就到达了文件尾EOF,
                                         //缓冲区就未进行修改,fgets函数返回一个NULL指针
    {
        char *token[4]; //存放ip字符串所分割的四个子字符串
        char *tmp;      //每次分割得到的临时子字符串

        int i = 0;
        if ((tmp = strtok(ip, ".")) != NULL)
        {
            token[i++] = tmp;
            while ((tmp = strtok(NULL, ".")) != NULL)
            {
                token[i++] = tmp;
            }
        }

        if (i != 4) //若分割的子字符串数量不为4,显然不是合法IP,记录结果,跳出本次循环
        {
            res[resindex++] = 'N';
            continue;
        }
        else
        {
            int num;      //将每个子字符串的内容转为整数num
            int flag = 1; //设置一个检查结果的标志位,初始为1

            int j;
            for (j = 0; j < 4; j++)
            {
                num = atoi(token[j]);     //atoi函数将字符串转化为整数
                if (num < 0 || num > 255) //只要有一个转化结果不在0~255区间就一定不合法
                {
                    res[resindex++] = 'N';
                    flag = -1;            //标记设置为-1,表示已经非法
                    break;                //跳出当前for循环
                }
                //以下检查是需要注意的部分
                if (num == 0)             //当atoi返回0时,可能此时token[j]中有非数字字符,需要进一步检查
                {
                    char *checkchar = token[j];  //将当前token[j]赋给一个临时字符指针变量,用于检查
                    if (*checkchar != '\0')      //碰到结束符结束检查
                    {
                        if (isdigit(*checkchar)) //若该字符为数字字符,则没问题,继续检查下一个字符
                        {
                            checkchar++;
                        }
                        else                     //若不为数字字符,该IP不合法,记录结果,跳出当前for循环
                        {
                            res[resindex++] = 'N';
                            flag = -1;           //标记设置为-1,表示已经非法
                            break;               //跳出当前for循环
                        }
                    }
                }
            }

            if (flag == 1) //从for循环出来之后若标志位未改变,则该IP合法,记录结果,跳出本次循环
            {
                res[resindex++] = 'Y';
                continue;
            }
        }
    }

    //打印检查结果
    int k;
    for (k = 0; k < resindex; k++)
    {
        printf("%c\n", res[k]);
    }

    return 0;
}


点赞(5)
 

0.0分

8 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 7 条评论

阿轩请求出战 3年前 回复TA
@ylem 不正确么
阿轩请求出战 3年前 回复TA
不正确么
D164805414 4年前 回复TA
@D164805414 看错了,没看到是或
D164805414 4年前 回复TA
第四十一行应该少个等于号吧,stdlib库atoi  VC++识别不出来我不知道为什么,我用VS编译的
D164805414 4年前 回复TA
isdigit 不应该是ctype吗
AngelCaval 4年前 回复TA
@ylem 本来就是啊
ylem 6年前 回复TA
0.1.2.3    居然被判断是一个正确的IP地址。。。