user3135211
user3135211

Reputation: 55

String Replacement parameters

(C#)My code seems to be fine but whenever I put 0 as the second parameter it will display "Enemy50" when I want enemy 57 to change to enemy 00. I think theres a problem with the third if statement but not sure for to fix it.

Main

   string enemy57 = "enemy57";
   Console.WriteLine("The old image name is: " + enemy57);
   Console.WriteLine("New image name: " + BuildingBlock.NextImageName(enemy57, 0));
   Console.ReadLine();


class BuildingBlock
{
    public static string ReplaceOnce(string word, string characters, int position)
    {
        word = word.Remove(position, characters.Length);
        word = word.Insert(position, characters);
        return word;
    }

    public static string GetLastName(string name)
    {
        string result = "";
        int posn = name.LastIndexOf(' ');
        if (posn >= 0) result = name.Substring(posn + 1);
        return result;
    }

    public static string NextImageName(string filename, int newNumber)
    {

        if (newNumber > 9)
        {
            return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 2));
        }
        if (newNumber < 10)
        {
            return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 1));
        }
        if (newNumber == 0)
        {
            return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 2));
        }
        return filename;
    }

Upvotes: 1

Views: 170

Answers (3)

Steve
Steve

Reputation: 216313

Try to replace your last call to ReplaceOnce with

 return ReplaceOnce(filename, newNumber.ToString("D2"), (filename.Length - 2));

The problem is because you pass the integer 0 that is converted to the string "0" which has a length of 1 char. So the ReplaceOnce method replace only the last char leaving the 5 in place.

Using the ToString composite formatting rule D2 ensure that whatever number you pass to the method will be formatted with at least two chars.

Said that, seeing that you test for newNumber == 0 you could also write

 return ReplaceOnce(filename, "00", (filename.Length - 2));

Also, the test for zero should be executed before the test for < 10 otherwise you call the method with wrong parameters.

public static string NextImageName(string filename, int newNumber)
{

    if (newNumber == 0)
    {
        return ReplaceOnce(filename, "00", (filename.Length - 2));
    }
    if (newNumber > 9)
    {
        return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 2));
    }
    if (newNumber < 10)
    {
        return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 1));
    }
    // Unreachable code ???
    // return filename;
}

If you are sure that twh ending characters are always two digits and you want to replace the current digits with two other digits also for one digits only newNumber you could write

public static string NextImageName(string filename, int newNumber)
{
    // ToString("D2") forces the 1-9 range to be passed as 0X no need to test 
    return ReplaceOnce(filename, newNumber.ToString("D2"), (filename.Length - 2));
}

removing all the now unnecessary tests on the digits length

Upvotes: 1

terrybozzio
terrybozzio

Reputation: 4532

the problem with your code is the last if statement which checks for 0 but before you have a check for < 10 which if newnumber is 0 will enter.So its just switch that if above the other 2 or between them like this:

public static string NextImageName(string filename, int newNumber)
{
    if (newNumber == 0)
    {
        return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 2));
    }
    if (newNumber > 9)
    {
        return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 2));
    }
    if (newNumber < 10)
    {
        return ReplaceOnce(filename, newNumber.ToString(), (filename.Length - 1));
    }
    return filename;
}

Or if you want as an example you can also eliminate the ReplaceOnce method and do it all like this:

public static string NextImageName(string filename, int newNumber)
{
    if (newNumber == 0)
    {
        return Regex.Replace(filename, @"[\d+]", newNumber.ToString());
    }
    if (newNumber > 9)
    {
        return Regex.Replace(filename, @"(\d+)(?!.*\d)", newNumber.ToString());
    }
    if (newNumber < 10)
    {
        return Regex.Replace(filename, @"(\d)(?!.*\d)", newNumber.ToString());
    }
    return filename;
}

Upvotes: 1

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391486

Here's an example that will likely do what you want.

It will:

  1. Replace all final digits with the new number
  2. Ensure the new number in the string is the same number of digits as the original number was in the string (or more, if needed)

Meaning that:

Enemy01, replace with 5, will be Enemy05
Enemy57, replace with 5, will be Enemy05
Enemy1, replace with 57, will be Enemy57

Here's a LINQPad program that demonstrates:

void Main()
{
    NextImageName("Enemy01", 5).Dump();
    NextImageName("Enemy57", 5).Dump();
    NextImageName("Enemy5", 57).Dump();
}

public static string NextImageName(string filename, int newNumber)
{
    var re = new Regex(@"\d+$");
    return re.Replace(filename, match =>
    {
        return newNumber.ToString().PadLeft(match.Length, '0');
    });
}

Output:

Enemy05
Enemy05
Enemy57

The regular expression

\d+$

means this:

  +- one or more times
  v
\d+$
^^ ^
 | |
 | +-- followed by the end of the string
 |
 digits (0-9)

In other words:

  • One or more digits (0-9)
  • Followed by the end of the string

Upvotes: 2

Related Questions