Mam tablicę która ma 1440000 elementów. Potrzebuję wywalić co drugi czyli 1,3,5..7777,7779... etc. Jest może jakaś gotowa funkcja? Mogę to zrobić w pętli ale może znajdzie się gotowiec ;>
Pętla... Skaczesz co drugi element.
Robisz w pętli i dzielisz wartość indeksu tabeli modulo przez 2. Jeśli wynik == 0 to usuwasz ten element. Chyba że chcesz z tego zrobić drugą tablicę to przepisujesz tylko tą co drugą wartość.
Zrobiłem tak:
for (int x = 0; x < (8006003); x++){
if (x%2==0) {
bitslow[x/2] = bits[x];
}
}
Ale coś nie działa (bitslow to nowa, mniejsza tablica) :(
const unsigned int size = 1440000;
int* twojaGlupiaTablica = new int[size];
int* nowaGlupiaTablica = new int[size/2+1]; //+1 jeden takie zabezpieczenie, nie wiem szczerze czy jest potrzebne, nie chce mi się myśleć.
for(unsigned int i = 1; i<size;i+=2) nowaGlupiaTablica[i>>1] = twojaGlupiaTablica[i];
No to móiwe robie jak ty:
const unsigned int size = 1440000;
unsigned char* bitslow = new unsigned char[400*300*3];
for(unsigned int i = 1; i<size; i+=2) bitslow[i>>2] = bits[i];
I crash programu (C::B)</del>
Mój błąd to crash był przez dalszy kod
Zastanawiałem się czy można to prosto zrobić za pomocą algorytmów z biblioteki standardowej. Okazuje się, że chyba nie ma niczego odpowiedniego. Inspirując się postem na stackoverflow napisałem takie coś do kopiowania co któregoś elementu:
template<typename InputIt, typename OutputIt>
OutputIt copy_every_nth(InputIt first, InputIt last, OutputIt d_first, size_t nth) {
if (nth == 0) {
throw std::invalid_argument("copy_nth: nth can't be 0");
}
size_t counter = 0;
auto pred = [&counter, nth]
(const typename std::iterator_traits<InputIt>::value_type &) -> bool {
return !(counter++ % nth);
};
return std::copy_if(first, last, d_first, pred);
}
W podobny sposób można napisać remove_every_nth
(zamieniając copy_if na coś innego z _if) itd. Oczywiście to bardzo ogólny zapis i prawdopodobnie prościej jest zrobić normalną pętlę z odpowiednimi licznikami, wrzucam, bo może komuś się przyda. ;-) (Najbardziej podoba mi się ogromny typ argumentu lambdy, który i tak nie jest potrzebny :->) Inną możliwością jest napisanie ładnego funktora, to teraz to po prostu algorithm-style.
O, funktor będzie np. taki:
class EveryNth {
public:
EveryNth(size_t nth) :
mNth(nth),
mCounter(0) {
if (mNth == 0) {
throw std::invalid_argument("EveryNth: nth can't be 0");
}
}
template<typename T>
bool operator()(const T &) {
return !(mCounter++ % mNth);
}
// Mało potrzebne, ale niech będzie.
void reset() {
mCounter = 0;
}
private:
size_t mNth;
size_t mCounter;
};
Na dobrą sprawę to funkcjonalnie dokładnie to samo co ta lambda tylko zajmuje więcej miejsca. ;-) Można też wprowadzić dodatkowe funktory dla mniej ogólnych przypadków, żeby pozbyć się modulo. (Tak jak niżej)
Boost ma za to ładne adaptery iteratorów.
@Endrju, przecież jest już gotowy remove_if
struct Odd
{
bool f;
Odd():f(true) {}
bool operator()(int) { f=!f; return f; }
};
int main()
{
int tb[]={1,2,3,4,5,6,7,8,9},n=sizeof(tb)/sizeof(*tb);
for(int i=0;i<n;++i) cout<<" "<<tb[i]; cout<<endl;
n=remove_if(tb,tb+n,Odd())-tb;
for(int i=0;i<n;++i) cout<<" "<<tb[i]; cout<<endl;
cin.sync(); cin.get();
return 0;
}
Ewentualnie: remove_if_copy
Ewentualnie:
bool Odd(int)
{
static bool f=true;
f=!f;
return f;
}
Chociaż to nie jest bezpieczne rozwiązanie mimo że prostsze, ponieważ przed remove_if trzeba zrobić coś dziwnego:
if(!Odd(0)) Odd(0);
Nie potrzebnie próbujecie wcisnąć tam coś z <algorithm>. Czyż takie coś
template <class InputIterator, class OutputIterator>
OutputIterator copy_even(InputIterator first, InputIterator last, OutputIterator result)
{
while(first != last && ++first != last) *result++ = *first++;
return result;
}
nie będzie eleganckie?