3 Ocak 2015 Cumartesi

String Algoritmaları

String Sınıfları
Bir çok dil içinde bir string sınıfı gelmektedir. 
C++ için #include <string> yapmak gerekir.

Substring Metodları
Bir çok dilde substring metodu substring (startindex, endindex) şekilnde çalışır.

memmove ve memcpy

C dilinde string.h ile beraber memmove ve memcpy fonksiyonları geliyor. Bu fonksiyonların string kullanımı ile direkt ilgisi yok, ancak karşımıza çokça çıktığı için buraya ekliyorum.

memmove
Üstüste çakışan iki bellek alanını bile doğru şekilde kopyalamak için aşağıdakine benzer bir şekilde çalışır. Örneğin array'in başındaki bir elemanı, sağa kaydırarak kopyalamak gibi düşünülebilir.

//It ensures that memory is not corrupted even if source and destination overlap
void memmove (void* destination, const void* source, size_t size){
 char* dest = destination;
 const char* src = source;
 //Burada çakışma durumuna bakılıyor
  if ( (src < dest) && (dest < (src + size)){
    for (dest += size, src += size; size > 0; --size) {
      *--dest = *--src;
    } //for
  }//if
  else {
   while (size > 0) {
     size --;
     *dest++= *src++;
   }//while
 }//else
 return (destination)
}
memcpy
Aşağıdaki açıklama çakışan bellek alanları için bu çağrıyı kullanmamamız gerektiğini belirtiyor.
"If copying takes place between objects that overlap, the behavior is undefined".

ASCII
C++
isalpha
Konuyu ASCII başlıklı yazıya taşıdım.

iswalpha
Bu metod ise anladığım kadarıyla daha doğru çalışıyor.

isdigit
Bu metod verilen karakterin rakam olup olmadığını bulur.
 
Karşılaştırma
C
strcmp() ve strncmp() metodları ile NULL ile biten stringler büyük küçük harf farkına göre karşılaştırılır. strcasecmp() ise POSIX ile geliyor ve büyük küçük harf farkına bakmadan karşılaştırma yapar. Buradaki linkte bu metodun nasıl gerçekleştirileceği gösterilmiş.

Upon completion, strcmp() shall return an integer greater than, equal to, or less than 0, if the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2, respectively.
strcmp sıfırdan küçük bir değer dönecekse herhangi bir şey dönebilir. -1 veya -5 bile olabilir. Eğer her iki string de sabit (constant) ise derleyici constant folding -yani sonucu derleme esnasında hesaplam - işlemi de yapabilir.

C++
compare() metodu ile iki string karşılaştırılabilir. Bu metod strcmp() ile aynı şekilde çalışır. Eğer sunuç 0 ise iki string eşittir.

Java
equalsIgnoreCase(String) ile büyük küçük harf farkına bakmadan karşılaştırma yapılabilir.
equals() metodu basit bir döngü içinde harfleri karşılaştırıyor


compareTo
Java'daki bu metod lexicographical (sözlüksel) olarak karşılaştırma yapar. Daha çok sıralama işlemi için kullanılır ancak döndürdüğü değerler ilginç.  İki harfin arasındaki büyüklük farkını döndürüyor. Bizim için esas olan bu büyüklüğün 0'dan küçük, 0 veya 0'dan büyük olması.

Lexical sıralama yapmak için aşağıdaki örnek kullanılabilir.
Arrays.sort(input, new Comparator<Integer>() {
   @Override
   int compareTo( Integer x, Integer y ) {
      return x.toString().compareTo( y.toString() );
   }
};

 
All
String'in tamamının rakam olup olmadığını anlama
C#
All() metodu kullanılır. Örnek:
 
Replace
boost
replace_first : ile ilk eşleşen string, yeni string ile yer değiştirir.

replace_all : ile bir string içindeki tüm karakterleri silmek mümkün. Örnek:
 

Java
String.replace(oldChar,newChar) : ile ilk eşleşen karakter, yeni karakter ile yer değiştirir.

replaceFirst : düzenli ifade ile eşleşen karakterler verilen string ile yer değiştirir. Örnek:

String.replaceAll (regex,replacement) : düzenli ifade ile eşleşen karakterler Örneğin string içindeki tüm boşlukları silmek için aşağıdaki kod kullanılabilir.
String sAfter = sBefore.replaceAll("\\s+", "");//replace white space and tabs
replaceAll düzenli ifade kullandığı için birden fazla karakteri değiştirmek için aşağıdakine benzer kod kullanılabilir.

C++

STL algoritmalarından olan std::replace ile std::replace(s.begin(), s.end(), 'a', 'b'); yöntemini kullanarak belli karakterleri değiştirmek kolay. Bu işlem çalışyor çünkü std::replace

void replace ( ForwardIterator first, ForwardIterator last,const T& old_value, const T& new_value );  

şeklinde tanımlı.

C#
Regex.Replace ile javadakine benzer şekilde replaceAll() yapabilmek mümkün. Örnek :

string_text = Regex.Replace(string_text, @"\s+", " ");
Trim
Trim işlemi ile string'in solundan veya sağından bazı karakterler silinir.
boost 
trim_right_if :String'in sağ tarafı eşleşiyorsa, eşleşen kısım silinir.
Örnek
std::string name = "Steve_Smith__";
trim_right_if(name, is_any_of("_"));//Steve_Smith verir
C#
String'in solundaki 0'ları silmek için örnek:

Bir Karakteri Arama
C
İlk karakteri aramak için strchr() kullanılır.

char* strchr (const char* s, int c){
  char* r = (char*) s;
  while (*r != (char) c) {
    if (*r ++ == '\0')
      return NULL;
  }
  return r;
}

En son karakteri aramak için strrchr() kullanılır.

char* strrchr (const char* s, int c){
  char* save = NULL;
  do{
    if (*s == (char) c) {
      save = s;
    }
  } while (*s++ != '\0');
  return save;

Java
indexOf() metodu kullanılır.
 
Contains

Bir string'in bir başka string içinde olup olmadığını anlama örneği.
Apache Commons
org.apache.commons.lang3.StringUtils sınıfı ile yapılabilir. Örnek:
StringUtils.containsIgnoreCase("ABCDEFGHIJKLMNOP", "gHi");
C++
string'in find metodu kullanılabilir. Örnek:
 
Ends With
C#
Aşağıdaki örnekte büyük küçük harf farkına bakılmaz 
string s =  "Steve_Smith__";
if (s.EndsWith("_",StringComparison.OrdinalIgnoreCase))
{
    //..
}
C++
Örnek :
bool has_suffix(const std::string &str, const std::string &suffix)
{
    //Ensure that string's size is not less than suffix.
    //Then use string.compare() method for comparison
    return str.size() >= suffix.size() &&
           str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

boost
Örnek:
#include <boost/algorithm/string/predicate.hpp>

if (boost::ends_with(fileName, ".txt")) { /* ... */ }

Verilen String'in Sol Tarafını Alma
Örneğin "abcdefg" içindeki "fg"'nin sol tarafını alma
Guava
ChartMatcher sınıfını trimTrailingFrom() metodu ile yapılabilir.

String'in boş olup olmadığını anlama
C
strlen ile yapılabilir. Aşağıda optimize bir strlen örneği var.
size_t strlen (const char* s) {
  const char* save = s + 1;
  while (*s ++ != '\0')
  ;
  return (s - save );
}
 
Java
Apache Commons ile gelen StringUtils.isBlank veya Spring ile gelen StringUtils.hasText metodları ile String'in boş olup olmadığı anlaşılabilir. 

Split
Konuyu String Split başlıklı yazıya taşıdım.

Collection İçindeki String'i Bulma
C++ 
std::search  ile bulunabilir
C#
Linq ile çok kolay.
var items = new List<string>();
items.Add("Oliver");
items.Add("Olsen");
items.Add("learns");
items.Add("how");
items.Add("change");
items.Add("world");
items.Add("engaging"); 
items.Where(item => item.StartsWith(prefixText))
     .OrderBy(item => item)

Collection İçindeki String'leri Sıralama
Java
Basit bir Comparator ile aşağıdaki gibi yapılabilir.
Base64 İşlemleri
Konuyu Base64 başlıklı yazıya taşıdım.

Clone İşlemleri
C
strdup
strdup ile verilen string'i kopyalamak mümkün. Aşağıda strdup'un kodu var.

Kullanım şekline bir örnek ise:

strcpy
Aynı şeyi strcpy ile başarmak ta mümkün ancak strdup ile aynı kapıya çıkıyor. Aradaki tek fark strcpy ile string'in NULL terminated olduğu garanti ediliyor. strdup bunu yapıyormu bilimiyorum.
char *line = malloc(strlen(buf) + 1);
strcpy(line, buf);
line[strlen(buf)] = 0;
String Birleştirme İşlemleri
C
strcat veya strncat ile iki stringi birleştirmek mümkün.
char * strcat ( char * destination, const char * source );
Aşağıda strncat sınıfı var.
char* strncat (char* dst, const char* src, size_t n){
  if (n != 0){
    char* d = dst;
    while (*d++ != '\0'); //Find end of string
    d--; //Rewind back of EOS

    while ( ( (*d++ = *src != '\0') && (--n >0) ) );
    if (n == 0){
     *d = '\0'; // null terminate string
    }
  }// n!= 0
  return dst;
}
Eğer bir string ortadan birleştirilmek istenirse aşağıdaki gibi yapılabilir.

Integer'ı String'e Çevirme
C
Çok kolay bir yöntem burada. Eğer integer'ın 0-9 arasında olduğunu biliyorsak, ASCII karakter değeri şöyle bulunabilir.
char c = '0' + count;
String'i Integer'a Çevirme
C
String'i Integer'a Çevirme yazısına taşıdım.

C++
String'i Integer'a Çevirme yazısına taşıdım.

boost
lexical_cast kullanılabilir. boost'un C metodlarına göre artısı, hatalı durumlarda bad_lexical_cast exception atmaları. Böylece hata daha kolay yakalanabiliyor.


Küçük Harfe Çevirmek İşlemleri

C++
Bu işlem UTF-8 için her zaman çalışmayabilir. Encoding'ing 1 byte kullanması gerekir.
 
std::tolower() ile locale'e uygun olarak küçük harfe çevirmek kolay. Eğer bunu kullanmak istemiyorsak aşağıdaki örneği kullanabiliriz.


boost
Örnek:
boost::to_lower_copy(fs::canonical(path).string())
Switch/Case İşlemleri
Java 7
switch (s.ToUpperCase()) şeklinde kullanmakta fayda var.

Join
Apache Commons
StringUtils.join ile yapılıyor. Örnek:
StringUtils.join(myList,',');
boost
Örnek:
#include <boost/algorithm/string/join.hpp>
std::vector<std::string> fields = { "foo", "bar", "baz" };
string joined_case = boost::algorithm::join( fields, "|" );

Hiç yorum yok:

Yorum Gönder