سؤال

ولدي الأمراض المنقولة جنسيا :: ناقلات m_vPaths. وسوف تكرار هذه النواقل، وندعو :: DeleteFile (strPath) كما ذهبت. إذا كنت بنجاح حذف الملف، وسوف إزالته من النواقل. سؤالي هو هل يمكنني الحصول على حول الحاجة إلى استخدام متجهين؟ هناك بنية البيانات المختلفة التي قد تكون أكثر ملاءمة لماذا يجب أن أفعل؟

وعلى سبيل المثال: باستخدام التكرارات تقريبا يفعل ما أريد، ولكن المشكلة بمجرد محو باستخدام مكرر، كل المكررات تصبح غير صالحة.

 std::vector<std::string> iter = m_vPaths.begin();
    for( ; iter != m_vPaths.end(); iter++) {
        std::string strPath = *iter;
        if(::DeleteFile(strPath.c_str())) {
            m_vPaths.erase(iter);   
                //Now my interators are invalid because I used erase,
                //but I want to continue deleteing the files remaining in my vector.    
        }
    }

ويمكنني استخدام اثنين من ناقلات وأنا لم يعد لدينا مشكلة، ولكن هناك، طريقة أكثر كفاءة أفضل من أن يفعل ما أحاول القيام به؟

وراجع للشغل، طارئ أنه من غير الواضح، وأعلن m_vPaths مثل هذا (في صفي):

std::vector<std::string> m_vPaths;
هل كانت مفيدة؟

المحلول

std::remove_if :

#include <algorithm> // for remove_if
#include <functional> // for unary_function

struct delete_file : public std::unary_function<const std::string&, bool> 
{
    bool operator()(const std::string& strPath) const
    {
        return ::DeleteFile(strPath.c_str());
    }
}

m_vPaths.erase(std::remove_if(m_vPaths.begin(), m_vPaths.end(), delete_file()),
                m_vPaths.end());

واستخدام std::list لوقف مشكلة المكررات غير صالحة، على الرغم من أن تفقد عشوائي التمكن من. (وأداء ذاكرة التخزين المؤقت، وبصفة عامة)


لالمحضر، فإن الطريقة التي ستنفذ التعليمات البرمجية الخاصة بك على النحو التالي:

typedef std::vector<std::string> string_vector;
typedef std::vector<std::string>::iterator string_vector_iterator;

string_vector_iterator iter = m_vPaths.begin();
while (iter != m_vPaths.end())
{
    if(::DeleteFile(iter->c_str()))
    {
        // erase returns the new iterator
        iter = m_vPaths.erase(iter);
    }
    else
    {
        ++iter;
    }
}

ولكن يجب عليك استخدام std::remove_if (إعادة اختراع العجلة سيئة).

نصائح أخرى

erase() الأسلوب بإرجاع مكرر الجديد (صالح) أن نقطة إلى العنصر التالي بعد واحد حذفه. يمكنك استخدام هذا مكرر على الاستمرار في حلقة:

std::vector<std::string>::iterator iter;
for (iter = m_vPaths.begin(); iter != m_vPaths.end(); ) {
    if (::DeleteFile(iter->c_str()))
        iter = m_vPaths.erase(iter);
    else
        ++iter;
}

ونظرا لضيق الوقت لمحو ملف، فإنه ربما لا يهم، ولكن كنت لا تزال ينصح بالتكرار عبر متجه إلى الوراء - وبهذه الطريقة كنت حذف عادة عناصر من (بالقرب من) نهاية النواقل. الوقت المستغرق لحذف عنصر يتناسب مع عدد من العناصر التالية في ناقلات. إذا (على سبيل المثال) لديك متجه من 100 أسماء الملفات، وبنجاح حذف كل منهم، وعليك نسخ العنصر الأخير 100 مرة في عملية (ونسخ الثانية إلى العنصر الأخير 99 مرات، وهلم جرا).

وOTOH، إذا كنت تبدأ من نهاية والعمل الى الوراء، لا نسخ طالما حذف الملفات غير ناجحة. يمكنك استخدام التكرارات العكسي لاجتياز متجه إلى الخلف دون تغيير الكثير من أي شيء آخر. على سبيل المثال، يجب كود جي-مان باستخدام remove_if مواصلة العمل (فقط صبي أسرع) ببساطة عن طريق استبدال rbegin () لتبدأ ()، وتمزق () للنهاية.

وهناك احتمال آخر هو استخدام صف مزدوج الذيل بدلا من ناقلات - في صف مزدوج الذيل يمكن أن يمحو العناصر من نهاية <م> أو بداية جمع في وقت ثابت

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top