Frage

Ich frage mich, wie diese Sprache in einer funktionalen Programmierung zu tun. Vielleicht F # oder Haskell.

Kann jemand zeigen Sie mir ein Beispiel ohne Verwendung von Funktionsaufrufen mit Ausnahme find und rfind?

Diese Funktion findet die nächste slash i als num von slash mit (<0 für rückwärts).

size_t findSlash(const char *sz, size_t i)
{
    std::string s = sz;
    size_t a, b, c, n, ai = abs(i), pos=0;
    for (n=0; n<ai; n++)
    {
        if (i<0)
        {
            a = s.rfind("\\", pos);
            b = s.rfind("/", pos);
        }
        else
        {
            a = s.find("\\", pos);
            b = s.find("/", pos);
        }
        if (a==-1u)
        {
            if (b==-1u)
                return pos;
            c = b;
        }
        else if (b==-1u)
            c = a;
        else
            c = min(a, b);
        pos = c+1;
    }
    return c;
}
War es hilfreich?

Lösung

Im ersten, den Code ist gebrochen. size_t ist unsigned Typ und kann nie i<0 werden.

Im zweiten, Ihr Code ist hässlich std Bibliothek Missbrauch und unwirksam. Es sollte Bibliothek für reguläre Ausdrücke oder solche oder Verwendung in Handarbeit Scanner eingesetzt werden. Code ergibt, ist viel sauberer und schneller. Zum Beispiel (ich habe mit C seit vielen Jahren nicht, aber unter Code in 10 Minuten in Handarbeit funktioniert.):

size_t findSlash(const char *sz, int i)
{
    const char *s = sz;
    if (i<0) {
        for(;*s;s++);
        for(;;s--){
            if(s<sz) return -1;
            if((*s == '/') || (*s == '\\'))
                if(! ++i) break;
        }
    }
    else {
        for(;;s++){
            if(! *s) return -1;
            if((*s == '/') || (*s == '\\'))
                if(! i--) break;
        }
    }
    return s-sz;
}

Ich habe nicht verwendet Haskell oder F # zu schreiben, aber zum Beispiel unter Code in Erlang sollte als Beispiel angeben, wie es in funktionaler Sprache zu tun:

findslash(L, I) when is_list(L), is_integer(I) ->
    if  I<0  ->
            case findslash(lists:reverse(L), -1*I - 1, 0) of
                none -> none;
                X -> length(L) - X - 1
            end;
        I>=0  -> findslash(L, I, 0)
    end.

findslash([H|_], 0, X) when H=:=$/; H=:=$\\ -> X;
findslash([H|T], I, X) when H=:=$/; H=:=$\\ ->
    findslash(T, I-1, X+1);
findslash([_|T], I, X) -> findslash(T, I, X+1);
findslash([], _, _) -> none.

Mein Versuch in Haskell mit Fehlerprüfung und hält Faulheit für i> = 0:

findSlash :: String -> Int -> Maybe Int
findSlash str i
  | i <  0 = reversed (_findSlash (reverse str) (-1*i-1) 0)
  | i >= 0 = _findSlash str i 0
    where
      reversed Nothing  = Nothing
      reversed (Just a) = Just ((length str) - a - 1)
      _findSlash (x:xs) i n
        | x == '/' || x == '\\' = if i==0 then Just n else _findSlash xs (i-1) (n+1)
        | True                  =                          _findSlash xs  i    (n+1)
      _findSlash []     _ _     = Nothing

Andere Tipps

Haskell:

import Data.List

findSlash :: String -> Int -> Int
findSlash str i = findIndices (\c -> c == '\\' || c == '/') str !! i

Umgang mit dem negativen Index (was hässlich ist, weil du wirklich nicht, es tun wollen):

findSlash :: String -> Int -> Int
findSlash str i =
    index (findIndices (\c -> c == '\\' || c == '/') str) i
          where index xs i | i  < 0 = (reverse xs) !! ((-i) - 1)
                           | i >= 0 = xs !! i

Handhabung Fehler:

findSlash :: String -> Int -> Maybe Int
findSlash str i = index i
    where xs = findIndices (\c -> c == '\\' || c == '/') str
          l = length xs
          index i
              | i <  0 && i < (-l) = Nothing
              | i >= 0 && i >= l   = Nothing
              | i <  0             = Just $ (reverse xs) !! ((-i) - 1)
              | i >= 0             = Just $ xs !! i

Jetzt können Sie sagen:

map (findSlash "/foo/bar/baz") [-4..4]

und erhalten:

-- -4        -3     -2     -1      0      1      2       3       4
[Nothing,Just 0,Just 4,Just 8,Just 0,Just 4,Just 8,Nothing,Nothing]

Wie auch immer, die Handhabung von dem Ende der Offset macht den Code ziemlich hässlich, und ruiniert die Möglichkeit für faule Auswertung. Also ich denke, die meisten Menschen den ersten benutzen würden, vielleicht mit einem wenig Fehlerprüfung in geworfen. (Was auch Faulheit tötet, da Länge Auswertung der gesamten Liste zwingen würde. Sie können „Drop“ anstelle von „!!“ um Fehler zu vermeiden und die Auswertung der gesamten Ergebnisliste zu verhindern, jedoch. TMTOWTDI.)

Sie können eine reine Funktionscode in reinem C schreiben:

/** Return pointer to the `n`-th occurrence of any char from `chars` in `s`.

    Return NULL if it can't find the `n`-th occurrence.  
    Start at the end of `s` if `n` is negative.
    `n` is zero-based.
*/
const char* 
find_nth(const char* s, int n, const char* chars) 
{
  if (n < 0) return rfind_nth(s, -(n+1), chars);
  if (! (s && *s)) return NULL;
  if (find(chars, *s)) return (n == 0) ? s : find_nth(s+1, n-1, chars);
  else return find_nth(s+1, n, chars);
}

Volles Programm:

#include <string.h>

const char* 
find(const char* s, char c) 
{
  if (! (s && *s)) return NULL;
  return (*s == c) ? s : find(s + 1, c);
}

const char* 
rfind_nth_range(const char* s, const char* end, size_t n, const char* chars)
{
  if (! (s && end && (end - s) > 0)) return NULL;
  if (find(chars, *(end - 1))) // `*(end-1)` is in `chars`
    return (n == 0) ? end - 1 : rfind_nth_range(s, end - 1, n-1, chars);
  else
    return rfind_nth_range(s, end - 1, n, chars);
}

const char* 
rfind_nth(const char* s, size_t n, const char* chars)
{
  return rfind_nth_range(s, s + strlen(s), n, chars);
}

int 
main(void) 
{
  const char* const s = "ab/cd\\e";
  return !(find_nth(s, 1, "/\\") == (s+5));
}

Also, äh, was ist das? Ist es findet nur den ‚i-ten Strich (vorwärts oder rückwärts) in der Zeichenfolge (oder den‘ -i'th vom Ende, wenn ich negativ ist)? Ich bin nicht sicher, ob ich es richtig nur aus der Lektüre den Code interpretiert.

Auf jedem Fall wäre es in dem Hafen einfach sein, aber es ist nicht klar, was Ihr Ziel / Zweck ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top