Programming Question:

Convert an IPv4 address in the format of null-terminated C string into a > 32-bit integer. For example, given an IP address “172.168.5.1”, the output > should be a 32-bit integer with “172” as the highest order 8 bit, 168 as the > second highest order 8 bit, 5 as the second lowest order 8 bit, and 1 as the > lowest order 8 bit. That is,

“172.168.5.1” => 2896692481 Requirements:

  1. You can only iterate the string once.
  2. You should handle spaces correctly: a string with spaces between a digit > and a dot is a valid input; while a string with spaces between two digits is > not. “172[Space].[Space]168.5.1” is a valid input. Should process the output > normally. “1[Space]72.168.5.1” is not a valid input. Should report an error. 3. > Please provide unit tests.

Answer:

ipv4toInt.h


#import <Foundation/Foundation.h>

/**
 * convert the ipv4 string to a 32-bit integer, if ipv4 is a invalid string return 0.
 */
NSInteger ipv4toInt(NSString *ipv4);

ipv4toInt.m


#import "ipv4toInt.h"

NSInteger ipv4toInt(NSString *ipv4){
    if(!ipv4 || [ipv4 isKindOfClass:[NSString class]]){
        return 0;
    }
    char * ip = (char *) [ipv4 UTF8String];
    char c;
    c = *ip;
    NSInteger ret = 0;
    int val;
    int i,j=0;
    for (j=0;j<4;j++) {
        if(j< 4 && c == '\0'){
            return 0;
        }
        
        val=0;
        bool flag = false;
        for (i=0;val<=255;i++) {
            if (isdigit(c)) {
                flag = true;
                val = (val * 10) + (c - '0');
                c = *++ip;
                
            }else if( c == ' '){    //check spaces
                if(!flag){
                    c = *++ip;
                }else{
                    c = *++ip;
                    if(isdigit(c)){
                        return 0;
                    }
                }
                
            }else
                break;
            
        }
        
        if (c == '.') {
            ret=(ret<<8) | val;
            c = *++ip;
        }
        else if(j==3 && c == '\0'){
            ret=(ret<<8) | val;
            break;
        }
        
    }
    if(c != '\0'){
        return 0;
    }
    return  ret;
}

main.m


#import <Foundation/Foundation.h>
#import "ipv4toInt.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"ip:172.168.5.1 toInt:%ld",ipv4toInt(@"172.168.5.1"));
        NSLog(@"ip:172.168.5.2 toInt:%ld",ipv4toInt(@"172.168.5.2"));
    }
    return 0;
}

UnitTest.m


#import <XCTest/XCTest.h>
#import "ipv4toInt.h"

@interface UnitTest : XCTestCase

@end

@implementation UnitTest

- (void)setUp {
}

- (void)tearDown {
}

- (void)testExample {
    // This is an example of a functional test case.
    XCTAssert(ipv4toInt(@"172.168.5.1") == 2896692481,@"OK");
    XCTAssert(ipv4toInt(@"172.168.5.2") == 2896692482,@"OK");
    XCTAssert(ipv4toInt(@"172.168.5.10") == 2896692490,@"OK");
    XCTAssert(ipv4toInt(@"172 . 168.5.1") == 2896692481,@"OK");
    XCTAssert(ipv4toInt(@"  172. 168  .  5.1  ") == 2896692481,@"OK");
    
    XCTAssert(ipv4toInt(nil) == 0,@"Error Input");
    XCTAssert(ipv4toInt(@"") == 0,@"Error Input");
    XCTAssert(ipv4toInt(@"  ") == 0,@"Error Input");
    XCTAssert(ipv4toInt(@"172.168.5") == 0,@"Error Input");
    XCTAssert(ipv4toInt(@"172.1a8.5.1") == 0,@"Error Input");
    XCTAssert(ipv4toInt(@"a.1a8.5.1") == 0,@"Error Input");
    XCTAssert(ipv4toInt(@"172.16  8.5.1") == 0,@"Error Input");
    XCTAssertFalse(ipv4toInt(@"1 72.168.5.1") == 2896692481,@"");
}

@end

继续阅读