简体   繁体   中英

atoi() Not Working with std::string::substr()

This is a snippet of my code:

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h> // atoi()


int main() {

    std::string line;

    std::ifstream numbers("numbertest.txt");

    if (numbers.is_open()) {
        while (std::getline(numbers, line)) {
            for (int i = 0; i < line.length() - 4; i++) {
                for (int n = 0; n < 5; n++) {
                    std::cout << atoi((line.substr(i, 5)[n]).c_str());
                }

I want to operate with numbers in groups of 5, from a file. Why is atoi() not working here? It says "expression must have class type" under the second parentheses on the atoi line.

line.substr(i, 5) creates a temporary std::string containing 5 characters in line from position i

std::string foo = "hello world";
int i = 2;
std::cout << foo.substr(2, 5) << '\n';

would print "llo wo".

The [n] operator returns the n th character of the substring, which is of type char , you are then calling .c_str() on that character rather than on the substring.

You can avoid the .c_str() entirely by using std::stoi , eg

std::cout << "line.substr(i, 5) = " << line.substr(i, 5) << '\n';
std::cout << std::stoi(line.substr(i, 5));

aoti and stoi both take a string representation of a number as their input and return the numeric value. For example:

std::string input = "123a";
// std::cout << input * 10 << '\n'; // illegal: input is a string, not a number.
int i = std::stoi(input); // converts to integer representation, i.e. 123
std::cout << i * 10 << '\n'; // outputs 1230

----- EDIT -----

You're actually asking all the wrong questions. What you want to do is take an input pattern and output all of the patterns of 5 characters in it.

Example input: "1020304050" Example output: 10203 02030 20304 03040 30405 04050

You don't need to convert these to numbers to output them, you can just output the characters. The problem with your original code wasn't the conversion it was the incorrect sequence of operators.

std::substring is expensive, it has to create a new, temporary string, copy characters from the original into it, and then return it, and it does it for every call.

The following should achieve what you're trying to do:

while (std::getline(numbers, line)) {
    for (size_t i = 0; i < line.length() - 4; i++) {
        for (size_t n = 0; n < 5; n++) {
            std::cout << line[i + n];
        }
        std::cout << '\n';
    }
}

If you really want to invoke substr, you could also implement this as

while (std::getline(numbers, line)) {
    for (size_t i = 0; i < line.length() - 4; i++) {
        std::cout << line.substr(i, 5) << '\n';
    }
}

Here's a working demonstration: http://ideone.com/mXv2z5

Try atoi( line.substr(i,5).c_str() )

Or if you want for each character

std::cout << ((line.substr(i, 5)[n]) - '0');

Or even better

std::cout << (line[i+n]) - '0');

Note that: atoi is not ascii to integer. It converts a ctype string to number. For a single character, this conversion should be done using arithmetic or lookup table.

Also there is no point converting characters to integer and then print it (back to chacters). You should better print digit character itself.

Moreover in C++, I would prefer to use stringstream instead or atoi. On C++11 there are even more advanced solutions like sto*.

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