C++ Abstract Programming: Detailed Interconversion between Strings and Integers

Posted by trackz on Wed, 10 Jul 2019 00:29:29 +0200

Given that files and strings are sequences of characters, it seems reasonable to think that programming languages may allow us to treat them the same way. C++ provides this functionality through the < sstream > library, which exports several classes that allow streams to be roughly the same as a string value and the < fstream > library allows streams to be associated with files. The istringstream class is the counterpart of ifstream and can read data from strings using stream operators. For output, the ostringstream class is very much like a stream, except that the output is directed to a string rather than a file.

String to integer

Let's start with a piece of code:

#include <iostream>
#include <fstream>
#include <sstream> //string stream 
#include <cstdlib> //EXIT_FAILURE
#include <string>
using namespace std;
int stringToInteger(string str);
void error(string msg); //Output error message and exit execution 
int main(){
    int n = 3,sum;
    cout << "Enter the string to be added" << endl; 
    string line;
    getline(cin,line);//The line we defined at this point is the string class 
    sum = n + stringToInteger(line);
    cout << "The results are as follows:  " << sum;
}
int stringToInteger(string str) {
    istringstream stream(str);
    int value;
    stream >> value >> ws;
    if (stream.fail() || !stream.eof()) {
    error("Illegal integer conversion");
        return 0;
    }
    return value;
}
void error(string msg){
    cerr << msg << endl;
    exit(EXIT_FAILURE);
}

The results are as follows:

code analysis

Here we define a function stringToInteger, which, as its name implies, converts strings into ints for operations, which we will often use later (we can use this function instead). C++ Abstract Programming STL(2) - bracket matching and pocket calculator The atof function in the middle pocket calculator.
Now let's take a closer look at stringToInteger.

int stringToInteger(string str) {
    istringstream stream(str);
    int value;
    stream >> value >> ws;
    if (stream.fail() || !stream.eof()) {
    error("Illegal integer conversion");
        return 0;
    }
    return value;
}

The first line of the function introduces an important feature of variable declaration that we haven't mentioned yet (in object-oriented). If we declare an object, C++ allows parameters to be provided after controlling the variable name of the object's initialization.

istringstream stream(str);

Declare a variable named stream and initialize it as an istringstream object that has been set to read data from the string variable str. The next two lines of code:

int value;
stream >> value >> ws;

Read the integer value from the stream and store it in the variable value value. In this implementation, white space characters are allowed before or after that value. The first > operator automatically skips any blank characters that appear before the value; the ws operator at the end of the line reads any blank characters that follow the value to ensure that if the input format is correct, the stream will be correctly positioned at the end of the line. (that is, we often ignore blank characters, but ws reads them and uses them together) the following if statement

if (stream.fail() || !stream.eof()) {
error("stringToInteger: Illegal integer format");
}

Check to ensure that the input is valid. If the string cannot be parsed as an integer, stream.fail () returns true with an error. However, if the string begins with a number but contains some additional characters, stream.eof () will be false, which also results in an error.
For example, the following picture:

Integer to string

If you need to convert in another direction, you can use the ostringstream class. For example, the following functions convert integers to strings:

string integerToString(int n) {
ostringstream stream;
stream << n;
return stream.str();
}

Let's try to write a code like this (for convenience, I added it directly to the code above):

#include <iostream>
#include <fstream>
#include <sstream> //string stream 
#include <cstdlib> //EXIT_FAILURE
#include <string>
using namespace std;
int stringToInteger(string str);
string integerToString(int n);//The return type is string 
void error(string msg); //Output error message and exit execution 
int main(){
    int n = 3,sum;
    cout << "Enter the string to be added" << endl; 
    string line;
    getline(cin,line);//The line we defined at this point is the string class 
    sum = n + stringToInteger(line);
    cout << "The results are as follows:  " << sum;
    cout << endl;
    cout << "Change the result to a string, and then add abc" << endl;
    string str = "abc";
    str +=  integerToString(sum);
    cout << str << endl;
}
int stringToInteger(string str) {
    istringstream stream(str);
    int value;
    stream >> value >> ws;
    if (stream.fail() || !stream.eof()) {
    error("Illegal integer conversion");
        return 0;
    }
    return value;
}
string integerToString(int n) {
    ostringstream stream;
    stream << n;
    return stream.str();
}
void error(string msg){
    cerr << msg << endl;
    exit(EXIT_FAILURE);
}

The results of implementation are as follows:

The operator in the second line of the integerToString function converts its value to a decimal representation, just like a file. However, here, the output is directed to the string values stored internally as part of the ostringstream object. The str function in the return statement copies the value of the internal string so that it can be returned to the caller. Interestingly, since formatting errors no longer need to be considered, it is easier to convert in this direction.

Better strategy for console input

The srtin stream also provides a solution to the problem of checking whether user input is correct. As we all know, the >> operator does not check for errors in user input. Imagine, for example, that we have the following code:

int limit;
cout << "Enter exponent limit: ";
cin >> limit;

If the user enters a valid integer, everything is fine. However, if the user tries to enter a value of 16, what happens if the user accidentally slips a line on the keyboard and enters the letter T instead of the number 6. In an ideal world, programs would look at input 1t and doubt its validity. Unfortunately, if the extraction operator is used in C++, the error is not detected. When the value is required to be read into the integer variable limit, the >> operator reads the character until it finds a character that is illegal in the integer segment. So the input stops at t, but the value 1 is still a valid integer, so the program will maintain the correct limit equal to 1 (that is, limit = 1 at this time). Take the first program above for example, if we annotate all the wrong information, when we input 100a, the output sum is 103a, a does not carry on the calculation.

The most effective way to ensure that user input is valid is to read an entire line as a string and then convert the string to an integer. Let's write a getInteger function to implement it, as shown in the following code. This function reads an integer from the user like the > operator, but also ensures that the integer is valid.

/*Request an integer value from the user. This function starts by printing a prompt string on the console, and then waits for the user to enter a line of input data. 
*If the row contains a single integer, the function returns the corresponding integer value. If the input is not a legitimate integer, or unrelated characters appear on the input line
*(Except for spaces, the function will re-enter the value to the user
*/
int getInteger(string prompt) {
int value;
string line;
while (true) {
cout << prompt;
getline(cin, line);
istringstream stream(line);//Line-by-line input
stream >> value >> ws;
if (!stream.fail() && stream.eof()) break;
cout << "Illegal integer format. Try again." << endl;
}
return value;
}

The logic of getInteger is similar to that used in the stringToInteger function in the previous section. The only major difference is that getInteger re-enters a value to the user instead of terminating the program with an error message. Let's run a simplified and improved version of the first example:

#include <iostream>
#include <fstream>
#include <sstream> //string stream 
#include <string>
using namespace std;
int getInteger(string prompt);
int main(){
    int n, sum = 0; string line;
    cout << "Enter the string to be added" << endl;  
    n = getInteger(line);
    sum += n; 
    cout << "The results are as follows:  " << sum;
}
int getInteger(string prompt) {
    int value;
    string line;
    while (true) {
        cout << prompt;
        getline(cin, line);
        istringstream stream(line);
        stream >> value >> ws;
    if (!stream.fail() && stream.eof()) break;//When the input fails, jump out of the loop 
        cout << "Illegal input, try again" << endl;
    }
    return value;
}

The results are as follows:

Topics: Programming calculator