1

I was writing a C++ program to manipulate a text file. A part of the task involves searching the text file for a particular "search string" and store a part of it as an integer array.

I wrote the following code:

ifstream myoutfile;                      
myoutfile.open (outputfile.c_str());    // filename is passed as a user input
string search="SEARCH STRING"           // search string
while (getline(myoutfile, line))
{
     if (line.find(search) != string::npos)
     {
           cout << line[54] << line[55] << line[56] << endl;  
     }
}

the thing is I want to read 54th 55th and 56th characters of the line into an array as a single integer. (Lets say that 54th charcter is '1' 55th is '2' and 56th is '6'. I would like to read it as number 126 into an array. Is it possible to do that inside this loop, or I have to save this into a file and write a separate section to read contents of the file into array. I was wondering whether anybody can help.

3 Answers 3

5

You could use std::stringstream and std::string::substr to get sub-string out and convert to int. Also could use std::atoi

#include <sstream>

int i = 0;
std::istringstream ss(line.substr(54, 3));
ss >> i;

Or

#include <cstdlib>
int b = std::atoi(line.substr(54, 3).c_str());
Sign up to request clarification or add additional context in comments.

9 Comments

stringstream could convert that.
Much easier to use std::stoi (or std::atoi on old compilers).
You never want to use atoi, since you have no way of capturing any errors. std::istringstream is a good solution if you don't have std::stoi; even if std::stoi is present, the std::istringstream solution may be preferable, as it avoids issues with exceptions.
And of course, with the std::istringstream solution, you have to verify its state, and that it has consumed all of the characters you've passed to it.
@KonradRudolph I worked the code out for both std::stoi and std::istringstream. The version using std::istringstream is actually simpler, once error handling has been taken into account. (If you've got a string extracted using a regular expression along the lines of "\\d{3}", then of course std::stoi is the way to go.)
|
3

if it is just the 54 till 56 chars exactly you can do:

int x = (line[54] - '0') * 100 +(line[55] - '0') * 10 +(line[56] - '0') ;

the line[54] - '0' part convert the char sign number to the number it is.

1 Comment

Not until you've verified that they really are digits.
0

The usual solution here is std::istringstream, but it does require more work than other posters seem to suggest:

std::istringstream parser( line.substr( 54, 3 ) );
parser >> i;
if ( !parser || parser.get() != EOF ) {
    //  Error.
} else {
    //  No error, you can use i...
}

If you have C++11, you can use std::stoi, but at first look, it seems even more complex:

size_t end = 0;
try {
    i = std::stoi( line.substr( 54, 3 ), &end );
} catch ( std::runtime_error const& ) {
    //  No numeric characters present...
    //  end remains 0...
} 
if ( end != 3 ) {
    //  Error, either string wasn't long enough, or
    //  contained some non-numeric.
} else {
    //  No error, you can use i...
}

On the other hand, by catching std::invalide_argument and std::out_of_range separately, you can distingish the type of error.

Or, of course, you can just use strtol directly:

char tmp1[4] = {};
line.copy( tmp1, 3, 54 );
char* end;
errno = 0;
long tmp2 = strtol( tmp1, &end, 10 );
if ( errno != 0 || end != tmp1 + 3 || tmp2 > INT_MAX || tmp2 < INT_MIN ) {
    //  Error...
} else {
    i = tmp2;
    //  No error, you can use i...
}

All things considered, I think I prefer the first method (but the last will probably be significantly faster).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.