2016-07-18 2 views
2

Изучив основы/основы языка программирования C#, я теперь пытаюсь решить мою первую проблему в реальном мире: Напишите программу, которая, учитывая строку, находит ее самая длинная подстрока, которая содержит не менее одна верхняя буква , но нет цифр (и затем отображает длину этой самой длинной подстроки). Это может быть два отборочных условия для приемлемого пароля, например ...Проверка двух условий при итерации по массиву символов

Я написал код, все сам, а это значит, есть, вероятно, проблемы с производительностью, но для дальнейшего рассмотрения. Я застрял в точке, где мне нужно убедиться, что в подстроке нет цифры. Комментарии в моем коде показывают мое мышление во время написания программы ...

Я думал, что сначала я должен проверить, есть ли надпись в верхней части строки, а если есть, то я могу храните эту квалификационную подстроку в списке и затем выходите из цикла. Но теперь мне интересно, как проверить состояние без цифр в одно и то же время в одной и той же подстроке?

Я стараюсь, чтобы это было аккуратно и просто (как я уже сказал, я только начал писать программы дольше, чем несколько строк!), Поэтому я думал, что делать вложенный цикл для проверки каждого символа против !char.IsNumber(letter) может оказаться не оптимальным. Или я должен сначала проверить, нет ли цифры, а затем посмотреть, есть ли хотя бы капитальный символ?

Я смущен, как добиться обоих ограничений, поэтому я был бы признателен за помощь в решении этой проблемы. Я также признателен за любые замечания или предложения у вас может быть. Например, нормально ли хранить мои подстроки в списке? Должен ли я сделать какой-то словарь? Оптимально ли мое полностью возможное подстрочное вложение?

p.s. Некоторые бит еще не закончены; например, я до сих пор осуществить последний шаг, чтобы найти самую длинную подстроку и отображения пользователю его длины ...

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace PasswordRestriction 
{ 
    class Program /// Write a program that, given a string, finds the longest substring that is a valid password and returns its length. 
    { 
     static void Main(string[] args) 
     { 
      // Ask the user for an alphanumeric string. 
      Console.WriteLine("Enter a string of alphanumeric values:"); 

      // Receive the user input as string. 
      string password = Console.ReadLine(); 

      // Print the length of the longest qualifying substring of the user string. 
      Console.WriteLine("Length of the longest qualifying substring:\n" + Solution(password).Length); 

      // Prevent the console window from closing. 
      Console.ReadLine(); 
     } 


     /// The method that exracts the longest substring that is a valid password. 
     /// Note that a substring is a 'contiguous' segment of a string. 
     public static string Solution(string str) 
     { 
      // Only allow non-empty strings. 
      if (String.IsNullOrEmpty(str)) 
      { 
       return ""; 
      } 
      else 
      { 
       // Only allow letters and digits. 
       if (str.All(char.IsLetterOrDigit)) 
       { 
        // A list for containing qualifying substrings. 
        List<string> passwordList = new List<string>(); 

        // Generate all possible substrings. Note that 
        // string itself is not a substring of itself! 
        for (int i = 1; i < str.Length; i++) 
        { 
         for (int j = 0; j <= (str.Length-i); j++) 
         { 
          string subStr = str.Substring(j, i); 
          Console.WriteLine(subStr); 

          bool containsNum = false; 
          bool containsUpper = false; 

          // Convert the substrings to arrays of characters with ToCharArray. 
          // This method is called on a string and returns a new character array. 
          // You can manipulate this array in-place, which you cannot do with a string. 
          char[] subStrArray = subStr.ToCharArray(); 

          // Go through every character in each substring. 
          // If there is at least one uppercase letter and 
          // no digits, put the qualifying substring in a list. 
          for (int k = 0; k < subStrArray.Length; k++) 
          { 
           char letter = subStrArray[k]; 

           if (char.IsNumber(letter)) 
           { 
            containsNum = true; 
            break; 
           } 

           if (char.IsUpper(letter)) 
           { 
            containsUpper = true; 
           } 

           if (containsUpper && (containsNum == false) && (k == subStrArray.Length - 1)) 
           { 
            Console.WriteLine("Found the above legit password!"); 
            passwordList.Add(subStr); 
           } 
          } 
         } 
        } 

        //Find the longest stored string in the list. 
        //if (passwordList.Count != 0) 
        //{ 
         string maxLength = passwordList[0]; 

         foreach (string s in passwordList) 
         { 
          if (s.Length > maxLength.Length) 
          { 
           maxLength = s; 
          } 
         } 
        //} 

        // Return the qualifying substring. 
        return maxLength; 
       } 
       else 
       { 
        return "aaaaaaaaaa"; 
       } 
      } 
     } 
    } 
} 
+2

