سؤال

كان هناك تعليق عابر في أحد كتبي حول قيام الأشخاص بإدخال فواصل في الأعداد الصحيحة وإفساد برنامجك، لكنه لم يوضح الأمر.هذا جعلني أفكر، لذلك حاولت كتابة خوارزمية صغيرة لأخذ سلسلة std::string وإزالة جميع الأحرف غير الصحيحة.يجمع هذا الرمز ولكنه يتخطى الإخراج.لماذا لا يتم تعيين أي شيء إلى newstring؟هل يتم تقييم if(isdigit(fstring[i])) على أنه صحيح للعنوان الذي يشير إلى أنه يحتوي على رقم؟

//little algorithm to take the non-integers out of a string
//no idea on efficiency

#include <iostream>
#include <string>

int main()
{
    std::cout << "Enter a number with non-integer characters: ";

    std::string fstring; 
    getline(std::cin, fstring);

    std::string newstring;

    int i = 0, x = 0;

    while (i != fstring.length())
    {
        if (isdigit(fstring[i]))
        {
            newstring[x] = fstring[i];
            i++;
            x++;
        }
        else
        {
           i++;
        }
    }

    std::cout << std::endl;
    std::cout << newstring;
    system("PAUSE");
}

سؤال ثانوي، ربما ينتمي إلى مكان آخر:كيف يمكنك تحويل سلسلة إلى int (أو رقم النقطة العائمة)؟

هل كانت مفيدة؟

المحلول

وnewstring هو من طول 0، لذلك newstring [س] حيث x = 0 غير قانوني في الواقع. يجب إلحاق سلسلة باستخدام: newstring.append (1، fstring [أنا])

وبالنسبة للسؤال الثانوي، والبحث عن atoi ()، atof ()، strtol (0، strtof () وظائف.

نصائح أخرى

وسلاسل تشبه المصفوفات، ولكن المنشئ الافتراضي لسلسلة يخلق سلسلة فارغة. لماذا يجب أن تخصص المزيد من الذاكرة من يحتاج إليها؟ حتى لو فعلت ذلك، ليس هناك قائلا: كم، أو إذا كان سوف تكون كبيرة بما فيه الكفاية للحصول على نسخة المصفاة من fstring. أنا معجب أنه لا تحطم الطائرة.

وهناك تعديل بسيط يتمثل في تغيير:

std::string newstring;

إلى:

 std::string newstring(fstring.length(), '\0')

وبعد الوظيفة حلقة:

 newstring.resize(x);

وهذه ستضمن أن newstring يكون ما لا يقل عن مساحة كافية (وربما أكثر) خلال الترشيح وسيتم تشذب إلى الحجم المناسب عندما تكون التصفية النهائية. قد تكون مهتمة ايضا في std::remove_copy_if وظيفة في <algorithm> أيضا.

ومنها مثلا.

struct isnotdigit { bool operator()(char c) { return !isdigit(c); } };

std::string newstring(fstring.length(), '\0');
std::string::iterator i = std::remove_copy_if(fstring.begin(), 
  fstring.end(), newstring.begin(), isnotdigit());
newstring.erase(i, newstring.end());

وأما بالنسبة لتحويل سلسلة إلى عدد صحيح / تعويم، بالإضافة إلى atoi، strtol، atof، strtof إلخ. وظائف سبق ذكرها يمكنك أيضا جعل استخدام من مكتبة iostream:

 #include <sstream>
 std::string integer("23");
 std::istringstream iss(integer);
 int result;
 iss >> result;

 std::string floatingpoint("3.14");
 std::istringstream iss2(floatingpoint);
 double result2;
 iss2 >> result2;

وأيضا، إذا كنت معتادا على الأسرة printf من الوظائف التي قد تكون مهتمة في scanf، sscanf

 const char *s = "23";
 int result;
 sscanf(s, "%d", &result);

والتوسع في الإجابة شينغ ييب ل:

لإزالة غير الأرقام:

#include <iostream>
#include <functional>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    string fstring;
    getline(cin, fstring);
    fstring.erase(
        remove_if(fstring.begin(), fstring.end(),
            not1(ptr_fun(static_cast<int(*)(int)>(isdigit)))
        ),
        fstring.end()
    );

    cout << fstring << "\n";
}

وأنا لست متأكدا من السبب في أن هناك حاجة إلى static_cast، وإن كان. أعتقد أن شيئا ما غامضا حول isdigit دون ذلك. [تحرير: إذا كنت لا تفعل "باستخدام مساحة الأمراض المنقولة جنسيا" فإنك لا تحتاج إليها، لذلك خطأي لكونه كسول كتابة رمز المثال]

وانها قابلة للنقاش ما إذا كان هذا هو أبسط من أي المتداول حلقة الخاصة بك:

#include <iostream>
#include <string>

using namespace std;

int main() {
    string fstring, ins;
    getline(cin, ins);
    for (string::iterator it = ins.begin(); it != ins.end(); ++it) {
        if (isdigit(*it)) fstring.push_back(*it);
    }
    cout << fstring << "\n";
}

وC ++ 0X سيكون copy_if، الذي استبعد أساسا عن طريق الصدفة، وغير تافهة لتنفيذ:

#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>

int main() {
    std::string fstring, ins;
    std::getline(std::cin, ins);
    std::copy_if(ins.begin(), ins.end(), 
        std::back_inserter(fstring), isdigit);
    std::cout << fstring << "\n";
}

لتحويل لكثافة العمليات (أو تعويم):

int i = boost::lexical_cast<int>(fstring);

وأو إذا لم يكن لديك دفعة:

#include <sstream>

int i = 0;
std::stringstream(fstring) >> i;

لاحظ أن لديك لتهيئة ط، وإلا لن يتم تعيينها إذا fstring فارغ.

لإزالة الأرقام:

fstring.erase(
      std::remove_if(fstring.begin(), fstring.end(), &isdigit), 
      fstring.end());

لتحويل السلسلة إلى int / تعويم /...:

int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
  • سلسلة إلى رقم النقطة العائمة:

أنت بحاجه إلى #include <cstdlib>

float strtof(const char *nptr, char **endptr);

على سبيل المثال:

 float f = strtof("3.4",NULL);
  • سلسلة إلى عدد صحيح

أنت بحاجه إلى #include <cstdlib>

int atoi(const char *numPtr);

لاحظ أن هذه دوال C - وليست C++، لذا تحتاج إلى استخدام طريقة c_str() على std::string للحصول على السلسلة C.

const char* c_str ( ) const;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top