-1

Given an input from the user (ex. 123456) you must convert the input int to an int array (ex. {1, 2, 3, 4, 5, 6}.

I was wondering, how can this be done? I have started out with a function that counts the digits the were inputted, and initializes an array with the amount of digits.

Is there another way to go about doing this that is simpler?

This is what I have so far:

#include <iostream>
using namespace std;

int main()
{
    int n, counter = 0;
    cin >> n;
    
    while (n != 1)
    {
        n = n / 10;
        counter++;
    }
    counter += 1;
    
    int arr[counter];
    
    return 0;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Vik
  • 1
  • 3
  • Your description sounds reasonable, if I could see your code I would be in a better position to know if there are simplifications you could make. – john Sep 08 '22 at 20:43
  • 2
    Can't you just read it as a string and convert each individual character into an int? – Etienne de Martel Sep 08 '22 at 20:43
  • 2
    @Vik Variable length arrays are not a standard C++ feature. You should use std::vector, – Vlad from Moscow Sep 08 '22 at 20:47
  • 3
    Use `std::vector` instead of an array and during the loop simply `push_back` and then use `std::reverse` get the correct order. This way you remove the extra step of having to count the number on digits in favor of a single loop just using remainder/divisions until you end up with 0. – fabian Sep 08 '22 at 20:47
  • `std::string` can be considered as array of `char` which can be considered as `int8_t` on most platforms. So you already have your data, only issue is to convert symbol '0' to number 0, '1' to 1 etc. – Slava Sep 08 '22 at 20:48
  • I thought you had working code. Conversion of the integer to a string and then spliting the string up into individual digits is the simplest way I think. – john Sep 08 '22 at 20:53
  • Warning: `int arr[counter];` this is a non-Standard Variable Length Array. Don't use these unless you're absolutely certain that all the folk who need to compile your code all have the same compiler. Also watch out because if you allow the user to specify the size of an array, you can pretty much count on someone specifying one too large to fit in the limited amount of Automatic storage your program has available. – user4581301 Sep 08 '22 at 20:54
  • Please don't alter your question after you've gotten answers that points out mistakes and suggests corrections for those. Those answers will not be useful to anyone else in the future. I rolled back your latest edit. – Ted Lyngmo Sep 08 '22 at 21:57

4 Answers4

1

Let me solve this in what is a bit overkill for the problem, but will actually teach you various C++ constructs instead of the "C plus a bit syntactic sugar" you are doing right now.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

int main( int argc, char * argv[] )
{
    if ( argc != 2 )
    {
        std::cout << "Enter *one* number.\n";
        return 1;
    }

    // Don't work with C arrays any more than you absolutely must.
    // Initializing a variable with those curly braces is the
    // modern C++ way of initialization. The older way using ()
    // had some issues (like the "most vexing parse" problem).
    std::string input { argv[1] };

    // Initialize a vector of int with the elements of input.
    // If you need the elements in reverse order, just use
    // std::rbegin and std::rend.
    std::vector<int> output { std::begin( input ), std::end( input ) };

    // The elements of output right now have a value depending on
    // the character encoding, i.e. they refer to the *character
    // value* of the digit, not the *integer* value. You could
    // call `std::stoi` on each, or you can substract the encoded
    // value for the letter '0', because the standard guarantees
    // that '0' through '9' are encoded with consecutive values.
    // This is NOT true for letters!
    // The part starting at [] is called a "lambda", and it is a
    // very nifty feature in conjunction with <algorithm> that you
    // should study at some point (right after you learned what a
    // 'functor' is, which is probably a bit down the road yet).
    // Think of it as a way to define a local function without
    // giving it a name.
    std::for_each( output.begin(), output.end(), [](int & i){ i -= '0'; } );

    // Prefer range-for over indexed for.
    for ( auto & i : output )
    {
        std::cout << i << "\n";
    }

    return 0;
}

That solution is a bit heavy on the advanced C++ features, though.

This second one is simpler (no <algorithm> or lambdas), but shows proper input error handling and still avoids manual arithmetics on the number:

#include <iostream>
#include <string>
#include <vector>

int main()
{
    int input;

    while ( ! ( std::cin >> input ) )
    {
        // Input can fail, e.g. when the user enters
        // letters.
        std::cout << "Enter a number.\n";
        // Clear the error flag on the input stream.
        std::cin.clear();
        // Clear input buffer of what the user entered.
        std::cin.ignore();
    }

    std::string number { std::to_string( input ) };

    // You *can* reserve space in the vector beforehand,
    // but unless you know you will be pushing a LOT of
    // values, I would not bother. (Also, there are a
    // couple of mistakes you could make if you try.)
    std::vector<int> output;

    for ( auto & c : number )
    {
        output.push_back( c - '0' );
    }

    for ( auto & i : output )
    {
        std::cout << i << "\n";
    }
}
DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • 1
    Alternatively, using `std::transform()` instead of `std::for_each()`: `std::transform( output.begin(), output.end(), output.begin(), [](int i){ return i - '0'; } );` – Remy Lebeau Sep 08 '22 at 21:25
  • @RemyLebeau Why should I showcase a more complicated function that writes to a different range, only to specify target range = source range? `for_each` is the correct algorithm here, and simpler to understand. – DevSolar Sep 08 '22 at 21:27
  • @CaptainGiraffe: But my intent is to change the values *in place*, so `for_each` is the correct algorithm and `transform`, to put it bluntly, isn't. Just because it is called "transform" doesn't make it the better fit here. For exactly the reason you state: Intent. I don't take `std::list` when I want `std::forward_list` either, just because the former is *called* "list". – DevSolar Sep 08 '22 at 21:39
  • Transformation in place is also possible with `std::transform`/`std::ranges::transform`. `std::ranges::transform(output, output.begin(), [](int i) { return i - '0'; });` would get the job done. It's a matter of taste I guess. – Ted Lyngmo Sep 08 '22 at 21:53
  • @Vik Second, simpler solution added that doesn't use `` and lambdas. – DevSolar Sep 08 '22 at 22:05
  • 1
    @DevSolar I think I need to concede =) – Captain Giraffe Sep 09 '22 at 00:30
0

First, the loop you have to calculate how many digits there are in the number only works if the left-most digit is a 1:

while (n != 1)  // what if it's 2-9 instead? 
{
    n = n / 10;
    counter++;
}
counter += 1;

The proper calculation would be

do {
    n /= 10;   // same as n = n / 10
    ++counter;
} while(n);

you must convert the input int to an int array

This requirement is pretty hard to fullfil using standard C++ since the sizes of arrays must be known at compile-time. Some compilers support Variable Length Arrays but using them makes your program non-portable. The tool for creating array-like containers with sizes only known at run-time is the class template std::vector. In this case you want to use a std::vector<int>. I've put the digit-counting part in a separate function here:

#include <iostream>
#include <vector>

int count_digits(int number) {
    int counter = 0;
    do {
        number /= 10;
        ++counter;
    } while (number);
    return counter;
}

int main() {
    int n;
    if (!(std::cin >> n)) return EXIT_FAILURE;

    // instead of  int arr[ count_digits(n) ];  use a vector<int>:
    std::vector<int> arr( count_digits(n) ); 

    // fill the vector starting from the end:
    for(size_t idx = arr.size(); idx--;) {
        arr[idx] = n % 10; // extract the least significant digit
        n /= 10;
    }

    // print the result using an old-school loop:
    for(size_t idx = 0; idx < arr.size(); ++idx) {
        std::cout << arr[idx] << '\n';
    }

    // print the result using a range based for-loop:
    for(int value : arr) {
        std::cout << value << '\n';
    }
}

Alternatively, use a reverse iterator to fill the vector:

    for(auto it = arr.rbegin(); it != arr.rend(); ++it) {
        *it = n % 10;
        n /= 10;
    }

You could also use the standard function std::to_string to convert the int to a std::string (or read the value from the user as a std::string directly).

Once you have a std::string you can easily populate the vector<int> by transformation.

Example:

#include <algorithm>
#include <iostream>
#include <ranges>
#include <string>
#include <vector>

int main() {
    int n;
    if (!(std::cin >> n)) return EXIT_FAILURE;

    auto as_str = std::to_string(n);

    std::vector<int> arr(as_str.size()); // create it big enough to hold all digits

    // transform each character in the string and put the result in arr:
    std::ranges::transform(as_str, arr.begin(), [](char ch) { return ch - '0'; });

    // print the result:
    for (int x : arr) std::cout << x << '\n';
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
-1

The easiest way for you would be to use the same loop that counts the number of digits to save it(using n%10 would give you the last digit in your number). Also you shouldn't use int arr[counter];, since variable length arrays are not supported in c++ even though the code is actually compiled. You should use an array allocated in the heap using int* arr = new int[counter];

Vektor 007
  • 35
  • 7
  • 2
    No, they should use `std::vector`, not `new`. – Etienne de Martel Sep 08 '22 at 21:04
  • Since it looks like he is just starting to learn how to write c++ code he may not know how to use the std::vector and it would be simpler for him to use the basics. Regarding the array, even if he uses a variable length array his IDE will probably fix it while compiling so his program would work. I only said that since it would be good for him to learn how to use pointers and how to work with the heap. – Vektor 007 Sep 08 '22 at 21:19
  • 5
    No, no, no. This isn't 1993 anymore, `vector` _is_ the basics. Dynamic memory allocation is a trap for beginners. – Etienne de Martel Sep 08 '22 at 21:21
  • I guess you are right but what I meant by the basics is the % operator. As I said his IDE will fix the variable length array so it will be fine if he leaves it like that. Btw I don't know about you but in university they don't let us use anything like vector or string. We have to write our own which is really fun since the code we write is actually on paper. – Vektor 007 Sep 08 '22 at 21:28
  • Yes, I know universities are generally ten to twenty years behind the times and don't encourage best coding practices. – Etienne de Martel Sep 08 '22 at 21:31
  • 2
    @Vektor007: If you find yourself in a class where you are forbidden to use language features because the instructor insists on teaching you to reimplement said language features "the hard way", that instructor is wasting your time. Find a better course. What you *should* be learning is to use the language properly. Forcing students to "come the long way around" by tying one hand to their back is just as outdated thinking as `new`. THIS is what's hurting C++ more than anything else, antiquated teaching. "I learned it that way so you will, too." – DevSolar Sep 08 '22 at 21:36
-2

The is the simplest way I guess!

int integer_length(int number){
    return trunc(log10(number)) + 1; 
}
XO56
  • 332
  • 1
  • 12
  • 3
    Variable length arrays are not standard C++. – DevSolar Sep 08 '22 at 21:22
  • 2
    "*you will get the array in `backward` order! you can fix that with a `for loop`*" - Or, you could simply put the digits into the array in reverse order to begin with, since you already know how many digits there are up front. `for(int i = 0; i < number_length; i++){ array[number_length-i-1] = number % 10; number /= 10; }` – Remy Lebeau Sep 08 '22 at 21:22
  • 2
    Wow. Worst answer available, last posted, but it gets accepted... (Why go through the effort with `%` and all if you already converted `number` to a series of values with `to_string(number)`? Variable length array is not C++. Indexed `for` is 1998.) – DevSolar Sep 08 '22 at 21:38
  • It gets worse with each edit, sorry man. Now you `to_string` the same number twice, loop *twice* over the length, have *two* unnecessary helper variables in there, **still** pick it apart with `%`, and **still** have a VLA in there. You're also not taking *input* but have the value hardcoded. – DevSolar Sep 08 '22 at 21:49
  • 1
    I'm not sure about the outcome! but I have learned a new thing today! thanks guys......@RemyLebeau @DevSolar – XO56 Sep 08 '22 at 22:03
  • 1
    If you take *anything* away from this, let it be this: Don't use C arrays. Not the variable-length ones (which aren't even in the language standard and merely a common compiler extension), and not the static ones. You really, *really* want to be using `` unless you have a *good* reason to use anything else. (And I think your last edit broke things entirely.) – DevSolar Sep 08 '22 at 22:11
  • What question is this supposed to answer? Whatever it is, it's also wrong. Try `integer_length(0)` – Ted Lyngmo Sep 08 '22 at 22:40
  • because of, `log10(x), x > 0`, thus `log10(0)` is `undefined`. Integer does not comes with a leading `0` and `array` with `length of 0` does not make any sense or should it? – XO56 Sep 08 '22 at 22:52
  • @XO56 Exactly. You used the wrong tools. `0` is a valid integer with length `1`. – Ted Lyngmo Sep 08 '22 at 22:55