1. idea

user input:
1. subnet ipv4: in string format dot decimal. (example: 192.168.1.1)
2. mask: string int range from [0, 32]
3. ipv4: in string format dot decimal. (example: 192.168.1.1)

The question is to check if ipiv4 is in the same subnet
  1. Transform the string dot decimal ipv4 into byte binary format.
  2. The mask will also be transformed to byte binary format. ex:(mask 24 is 0xFF FF FF 00 )
  3. (subnetip & mask) == (ip & mask)

bit manipulation operations are needed. or (|) operation can be add the octet (8 bits) to another octet = 0; shift opertion can be used to get bit probe for example 1 << 31 can used to create a probe point to the highest bit in the ipv4.

To create a ipv4 byte binary from scratch, we usually start from 0.

2. code

function to split string using string find

/*
  @brief: split string s using delimiter
 */
vector<string> split(const string& s, const string& delimiter)
{
  vector<string> ans;
  size_t start = 0, end = 0;
  while((end = s.find(delimiter, start)) != string::npos) {
    ans.push_back(s.substr(start, end-start));
    start = end + delimiter.size();
  }

  ans.push_back(s.substr(start));
  return ans;
}

function to transform string to int

/*
  @breif translate string to int
  @return
    -1 if octet is invalid (not integer or out of range)
    ow int represented by the string
 */

int to_int(const string& str) {

  try {
    size_t end = 0;
    int ans = stoi(str, &end);
    // invalid case: 123abc
    if(end != str.size()) return -1;

    return ans;
  } catch(...) {
    return -1;
  }

  return -1;
}

function to parse ipv4 octet to int

/*
  @breif translate ipc4 octet to byte order binary form
  @return
    byte order of the ipv4 octet
    -1 if octet is invalid (not integer or out of range)
 */
int octet_to_byte(const string& octet) {
  int octet_byte = to_int(octet);

  if(octet_byte < 0 || octet_byte > 255) return -1;

  return octet_byte;
}

function to parse ipv4 to long long

/*
  read string ipv4 in dot decimal format,
  @return
    -1 if ipv4 is not valid,
    ow ipv4 in binary format hold by long long
  @note:
    ipv4 bin can be held in the 4 bytes int, but need
    a way to represent invalid ipv4, so use long long 8
    bytes to hold ipv4 bin
 */
long long parse_ipv4(const string &ipv4)
{
  vector<string> octets = split(ipv4, ".");
  if(octets.size() != 4) return -1;

  long long ipv4_byte = 0;
  for(string &s : octets) {
    int octet_byte = octet_to_byte(s);
    if(octet_byte == -1) return -1;
    ipv4_byte <<= OCTET_LEN;
    ipv4_byte |= octet_byte;
  }

  return ipv4_byte;
}

fucntion to parse mask to byte

/*
  @brief: ipv4 mask where the first mask bits are 1 and others are 0
  @return:
    the mask in binary byte format
    -1 if mask out of range
*/
long long mask_byte(const string &str_mask) {

  long long mask = to_int(str_mask);

  if(mask < 0 || mask > 32) return -1;

  long long ans = 0;
  long long probe = 1LL << 31;

  for(int i=0; i<mask; i++) {
    ans |= probe;
    probe >>= 1;
  }
  // ex: 0x00 00 00 00 FF FF FF 00 for str_maks = "24"
  return ans;
}

main function

/*
user input:
./subnet subnet_ip mask ip_address
@param1[string]: subnet_ip ipv4 address of current subnet in the dot decimal format
@param2[string]: can be transfer to number in the range [0,32]
@param3[string]: ipv4 in the dot decimal format like 192.168.0.2
*/

int main(int argc, char* argv[])
{

  // parsing input
  if(argc != 4) {
    cerr << "usage: ./subnet subnet_ip mask ip_address" << endl;
    return 1;
  }

  string str_subnet_ip = argv[1];
  string str_mask = argv[2];
  string str_ip = argv[3];

  long long subnet_ip = parse_ipv4(str_subnet_ip);
  if(subnet_ip == -1) {
    cerr << "invalid subnet ip: " << subnet_ip;
    return 1;
  }

  long long mask = mask_byte(str_mask);
  if(mask == -1) {
    cerr << "invalid mask: " << str_mask << endl;
    return 1;
  }

  long long ip = parse_ipv4(str_ip);
  if(mask == -1) {
    cerr << "invalid ip: " << str_ip;
    return 1;
  }

  bool same_subnet = ((subnet_ip & mask) == (ip & mask));

  if(same_subnet) {
    cout << "ip: " << str_ip << " is in the same subnet as " << str_subnet_ip << "/" << str_mask << endl;
  }
  else {
    cout << "ip: " << str_ip << " is not in the same subnet as " << str_subnet_ip << "/" << str_mask << endl;
  }

  return 0;


}

