kozioł napisał(a):Owa funkcja właśnie do tego służy:
To jednak Ty nieuważnie to przeczytałeś lub nie zrozumiałeś.
Odczytuje dane z ciągu znaków i zapisuje je w zależności od parametru formatu w miejscach podanych przez dodatkowe argumenty. Miejsca wskazane przez wszystkie dodatkowe argumenty są wypełnione odpowiednimi typami wartości określonymi w ciągu formatu. |
Więc jak widzisz nie służy do wyciągania liczb z ciągu znaków, lecz do odczytywania ciągu znaków w zależności o formatu.
[=%[*][ szerokości] [modyfikatory] typ =][/b]
gdzie:
* -
gwiazdka oznacza, że dane mają być pobrane z string str, ale ignorowane, tj. nie są przechowywane.szerokość -
określa maksymalną liczbę znaków do odczytu w obecnej operacji czytaniamodyfikatory -
Specifies a size different from int (in the case of d , i and n ), unsigned int (in the case of o , u and x ) or float (in the case of e , f and g ) for the data pointed by the corresponding additional argument:
h : short int (for d , i and n ), or unsigned short int (for o , u and x ) h: short int (na d, i oraz n), lub unsigned short int (na o, u, x)
l : long int (for d , i and n ), or unsigned long int (for o , u and x ), or double (for e , f and g ) l: long int (na d, i oraz n), or double (do o, u, x) lub podwójne (dla e, f, g) L : long double (for e , f and g ) L: long double (e, f, g) (za długie nie chce mi się tłumaczyć) typ -
typ znaków określający rodzaj danych, które należy czytać, oraz sposób ich odczytywaniaJak to ma się do Twojego kodu, ano tak:
- Kod: Zaznacz cały
char sentence [] = "Greys.Anatomy.S03E20.HDTV.XviD2HD.VTV.avi";
int i, j;
sscanf (sentence, "%*[Greys.Anatomy.] %*[S] %d %*[E] %d", &i, &j);
Memo1->Lines->Add((String)i + " " + (String)j);
Teraz odczyta. Przede wszystkim musisz zachować kolejność pobieranych znaków, więc jeżeli chcesz pominąć
Greys.Anatomy. i
S to musisz podstawić tam typ z gwiazdką
%*typ, ale taki typ
[a-zA-z0-9.] nie przejdzie, gdyż ta funkcja nie rozpoznaje takiego typu. Musisz podać albo długość ciągu znaków który ma być pominięty, czyli
%*14s, albo
%*[Greys.Anatomy.], czyli szerokość ciągu znaków. Potem chcesz pominąć
S więc również
%*S, ale w związku z wcześniejszym nie ma sensu dzielić tak tego. Dalej masz liczbę którą pobierasz do zmiennej typu int, więc
%d, potem pomijasz E, więc
%*[E], potem znów zmienna typu int więc
%d, a ponieważ więcej nie pobierasz więc resztę pomijasz.
Problem stanowi
szerokość, gdybyś zamiast tych kropek miał spacje, to można by ten problem rozwiązać, bez podawania szerokości łańcucha znaków. Trzeba więc zamienić kropki na spacje:
kod dla C++Builder wersja 2007 i wcześniejsze.- Kod: Zaznacz cały
String tekst = "Greys.Anatomy.S03E20.HDTV.XviD2HD.VTV.avi";
tekst = StringReplace(tekst, ".", " ", TReplaceFlags() << rfReplaceAll).Trim();
int i, j;
sscanf (tekst.c_str(), "%*s %*s %*[S] %d %*[E] %d", &i, &j);
Memo1->Lines->Add((String)i + " " + (String)j);
Teraz działa - sprawdź!
Nie łatwo będzie jednak to zautomatyzować, gdyż nie wiesz ile spacji wystąpi przed S, jeżeli tytuł programu składa się z dwóch wyrazów to i spacje będą dwie, wtedy format wygląda tak
"%*s %*s", ale przy mniejszej i większej liczbie spacji trzeba odpowiednio modyfikować formant.