Вы можете взять индекс всех чисел в строке, вычитая последующие индексы, вы получите самую длинную строку с числовым значением, а затем просто найдите те, которые заглавны. У вас есть один момент 3 для петель, и это, вероятно, никогда не будет оптимальным. – Bmo

ответ

4

Хорошая задача для Linq

  • не содержит цифр - Split на цифры
  • по меньшей мере, один символ верхнего регистра - Where + Any
  • длинный (не короткая) OrderByDescending
  • самый длинный (только один) - FirstOrDefault

Реализация

string source = .... 

var result = source 
    .Split('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') 
    .Where(line => line.Any(c => c >= 'A' && c <= 'Z')) // or char.IsUpper(c) 
    .OrderByDescending(line => line.Length) 
    .FirstOrDefault(); // null if there're no such substrings at all 
+1

Аналогично, с 'Regex', вы можете использовать' Split (@ "\ d") ', затем' IsMatch ("[A-Z]") '. – Scott

+1

да, но если ОП не знает о функции «Сплит», не говоря уже о Linq, как можно было бы ожидать, что OP будет понимать Regex независимо от того, насколько простым или сложным является выражение ...? просто подумать о – MethodMan

+1

@MethodMan: Я вижу; но я также думаю, что проблема хорошая, чтобы продемонстрировать силу Linq, как сложная проблема может быть решена всего в четырех строках (и, следовательно, поощрять инвестировать некоторое время на изучение техники Linq) –

1

В качестве альтернативы ответа Linq, и если я вас правильно понимаю, это то, что я хотел бы сделать, заменив содержимое of str. Все условия:

string qualifier; 
string tempQualifier; 
bool containsUpper = false; 
for (int i = 0; i < str.Length(); i++) { 
    tempQualifier += str[i]; 
    if (char.IsNumber(str[i])) { 
     if (containsUpper) { 
      if (tempQualifier.Length > qualifier.Length && tempQualifier.Length != str.Length) { 
       qualifier = tempQualifier; 
      } 

      containsUpper = false; 
     } 

     tempQualifier = ""; 
    } else if (char.IsUpper(str[i])) { 
     containsUpper = true; 
    } 
} 

return qualifier; 

Это будет проходить через строку, создавая подстроку, пока она не встретится с числом.Если подстрока содержит заглавную букву и длиннее любого предыдущего квалификатора, она сохраняется как новый квалификатор (также предполагая, что это не длина предоставленной строки). Извиняюсь, если я допустил какие-либо ошибки (я не очень разбираюсь в C#).

Это намного дольше, чем ответ Linq, но я подумал, что вам будет удобно разобраться в этом процессе, чтобы вы могли понять его лучше.

+0

Спасибо! Исходя из вашего предложения, я редактировал свой код. Теперь он возвращает длину самой длинной подстроки (строки ввода пользователя), которая не имеет цифр и, по крайней мере, одну заглавную букву. Однако, если вы видите в конце, пожалуйста, где я узнаю длину самой длинной подстроки, если мой список пуст (т. Е. В списке не найдена и не помещена соответствующая подстрока), моя программа, конечно, так как 'passwordList [0];' будет неопределенным. Итак, я попытался проверить пустое использование с помощью оператора if, но тогда строка 'mayLength' будет недоступна (прокомментировано if) – Joshua

Смежные вопросы