简体   繁体   中英

how to extract integer from a string? c++

i have this line taken from a txt file (first line in the file):

#operation=1(create circle and add to picture) name X Y radius.

why does this code doesnt take the integer 1 and puts it into k?

Circle Circle::CreateCirc(Circle c){
    int k;
    ifstream myfile("cmd.txt");
    if (!myfile.is_open())
        cout<<"Unable to open the requested file "<<endl;
    string line,line2="create circle";
    for (int i=1;i<countrows();i++)
    {
        getline(myfile,line);
        if (line.find(line2)!=string::npos)
        {
             istringstream ss(line);
             ss>>k;
             cout<<k<<endl;

        }

    }
    return c;

}

instead im getting adress memory...help plz

Because the line doesn't start with a number. You'll need to skip over the #operation= part before extracting a number.

You should check the result of the extraction, and of getline , to help identify what's going wrong when these fail.

Also, if countrows() returns the expected number of rows in the file, then your loop would miss out the last one. Either loop from zero, or while i <= countrows() ; or, if you want to process every line in the file, you could simply loop while (getline(myfile,line)) .

If the actual text in the file you try to read starts with "#operation=1" and you want the number 1 from that, you can't use the simple input operator. It will read the character '#' first, which isn't a digit and so the parsing will fail and k will not be initialized. And if k is not initialized, it will be of indeterminate value, and reading that value will lead to undefined behavior and seemingly random output.

You need to check that the extraction worked:

if (ss >> k)
    std::cout << k << '\n';

That won't solve your problem though, as like I said above, you can't use the simple input operator here. You need to parse the string using other methods. One way might be to find the equal character '=' and get a sub-string after that to try and extract the number.

EDIT: A way to do it not much bit a little closer to the way you were trying to do it using atoi() rather than streams.

#include <iostream>
#include <cstdlib> // for atoi()
int main(){

    std::string str = "#operation=1(create circle and add to picture) name X Y radius.";
    int k;

    std::string line=str, line2="(create circle";

    std::size_t fnd = line.find(line2);
    if (fnd!=std::string::npos)
    {
         k = atoi(&str[fnd-1]); // int atoi(const char *str) == argument to integer
         std::cout<< k << " " << str[fnd-1] << str[fnd] << " ";
    }
}

There are a few ways to extract an integer from a string but i like to filter out the digit from the string;

#include <iostream>

int main(){

    std::string str = "#operation=1(create circle and add to picture) name X Y radius.";
    int k = 0;

    // an array of our base10 digits to filter through and compare
    const char digit[] = {'0','1','2','3','4','5','6','7','8','9'};

    for(int s_filter = 0; s_filter<str.size(); ++s_filter){
        for(int d_filter = 0; d_filter<10; ++d_filter){
        // filter through each char in string and
        // also filter through each digit before the next char

            if(digit[d_filter] == str[s_filter]) {
            // if so the char is equal to one of our digits

                k = d_filter;// and d_filter is equal to our digit
                break;

            } else continue;
        }
    }
    switch(k) {
        case 1:
            std::cout<< "k == 1";
            // do stuff for operation 1..
            return 0;
        case 2:
            std::cout<< "k != 1";
            // do more stuff
            break;
        //case 3: ..etc.. etc..
        default:
            std::cout<< "not a digit";
            return 1;
    }
}

try this:

Circle Circle::CreateCirc(Circle c){
 const std::streamsize ALL = std::numeric_limits< std::streamsize >::max(); // #include <limits> needed
 int k;
 ifstream myfile("cmd.txt");
 if (!myfile.is_open())
    cout<<"Unable to open the requested file "<<endl;
 for (int i=1;i<countrows(); ++i, myfile.ignore(ALL,'\n') ) // skip rest of the line
 {
    if( myfile.ignore(ALL,'=') >> k  )
    {
         cout<<k<<endl;
    }
    else
        break; // read error
 }
 return c;
}
// find_num.cpp (cX) 2015 adolfo.dimare@gmail.com
// http://stackoverflow.com/questions/21115457/

#include <string> // std::string
#include <cctype> // isnum

/// Find the number in 'str' starting at position 'pos'.
/// Returns the position of the first digit of the number.
/// Returns std::string::npos when no further numbers appear within 'str'.
/// Returns std::string::npos when 'pos >= str.length()'.
size_t find_num( const std::string str, size_t pos ) {
    size_t len = str.length();
    bool   isNegative = false;
    while ( pos < len ) {
        if ( isdigit(str[pos]) ) {
            return ( isNegative ? pos-1 : pos );
        }
        else if ( str[pos]=='-' ) {
            isNegative = true;
        }
        else {
            isNegative = false;
        }
        ++pos;
    }
    return std::string::npos;
}

#include <cassert>     // assert()
#include <cstring>     // strlen();

int main() {
    std::string str;

    str = "";
    assert( std::string::npos == find_num( str, 0 ) );
    assert( std::string::npos == find_num( str, 9 ) );

    str = "#operation=1(create circle and add to picture) name X Y radius.";
    assert( strlen("#operation=") == find_num( str, 0 ) );

    str = "abcd 111 xyx 12.33 alpha 345.12e-23";
    ///    0123456789.123456789.123456789.123456789.
    assert(     5 == find_num( str, 0 ) );
    assert(            13 == find_num( str, 5+3 ) );
    assert(                        25 == find_num( str, 20 ) );

    str = "abcd-111 xyx-12.33 alpha-345.12e-23";
    ///    0123456789.123456789.123456789.123456789.
    assert(    4 == find_num( str, 0 ) );
    assert(           12 == find_num( str, 5+3 ) );
    assert(                       24 == find_num( str, 20 ) );

    str = "-1";
    assert( 0 == find_num( str, 0 ) );
    assert( 1 == find_num( str, 1 ) );
    assert( std::string::npos == find_num( str, 2 ) );
    assert( std::string::npos == find_num( str, strlen("-1") ) );

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM