how to tell if a number is octal

Pages: 12
How do I tell if a number is in octal without the regex library? I need to do it for this:

// Exercise Specifications:
/**
* Write a program called multi_input.cpp that prompts the user to enter
* several integers in any combination of octal, decimal, or hexadecimal,
* using the 0 and 0x base suffixes; interprets the numbers correctly; and
* converts them to decimal form. Then your program should output the
* values in properly spaced columns like this:
* 0x43 hexadecimal converts to 67 decimal
* 0123 octal converts to 83 decimal
* 65 decimal converts to 65 decimal
*/


This is the code I have so far:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// multi_input.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 4 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 4
// Exercise Specifications:
/**
* Write a program called multi_input.cpp that prompts the user to enter
* several integers in any combination of octal, decimal, or hexadecimal,
* using the 0 and 0x base suffixes; interprets the numbers correctly; and
* converts them to decimal form. Then your program should output the
* values in properly spaced columns like this:
*		0x43 hexadecimal converts to 67 decimal
*		0123 octal converts to 83 decimal
*		65 decimal converts to 65 decimal
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <sstream>
#include <locale>
#include <string>
#include <regex>
#include <stdexcept>
#include <iomanip>

int main()
{
	using namespace std;
	cout << "Please enter some numbers in any combination of decimal, hexadecimal, "
		<< "or octal. Use the 0x and 0 suffixes for hexadecimal and octal as needed.\n";
	int num1;
	int num2;
	int num3;
	cin >> num1 >> num2 >> num3;
	istringstream ist1{ num1 };
	istringstream ist2{ num2 };
	istringstream ist3{ num3 };
	string num1_s = to_string(num1);
	string num2_s = to_string(num2);
	string num3_s = to_string(num3);
	for (char ch : num1_s)
	{
		// is number in decimal?
		if (isdigit(ch) && !isxdigit(ch))
		{
			cout << num1 << " in decimal " << setw(11) << " converts to "
				<< num1 << " in decimal\n";
		}
		// is number in hexadecimal?
		else if (!isdigit(ch) && isxdigit(ch))
		{
			cout << hex << " in hexadecimal " << setw(11) << " converts to "
				<< dec << num1 << " in decimal\n";
		}
		// TODO: Is number in octal?
		else if ()
		{

		}
	}
}
One way would be to read the number in a string and check that first char is '0' and second char != 'x'.
The current way using an istringstream would work with that, right?

And is it correct to think that isdigit() checks for a decimal number, meaning that if it returns true, the digit is not an octal or hexadecimal digit? Because as you can see, I'm trying to leverage that in my code. It won't be funny if it doesn't work that way.

And speaking of which, how would I tell if the number starting with a 0 but that doesn't have 'x' as the second digit is a decimal number and not an octal (like, maybe the user tries to fool the program by putting a 0 in front of a decimal number)?
Last edited on
And is it correct to think that isdigit() checks for a decimal number, meaning that if it returns true, the digit is not an octal or hexadecimal digit?

No, isdigit returns true if the char is >= '0' and <= '9'

ike, maybe the user tries to fool the program by putting a 0 in front of a decimal number

I don't see a solution to avoid it. 012 can be decimal or octal, but he / she would cheat himself/herself, so there is need to worry about it.
So for checking if it's a decimal number, I'd have to check if the number starts with "0x" or '0' or not? That's the only way?

Edit: I have this for now, but the result is all wrong:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// multi_input.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 4 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 4
// Exercise Specifications:
/**
* Write a program called multi_input.cpp that prompts the user to enter
* several integers in any combination of octal, decimal, or hexadecimal,
* using the 0 and 0x base suffixes; interprets the numbers correctly; and
* converts them to decimal form. Then your program should output the
* values in properly spaced columns like this:
*		0x43 hexadecimal converts to 67 decimal
*		0123 octal converts to 83 decimal
*		65 decimal converts to 65 decimal
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <sstream>
#include <locale>
#include <string>
#include <iomanip>

int main()
{
	using namespace std;
	cout << "Please enter some numbers in any combination of decimal, hexadecimal, "
		<< "or octal. Use the 0x and 0 suffixes for hexadecimal and octal as needed.\n";
	int num1;
	int num2;
	int num3;
	cin >> num1 >> num2 >> num3;
	string num1_s = to_string(num1);
	istringstream ist1{ num1_s };
	bool is_oct = 
		(num1_s.size() > 1 && num1_s[0] == '0' && num1_s[1] != 'x') ? true : false;
	for (char ch : num1_s)
	{
		// is number in decimal?
		if (isdigit(ch) && !isxdigit(ch) && !is_oct)
		{
			cout << num1 << " in decimal " << setw(11) << " converts to "
				<< num1 << " in decimal\n";
		}
		// is number in hexadecimal?
		else if (isdigit(ch) && isxdigit(ch) && !is_oct)
		{
			cout << hex << num1 << " in hexadecimal " << setw(11) << " converts to "
				<< dec << num1 << " in decimal\n";
		}
		// is number in octal?
		else if (isdigit(ch) && is_oct)
		{
			cout << oct << num1 << " in octal " << setw(11) << " converts to "
				<< dec << num1 << " in decimal\n";
		}
	}

	string num2_s = to_string(num2);
	istringstream ist2{ num2_s };
	is_oct =
		(num2_s.size() > 1 && num2_s[0] == '0' && num2_s[1] != 'x') ? true : false;
	for (char ch : num2_s)
	{
		// is number in decimal?
		if (isdigit(ch) && !isxdigit(ch) && !is_oct)
		{
			cout << num2 << " in decimal " << setw(11) << " converts to "
				<< num2 << " in decimal\n";
		}
		// is number in hexadecimal?
		else if (isdigit(ch) && isxdigit(ch) && !is_oct)
		{
			cout << hex << num2 << " in hexadecimal " << setw(11) << " converts to "
				<< dec << num2 << " in decimal\n";
		}
		// is number in octal?
		else if (isdigit(ch) && is_oct)
		{
			cout << oct << num2 << " in octal " << setw(11) << " converts to "
				<< dec << num2 << " in decimal\n";
		}
	}
	
	string num3_s = to_string(num3);
	istringstream ist3{ num3_s };
	is_oct =
		(num3_s.size() > 1 && num3_s[0] == '0' && num3_s[1] != 'x') ? true : false;
	for (char ch : num2_s)
	{
		// is number in decimal?
		if (isdigit(ch) && !isxdigit(ch) && !is_oct)
		{
			cout << num3 << " in decimal " << setw(11) << " converts to "
				<< num3 << " in decimal\n";
		}
		// is number in hexadecimal?
		else if (isdigit(ch) && isxdigit(ch) && !is_oct)
		{
			cout << hex << num3 << " in hexadecimal " << setw(11) << " converts to "
				<< dec << num3 << " in decimal\n";
		}
		// is number in octal?
		else if (isdigit(ch) && is_oct)
		{
			cout << oct << num3 << " in octal " << setw(11) << " converts to "
				<< dec << num3 << " in decimal\n";
		}
	}
	keep_window_open();
}


output:

Please enter some numbers in any combination of decimal, hexadecimal, or octal. Use the 0x and 0 suffixes for hexadecimal and octal as needed.
0xac0 4561 015
0 in hexadecimal converts to 0 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
cccccccc in hexadecimal converts to -858993460 in decimal
Please enter a character to exit
Press any key to continue . . .
Last edited on
No, hex starts with "0x", oct starts with '0' and dec starts with any digit between '1' && '9'. I think you can ignore leading '-' or '+'
I'm not worried about the leading '+' or '-', I'm just worried about why the hexadecimal and decimal values came out wrong. And about why there's no octal number in the output.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string>

std::string trim( std::string str )
{
    while( !str.empty() && std::isspace( str.back() ) ) str.pop_back() ;

    std::size_t pos = 0 ;
    while( pos < str.size() && std::isspace( str.front() ) ) ++pos ;

    return str.substr(pos) ;
}

int base_of( std::string str ) // trimmed string
{
    if( str.find_first_of("+-") == 0 ) str = str.substr(1) ;

    if( str.empty() || !std::isdigit( str.front() ) ) throw std::invalid_argument("") ;

    if( str.front() == '0' )
    {
        if( str.size() > 1 && std::tolower( str[1] ) == 'x' ) return 16 ;
        else return 8 ;
    }

    return 10 ;
}

int main()
{
    std::cout << "Please enter some numbers in any combination of "
              << "decimal, hexadecimal or octal.\nUse the 0x and 0 suffixes "
              << "for hexadecimal and octal as needed.\n";

    std::string str ;

    while( std::cout << "? " && std::getline( std::cin, str ) )
    {
        str = trim(str) ;

        try
        {
            const int base = base_of(str) ;
            std::size_t pos ;
            long long number = std::stoll( str, std::addressof(pos), base ) ;

            std::cout << str.substr(0,pos) << ' ' ;
            switch(base)
            {
                case 8 : std::cout << "octal " ; break ;
                case 10 : std::cout << "decimal " ; break ;
                case 16 : std::cout << "hexadecimal " ; break ;
            }
            std::cout << "converts to " << number << " decimal\n" ;
            if( pos != str.size() ) std::cout << "  note: '" << str << "' was not fully parsed\n" ;
        }

        catch( const std::invalid_argument& )
        {
            std::cout << "you did not enter a valid number\n" ;
        }

        catch( const std::out_of_range& )
        {
            std::cout << "the number you entered is outside the range "
                      << "of numbers that this program can handle\n" ;
        }
    }
}
Thanks. It worked, though I didn't take the trim() function since I'm not sure why or how it's needed here.

Isn't there a way I could read in whitespace separated numbers into numerical variables and then turn those into strings to pass into base_of? And the book also to show the output in properly spaced columns.

In properly spaced columns and organized like this (showing one base):
0x45 in hexadecimal converted to decimal is 69 in decimal


I have the code like this right now:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// multi_input.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 4 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 4
// Exercise Specifications:
/**
* Write a program called multi_input.cpp that prompts the user to enter
* several integers in any combination of octal, decimal, or hexadecimal,
* using the 0 and 0x base suffixes; interprets the numbers correctly; and
* converts them to decimal form. Then your program should output the
* values in properly spaced columns like this:
*		0x43 hexadecimal converts to 67 decimal
*		0123 octal       converts to 83 decimal
*		65 decimal       converts to 65 decimal
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <locale>
#include <string>
#include <iomanip>
#include <stdexcept>

int base_of(std::string &num_s);
void print_base_num(const long long num, const int base, 
	const std::string num_s, size_t i);

int main()
{
	using namespace std;
	cout << "Please enter some numbers in any combination of decimal, hexadecimal, "
		<< "or octal.\nUse the '0x' and '0' suffixes "
		<< "for hexadecimal and octal as needed.\n";
	
	string number_s;
	while (getline(cin, number_s))
	{
		try
		{
			const int base = base_of(number_s);
			size_t i;
			long long number = stoll(number_s, addressof(i), base);
			print_base_num(number, base, number_s, i);
		}
		catch (const invalid_argument &inv_arg)
		{
			cerr << "invalid argument error: " << inv_arg.what() << '\n';
		}
		catch (const out_of_range &oor)
		{
			cerr << "out of range error: " << oor.what() << '\n';
		}
	}

	keep_window_open();
}

int base_of(std::string &num_s)
{
	using namespace std;
	if (num_s.find_first_of("+-") == 0)
	{
		num_s = num_s.substr(1);
	}
	if (num_s.empty() || !isdigit(num_s.front()))
	{
		throw invalid_argument("");
	}
	if (num_s.front() == '0')
	{
		if (num_s.size() > 1 && tolower(num_s[1]) == 'x')
		{
			return 16;
		}
		else
		{
			return 8;
		}
	}
	return 10;
}

void print_base_num(const long long num, const int base,
	const std::string num_s, size_t i)
{
	using namespace std;
	cout << num_s.substr(0, i) << ' ';
	switch (base)
	{
	case 8:
		cout << "in octal ";
		break;
	case 10:
		cout << "in decimal ";
		break;
	case 16:
		cout << "in hexadecimal ";
		break;
	}
	cout << "converts to " << num << " in decimal\n";
	if (i != num_s.size())
	{
		cout << "note: '" << num_s << "' was not fully parsed\n";
	}
}
Last edited on
> Isn't there a way I could read in whitespace separated numbers into numerical variables
> and then turn those into strings to pass into base_of?

Read it as a complete line and then split the line into white space delimited tokens.
In this case, trim is not required as the tokens would already be trimmed.


> And the book also to show the output in properly spaced columns.

Use the manipulators std::setw(), std::left and std::right

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>

std::vector<std::string> split( std::string line ) // split on white space
{
    std::vector<std::string> result ;

    std::istringstream stm(line) ;
    std::string str ;
    while( stm >> str ) result.push_back(str) ;

    return result ;
}

int base_of( std::string str ) // trimmed string
{
    if( str.find_first_of("+-") == 0 ) str = str.substr(1) ;

    if( str.empty() || !std::isdigit( str.front() ) ) throw std::invalid_argument("") ;

    if( str.front() == '0' )
    {
        if( str.size() > 1 && std::tolower( str[1] ) == 'x' ) return 16 ;
        else return 8 ;
    }

    return 10 ;
}

int main()
{
    std::cout << "Please enter some numbers in a single line in any combination of "
              << "decimal, hexadecimal or octal.\nUse the 0x and 0 suffixes "
              << "for hexadecimal and octal as needed.\n";

    std::string line ;

    if( std::cout << "? " && std::getline( std::cin, line ) )
    {
        for( std::string str : split(line) ) try
        {
            std::cout  << std::left << std::setw(30) ;
            const int base = base_of(str) ;
            std::size_t pos ;
            long long number = std::stoll( str, std::addressof(pos), base ) ;

            switch(base)
            {
                case 8 : std::cout << str.substr(0,pos) + " octal " ; break ;
                case 10 : std::cout << str.substr(0,pos) + " decimal " ; break ;
                case 16 : std::cout << str.substr(0,pos) +  " hexadecimal " ; break ;
            }
            std::cout << "converts to " << std::right << std::setw(15) << number << " decimal" ;
            if( pos != str.size() ) std::cout << "  note: '" << str << "' was not fully parsed" ;
            std::cout << '\n' ;
        }

        catch( const std::invalid_argument& )
        {
            std::cout << std::quoted(str) << "you did not enter a valid number\n" ;
        }

        catch( const std::out_of_range& )
        {
            std::cout << std::quoted(str)
                      << "the number you entered is outside the range "
                      << "of numbers that this program can handle\n" ;
        }
    }
}
how to tell if a number is octal

It is just about how to tell if a number if octal, you don't need to provide your code and just ask for the approach instead.

I will suggest an other approach other than JLBorges' :

You could use std::getline if you want to handle an unlimited number of numbers. A std::istringstream would deal with all numbers flawlessly.

Check the first digit(s) to detect the number whether it is decimal, octal, hexadecimal. When you know the base of a number, you can just iss >> std::oct >> number; if the number is an octal, or iss >> std::hex >> number; if the number is a hexadecimal, or iss >> std::dec >> number; if the number is a decimal. After that you output the final result.
It only takes one number before outputting the result and quitting now. I'll try changing just the if and for in main back into while.

Edit: Here's the output after having made that change:

Please enter some numbers in any combination of decimal, hexadecimal, or octal.
Use the '0x' and '0' suffixes for hexadecimal and octal as needed.
0x45
0x45 in hexadecimal converts to 69 in decimal
045 56 0x74
045 in octal converts to 37 in decimal
note: '045 56 0x74' was not fully parsed
^Z
Please enter a character to exit
k
Press any key to continue . . .


[Of course, the extra spaces aren't preserved since I don't know how to do that here.]
Last edited on
Pattako said:
You could use std::getline if you want to handle an unlimited number of numbers. A std::istringstream would deal with all numbers flawlessly.


This would be the solution. Stringstreams were covered in Chapter 11.4
Yeah, stringstreams were covered. I only just read that post, though. I hadn't seen it earlier.

I need to check if it's octal, hexadecimal or decimal and then read it like that. So I could read a number with cin, look at the first one or two numbers, and then try to read it correctly.

Edit: I need to read the numbers in any combination of decimal, hexadecimal and octal, and then print them out in properly spaced columns where the numbers as they were entered are lined up with the originally entered numbers indented towards the left, then the name of the base with two spaces between it and the number, and then "converts to" all lined up in column and "<some number> decimal" lined up in one column. I can't get the output looking right.
Last edited on
Easiest way would be:
1
2
3
4
5
6
7
8
  string line;
  getline(cin,line);
  istringstream iss(line);
  string number;
  while (iss >> number)
  {
    // check if number is hex, oct....
  }
How about this?

I need to read the numbers in any combination of decimal, hexadecimal and octal, and then print them out in properly spaced columns where the numbers as they were entered are lined up with the originally entered numbers indented towards the left, then the name of the base with two spaces between it and the number, and then "converts to" all lined up in column and "<some number> decimal" lined up in one column. I can't get the output looking right.
As JLBorges said:
Use the manipulators std::setw(), std::left and std::right

You need to experiment a bit to get it aligned.
Something weird happened. Look at this output, please:

Please enter some numbers in any combination of decimal, hexadecimal, or octal.
Use the '0x' and '0' suffixes for hexadecimal and octal as needed.
0x43 0123 65 852 0852 0xca
0x43 hexadecimal converts to 67 decimal
0123 octal converts to 83 decimal
0123 decimal converts to 83 decimal
0123 hexadecimal converts to 83 decimal
65 decimal converts to 65 decimal
65 hexadecimal converts to 65 decimal
852 decimal converts to 852 decimal
852 hexadecimal converts to 852 decimal
0852 octal converts to 0 decimal
0852 decimal converts to 0 decimal
0852 hexadecimal converts to 0 decimal
0xca hexadecimal converts to 202 decimal
Please enter a character to exit
k
Press any key to continue . . .


Aside from the weird conversions, there's also the problem of "converts to" and "<some number decimal" being output together.

And here's the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// multi_input.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 4 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 4
// Exercise Specifications:
/**
* Write a program called multi_input.cpp that prompts the user to enter
* several integers in any combination of octal, decimal, or hexadecimal,
* using the 0 and 0x base suffixes; interprets the numbers correctly; and
* converts them to decimal form. Then your program should output the
* values in properly spaced columns like this:
*		0x43   hexadecimal  converts to   67 decimal
*		0123   octal             converts to   83 decimal
*		65       decimal         converts to   65 decimal
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <locale>
#include <string>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <vector>

int base_of(std::string &num_s);
std::vector<std::string> split(const std::string &line);

int main()
{
	using namespace std;
	cout << "Please enter some numbers in any combination of decimal, hexadecimal, "
		<< "or octal.\nUse the '0x' and '0' suffixes "
		<< "for hexadecimal and octal as needed.\n";
	
	string input;
	getline(cin, input);
	for (string num_s : split(input))
	{
		try
		{
			const int base = base_of(num_s);
			size_t position;
			int number = stoi(num_s, addressof(position), base);

			switch (base)
			{
			case 8:
				cout << right << setw(5) << num_s << " octal "
					<< setw(11) << right << " converts to " << number << " decimal\n";
			case 10:
				cout << right << setw(5) << num_s << " decimal "
					<< setw(11) << right << " converts to " << number << " decimal\n";
			case 16:
				cout << right << setw(5) << num_s << " hexadecimal "
					<< setw(11) << right << " converts to " << number << " decimal\n";
			}
		}
		catch (const invalid_argument &inv_arg)
		{
			cerr << "invalid argument error: " << inv_arg.what() << '\n';
		}
		catch (const out_of_range &oor)
		{
			cerr << "out of range error: " << oor.what() << '\n';
		}
	}

	keep_window_open();
}

int base_of(std::string &num_s)
{
	using namespace std;
	if (num_s.find_first_of("+-") == 0)
	{
		num_s = num_s.substr(1);
	}
	if (num_s.empty() || !isdigit(num_s.front()))
	{
		throw invalid_argument("");
	}
	if (num_s.front() == '0')
	{
		if (num_s.size() > 1 && tolower(num_s[1]) == 'x')
		{
			return 16;
		}
		else
		{
			return 8;
		}
	}
	return 10;
}

std::vector<std::string> split(const std::string &line)
{
	using namespace std;
	vector<string> result;

	istringstream ist{ line };
	string str;
	while (ist >> str)
	{
		result.push_back(str);
	}
	return result;
}
Last edited on
You forgot the break statements in your switch(base)
*face/palm* Yeah, that's right. The break statements. I also have a problem of "no output" in Exercise 5, but I'll get to that later. Thanks for pointing that out, by the way.

Edit:
I still can't get it to align right. This is the code right now:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// multi_input.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 4 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 4
// Exercise Specifications:
/**
* Write a program called multi_input.cpp that prompts the user to enter
* several integers in any combination of octal, decimal, or hexadecimal,
* using the 0 and 0x base suffixes; interprets the numbers correctly; and
* converts them to decimal form. Then your program should output the
* values in properly spaced columns like this:
*		0x43 hexadecimal converts to 67 decimal
*		0123 octal       converts to 83 decimal
*		65 decimal       converts to 65 decimal
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <locale>
#include <string>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <vector>

int base_of(std::string &num_s);
std::vector<std::string> split(const std::string &line);

int main()
{
	using namespace std;
	cout << "Please enter some numbers in any combination of decimal, hexadecimal, "
		<< "or octal.\nUse the '0x' and '0' suffixes "
		<< "for hexadecimal and octal as needed.\n";
	
	string input;
	getline(cin, input);
	for (string num_s : split(input))
	{
		try
		{
			const int base = base_of(num_s);
			size_t position;
			int number = stoi(num_s, addressof(position), base);

			switch (base)
			{
			case 8:
				cout << right << setw(5) << num_s << " octal "
					<< setw(11) << right << " converts to " 
					<< left << setw(11) << number << " decimal\n";
				break;
			case 10:
				cout << right << setw(5) << num_s << " decimal "
					<< setw(11) << right << " converts to " 
					<< left << setw(11) << number << " decimal\n";
				break;
			case 16:
				cout << right << setw(5) << num_s << " hexadecimal "
					<< setw(11) << right << " converts to " 
					<< left << setw(11) << number << " decimal\n";
				break;
			}
		}
		catch (const invalid_argument &inv_arg)
		{
			cerr << "invalid argument error: " << inv_arg.what() << '\n';
		}
		catch (const out_of_range &oor)
		{
			cerr << "out of range error: " << oor.what() << '\n';
		}
	}

	keep_window_open();
}

int base_of(std::string &num_s)
{
	using namespace std;
	if (num_s.find_first_of("+-") == 0)
	{
		num_s = num_s.substr(1);
	}
	if (num_s.empty() || !isdigit(num_s.front()))
	{
		throw invalid_argument("");
	}
	if (num_s.front() == '0')
	{
		if (num_s.size() > 1 && tolower(num_s[1]) == 'x')
		{
			return 16;
		}
		else
		{
			return 8;
		}
	}
	return 10;
}

std::vector<std::string> split(const std::string &line)
{
	using namespace std;
	vector<string> result;

	istringstream ist{ line };
	string str;
	while (ist >> str)
	{
		result.push_back(str);
	}
	return result;
}
Last edited on
Pages: 12