如何使用fscanf扫描IP地址

时间:2018-01-10 21:49:11

标签: c ip scanf

如何在c?

中使用scanf扫描IP地址

我已经是用户:

scanf(" %d ", &ip_adress)

我应该使用

%d.%d.%d

或者有一种更简单的方法。

这是我从文件中读取信息的功能:

void read_tree_from(FILE *in, PC **root){
    char name[MAX_NAME];
    int ip_adress;
    int speed;
    while(fscanf(in, "%s %d %d", name, &ip_adress, &speed) != EOF){
        PC *new = create_new_item(name, ip_adress, speed);
        add_to_tree(new, root);
    }
}

但是当我运行该程序时,它工作正常,但在输出文件中它的混乱......

3 个答案:

答案 0 :(得分:4)

您可以使用格式说明符%hhu.%hhu.%hhu.%hhu,它读取无符号的8位值,您可以直接读取ip地址的int表示的4个字节:

int main () {

    const char* testLine = "aName 192.168.112.54 100";

    char name[100];
    int speed;

    volatile uint32_t ipAddress=0;
    unsigned char* ipAddressBytes = (unsigned char*)&ipAddress;


    if (sscanf(testLine, "%s %hhu.%hhu.%hhu.%hhu %d", name, ipAddressBytes+3, ipAddressBytes+2,ipAddressBytes+1,ipAddressBytes+0, &speed) == 6) {
        printf("%s %08X %d\n",name, ipAddress, speed);
    }

    return 0;   
}

输出:

aName C0A87036 100

格式%hhu读取整数值并将其映射到8位;因此,它不会检查有关IP地址的输入在1025.168.112.54无效的意义上是否有效。但是,它避免了技术溢出,因为任何超过8位的部分都会被忽略。所以在提到之前输入会产生01A87036

注意volatile - 说明符,它告诉编译器它不应该优化对这个变量的访问;否则,编译器可能会认为 - 由于该值没有明显改变 - 变量未更改/未初始化。

进一步注意,您必须注意您的环境是大端还是小端架构。

希望它有所帮助。

答案 1 :(得分:1)

  

如何使用fscanf扫描IP地址

使用数据,==81480== 154,839 bytes in 81 blocks are definitely lost in loss record 1,258 of 1,259 ==81480== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==81480== by 0x4ED9777: ??? (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4EA81D8: PyUnicode_New (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4EABFDC: _PyUnicode_FromASCII (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4FA073C: ??? (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4EE8038: PyCFunction_Call (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4FF41B4: PyEval_EvalFrameEx (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4FF4638: PyEval_EvalFrameEx (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x5084CAB: ??? (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x5084D82: PyEval_EvalCodeEx (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4FEC9CA: PyEval_EvalCode (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== by 0x4FF967C: ??? (in /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0) ==81480== > ==55233== > ==55233== > ==55233== HEAP SUMMARY: > ==55233== in use at exit: 2,642,149 bytes in 4,750 blocks > ==55233== total heap usage: 42,001 allocs, 37,251 frees, 34,675,848 bytes allocated > ==55233== > ==55233== LEAK SUMMARY: > ==55233== definitely lost: 157,656 bytes in 85 blocks > ==55233== indirectly lost: 0 bytes in 0 blocks > ==55233== possibly lost: 158,663 bytes in 90 blocks > ==55233== still reachable: 2,325,830 bytes in 4,575 blocks > ==55233== suppressed: 0 bytes in 0 blocks > ==55233== Rerun with --leak-check=full to see details of leaked memory > ==55233== > ==55233== For counts of detected and suppressed errors, rerun with: -v > ==55233== Use --track-origins=yes to see where uninitialised values come from > ==55233== ERROR SUMMARY: 3460 errors from 123 contexts (suppressed: 0 from 0) 有许多优势,包括比fgets()更好的错误恢复,因此fscanf()解决方案

fgets/sscanf()
  

或者有一种更简单的方式(?)

是的,如果代码不关心检测错误数据,可以使用许多快捷方式。生产代码检查错误数据。强大的检查将采用void read_tree_from(FILE *in, PC **root){ char buffer [MAX_NAME + 50]; // Read a line of input if (fgets(buffer, sizeof buffer, in)) { int ip_address; int speed; unsigned char octet[4]; int n = 0; int namelen; // This approach uses %n to record the scan offset - if it got that far // %*s%n to scan over the name, all tht is needed is how long it is // %hhu to scan an `unsigned char` // " ." to scan spaces and then a '.' sscanf(buffer, "%*s%n %hhu .%hhu .%hhu .%hhu %d %n", &namelen, &octet[0], &octet[1], &octet[2], &octet[3], &speed, &n); // When `n > 0`, the complete scan occurred // buffer[n] != '\0' detects extra junk after the speed if (n == 0 || buffer[n] != '\0') { // failed scan return; } // Check data for validity if (namelen >= MAX_NAME) { // name too long return; } buffer[namelen] = '\0'; // \0 terminate the name // form IP address. I'd recommend `uint32_t` rather than `int` // The `1u*` insures code deals with unsigned promotions and shifts. No sign extend ip_address = 1u*octet[0] << 24 | 1u*octet[1] << 16 | 1u*octet[2] << 8 | octet[3]; PC *new = create_new_item(buffer, ip_adress, speed); add_to_tree(new, root); } } } 并查找超出范围的数值,(可能使用strtoul)等。

答案 2 :(得分:0)

我第一次尝试了这个,但它没有工作,可能是bcs我在代码中的其他地方有一些错误,我认为这是制作eror的部分。但是当我修复我的代码中的一些错误时,它工作。

while(fscanf(in, "%d %s %s %d", tmp_number, tmp_name, tmp_ip, &tmp_speed) != EOF){ RACUNAR *new = create_new_item(tmp_number, tmp_name, tmp_ip, tmp_speed); add_to_tree(new, root);