put it together

#include <iostream>
#include <vector>

using namespace std;
#define OCTET_LEN 8

/*
  @brief: split string s using delimiter
 */
vector<string> split(const string& s, const string& delimiter)
{
  vector<string> ans;
  size_t start = 0, end = 0;
  while((end = s.find(delimiter, start)) != string::npos) {
    ans.push_back(s.substr(start, end-start));
    start = end + delimiter.size();
  }

  ans.push_back(s.substr(start));
  return ans;
}

/*
  @breif translate string to int
  @return
    -1 if octet is invalid (not integer or out of range)
    ow int represented by the string
 */

int to_int(const string& str) {

  try {
    size_t end = 0;
    int ans = stoi(str, &end);
    // invalid case: 123abc
    if(end != str.size()) return -1;

    return ans;
  } catch(...) {
    return -1;
  }

  return -1;
}

/*
  @breif translate ipc4 octet to byte order binary form
  @return
    byte order of the ipv4 octet
    -1 if octet is invalid (not integer or out of range)
 */
int octet_to_byte(const string& octet) {
  int octet_byte = to_int(octet);

  if(octet_byte < 0 || octet_byte > 255) return -1;

  return octet_byte;
}

/*
  read string ipv4 in dot decimal format,
  @return
    -1 if ipv4 is not valid,
    ow ipv4 in binary format hold by long long
  @note:
    ipv4 bin can be held in the 4 bytes int, but need
    a way to represent invalid ipv4, so use long long 8
    bytes to hold ipv4 bin
 */
long long parse_ipv4(const string &ipv4)
{
  vector<string> octets = split(ipv4, ".");
  if(octets.size() != 4) return -1;

  long long ipv4_byte = 0;
  for(string &s : octets) {
    int octet_byte = octet_to_byte(s);
    if(octet_byte == -1) return -1;
    ipv4_byte <<= OCTET_LEN;
    ipv4_byte |= octet_byte;
  }

  return ipv4_byte;
}

/*
  @brief: ipv4 mask where the first mask bits are 1 and others are 0
  @return:
    the mask in binary byte format
    -1 if mask out of range
*/
long long mask_byte(const string &str_mask) {

  long long mask = to_int(str_mask);

  if(mask < 0 || mask > 32) return -1;

  long long ans = 0;
  long long probe = 1LL << 31;

  for(int i=0; i<mask; i++) {
    ans |= probe;
    probe >>= 1;
  }
  // ex: 0x00 00 00 00 FF FF FF 00 for str_maks = "24"
  return ans;
}

/*
user input:
./subnet subnet_ip mask ip_address
@param1[string]: subnet_ip ipv4 address of current subnet in the dot decimal format
@param2[string]: can be transfer to number in the range [0,32]
@param3[string]: ipv4 in the dot decimal format like 192.168.0.2
*/

int main(int argc, char* argv[])
{

  // parsing input
  if(argc != 4) {
    cerr << "usage: ./subnet subnet_ip mask ip_address" << endl;
    return 1;
  }

  string str_subnet_ip = argv[1];
  string str_mask = argv[2];
  string str_ip = argv[3];

  long long subnet_ip = parse_ipv4(str_subnet_ip);
  if(subnet_ip == -1) {
    cerr << "invalid subnet ip: " << subnet_ip;
    return 1;
  }

  long long mask = mask_byte(str_mask);
  if(mask == -1) {
    cerr << "invalid mask: " << str_mask << endl;
    return 1;
  }

  long long ip = parse_ipv4(str_ip);
  if(mask == -1) {
    cerr << "invalid ip: " << str_ip;
    return 1;
  }

  bool same_subnet = ((subnet_ip & mask) == (ip & mask));

  if(same_subnet) {
    cout << "ip: " << str_ip << " is in the same subnet as " << str_subnet_ip << "/" << str_mask << endl;
  }
  else {
    cout << "ip: " << str_ip << " is not in the same subnet as " << str_subnet_ip << "/" << str_mask << endl;
  }

  return 0;


}