New_programmer
New_programmer

Reputation: 11

Stuck with the part of string comparison

I have to change the "." parts of the IP address to "[.]" using C++. For example: "1.1.1.1" should be converted to "1[.]1[.]1[.]1".

I tried to solve it using normal for-loop,

string defangIPaddr(string address) {
    for(int i=0;i<address.size();i++)
    {
        if(address[i]==".")
        {
            address[i]="[.]";
        }
    }
    return address;
}

But it throws an error:

Line 6: Char 16: error: no matching function for call to 'strcmp'
6 |             if(strcmp(address[i],"."))
  |                ^~~~~~
/usr/include/string.h:156:12: note: candidate function not viable: no known conversion from 'value_type' (aka 'char') to 'const char *' for 1st argument; take the address of the argument with &
147 | extern int strcmp (const char *__s1, const char *__s2)
    |            ^~~~~~~~~~~~~~~~~

Can someone please explain what mistake(s) have I made here?

Upvotes: -3

Views: 86

Answers (3)

PaulMcKenzie
PaulMcKenzie

Reputation: 35454

The errors are that

  1. You are trying to compare a single character address[i] to a string "."
  2. You are trying to stuff four characters into a single character, address[i]="[.]".

Even if you fix those errors so that your code compiles cleanly, your loop is very awkward in that you are increasing the size of the original string if . is found, and at the same time you're looping depending on the size of the string.

Instead of all of this, simply build a new string from the original string by looping over the original string and checking each character to see if it is '.':

#include <string>
#include <iostream>

std::string defangIPaddr(std::string address) 
{
    std::string newString;
    for(auto ch : address)
    {
        if (ch == '.')
            newString += "[.]";
        else
            newString += ch;
    }
    return newString;
}


int main()
{
    std::cout << defangIPaddr("1.1.1.1");
}

Output:

1[.]1[.]1[.]1

Upvotes: 1

D&#250;thomhas
D&#250;thomhas

Reputation: 10083

I upvoted Paul McKenzie’s answer, but you can also accomplish this with regular expressions:

#include <iostream>
#include <regex>
#include <string>

int main()
{
    std::string ip = "192.168.1.1";
    std::cout
        << ip
        << " --> "
        << regex_replace( ip, std::regex{ "\\." }, "[.]" )
        << "\n";
}

Upvotes: 0

Pepijn Kramer
Pepijn Kramer

Reputation: 13076

I would use a reusable function to split up a string into substrings (tokenize like function). And then use std::format to creat the output string. Like this

#include <cassert>
#include <format>
#include <iostream>
#include <string_view>
#include <vector>


auto split_string(std::string_view string, std::string_view delimiters)
{
    std::vector<std::string_view> substrings;
    
    if ((string.size() == 0ul))
    {
        return substrings;
    }
    
    if (delimiters.size() == 0ul)
    {
        substrings.emplace_back(string);
        return substrings;
    }

    auto start_pos = string.find_first_not_of(delimiters);
    auto end_pos = start_pos;
    auto max_length = string.length();

    while (start_pos < max_length)
    {
        end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));

        if (end_pos != start_pos)
        {
            substrings.emplace_back(&string[start_pos], end_pos - start_pos);
            start_pos = string.find_first_not_of(delimiters, end_pos);
        }
    }

    return substrings;
}

std::string defangIPaddr(const std::string_view sv)
{
    auto result = split_string(sv, ".");
    assert(result.size() == 4ul);

    return std::format("{}[.]{}[.]{}[.]{}", result[0], result[1], result[2], result[3]);
}

int main()
{
    std::string_view test{ "192.168.0.1" };
    std::cout << defangIPaddr(test);
}

Upvotes: 0

Related Questions