简体   繁体   中英

Generate all ip addresses from given string

Write a program that determines where to add periods to a decimal string so that the resulting string is a valid IP address. There may be more than one valid IP address corresponding to a string, in which case you should print all possibilities. Additionally your program must validate that neither group must not exceed 255. For example: If the mangled string is “19216811” then two corresponding IP addresses are 192.168.1.1 and 192.216.81.1. There are also seven other possible IP addresses for this string.

My program is causin segmentationn fault

My Code:

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


bool is_valid_part(char *part) {
  return (strlen(part)== 1) || (part[0] != 0 && atoi(part) <= 255);
}
int a =0;
int pos = 0;
void generate(char *ip, char **ans)
{
    int l = strlen(ip);
 
    // Check for string size
    if (l > 12 || l < 4) {
        printf("Not valid IP String");
        return;
    }
 
    char *check = ip;
 
    // Generating different combinations.
    for (int i = 1; i < l - 2; i++) {
        for (int j = i + 1; j < l - 1; j++) {
            for (int k = j + 1; k < l; k++) {
                check =  strncpy(check, ip, k); + '.'+ strncpy(check, ip + k, strlen(ip) - k - 1);
                check = strncpy(check, ip, j); + '.'+ strncpy(check, ip + j, strlen(ip) - j - 1);
                check= strncpy(check, ip, i); + '.'+ strncpy(check, ip + i, strlen(ip) - i - 1); 
                if (is_valid_part(check)) {
                    ans[pos++] = check;
                    printf("%s", check);
                }
                check = ip;
            }
        }
    }
}
int main(void){
    char str[32];
    fgets(str, 32, stdin);
    printf("%s",str);
    char **ans;
    generate(str, ans);
}
  • As the input string str contains a trailing newline character, strlen(str) is larger than the intended value. You need to chop the newline character off.
  • Your is_valid_part() function is very close but you need to change part[0] != 0 to part[0] != '0' to examine the leading 0 .
  • If you want to create a list of ip addresses at runtime, you need to allocate memory area with malloc/realloc and free the area after use.

Then would you please try the following:

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

bool is_valid_part(char *part) {
    return (strlen(part) == 1) || (part[0] != '0' && atoi(part) <= 255);
}

void generate(char *ip, char ***ptr, int *pos)
{
    int len = strlen(ip);
    char octet[4][4];
    char addr[16];

    // check for string size
    if (len > 12 || len < 4) {
        printf("The length must be between 4 and 12\n");
        return;
    }
    // check characters
    for (int i = 0; i < len; i++) {
        if (! isdigit(ip[i])) {
            printf("Invalid character: %c\n", ip[i]);
            return;
        }
    }

    // generating different combinations.
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 3; j++) {
            for (int k = 1; k <= 3; k++) {
                int l = len - i - j - k;
                if (l < 1 || l > 3) continue;
                strncpy(octet[0], ip, i); *(octet[0] + i) = '\0';
                strncpy(octet[1], ip + i, j); *(octet[1] + j) = '\0';
                strncpy(octet[2], ip + i + j, k); *(octet[2] + k) = '\0';
                strncpy(octet[3], ip + i + j + k, l); *(octet[3] + l) = '\0';

                int fail = 0;
                for (int m = 0; m < 4; m++) {
                    if (! is_valid_part(octet[m])) fail = 1;
                }
                if (fail) continue;     // skip to next combination

                // generate a string of ip address
                strcpy(addr, octet[0]);
                for (int m = 1; m < 4; m++) {
                    strcat(addr, ".");
                    strcat(addr, octet[m]);
                }

//              printf("%s\n", addr);
                // allocate memory and append the string to the list
                *ptr = realloc(*ptr, (*pos + 1) * sizeof(char **));
                (*ptr)[*pos] = malloc(strlen(addr) + 1);
                strcpy((*ptr)[*pos], addr);
                (*pos)++;               // increment the count of ip addresses
            }
        }
    }
}

int main(void) {
    char str[BUFSIZ];
    printf("Enter a decimal string: ");
    fgets(str, BUFSIZ, stdin);
    char *p = rindex(str, '\n');        // trim the newline character
    if (p) *p = '\0';
    p = rindex(str, '\r');              // trim the carrage return character
    if (p) *p = '\0';

//  printf("%s\n", str);
    char **ans = NULL;                  // array of ip address strings
    int cnt = 0;                        // counter of the ip addresses
    generate(str, &ans, &cnt);

    // print the results
    for (int i = 0; i < cnt; i++) {
        printf("%s\n", ans[i]);
    }

    // free memory
    for (int i = 0; i < cnt; i++) {
        free(ans[i]);
    }
    free(ans);
}

Output:

Enter a decimal string: 19216811
1.92.168.11
19.2.168.11
19.21.68.11
19.216.8.11
19.216.81.1
192.1.68.11
192.16.8.11
192.16.81.1
192.168.1.1
  • Integer values i, j, k and l are generated such that each value is between 1 and 3 inclusive and the sum equals to strlen(ip).
  • Then the string ip is divided into an array octet , each of length i, j, k and l.
  • Each substring in octet is terminated with a null character.
  • If every elements of octet meet the condition, they are concatenated into an ip address string.
  • *ptr is a 2-d array which grows on the fly.
  • As the value of *ptr is modified within the generate() function, a pointer to ans is passed to the function.
  • The counter cnt is also passed by address. It is not recommended to use a global address as long as there are alternatives.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM