1

Let's say I have a function that takes in an integer as an argument and returns an array that has all the digits of the integer separated as a 1D array (pseudocode):

int separatingInt (int num)
{
    int length = amount of digits in num
    int *arr = new int[length]

    for ( int i = length; i > length; i-- )
    {
        arr[i] = num%10
        num = num /10
    }

    return *arr
}

int main()
{
    ifstream file
    file.open("liczby.txt")

    int number
    file >> number

    int* arrayFromNumber = seperatingInt(int num)
}

How do I declare an array from seperatingInt() in main() (referring to the last line in the pseduocode)? Is it better to just separate the digits into an array in seperate?

I was not even sure how to formulate my question properly, so I couldn't find answers myself.

I guess you could do it with a loop in the main() function, but since it's reading numbers from a file, and they all have different amounts of digits, it would look messy. Maybe messy is the way to go, I don't know.

11
  • 5
    return *arr should be return arr. And change the function type to int *. Commented Sep 17, 2024 at 17:45
  • 5
    Also, in C++ you should use std::vector, not C-style arrays. Commented Sep 17, 2024 at 17:46
  • 11
    Stop using c-arrays. Either use std::array for arrays where the size is fixed at compile time or std::vector for an array with dynamic size. Commented Sep 17, 2024 at 17:47
  • 3
    There is no way to return an array from a function in either C or C++. You can return a pointer to an array, but that is not the same thing. In C++ the sensible way to write your function would be to have it return a std::vector<int> which is an array like object (actually much more powerful than an array) which can be returned from a function. Commented Sep 17, 2024 at 17:50
  • 3
    In arr[i] = num%10, i is out of bounds. Not that it matters, since your for loop is wrong to begin with, as i > length will never be true. Commented Sep 17, 2024 at 17:52

3 Answers 3

8
#include <array>
#include <ranges>
#include <limits>
#include <cstdint>

using my_uint = std::uint64_t;

using digit_array =
   std::array<
      std::uint8_t,
      1 + std::numeric_limits<my_uint>::digits10
   >;

digit_array explode_digits(my_uint n){
    digit_array result{};
    for(auto& digit: result | std::views::reverse){
        /*if (n==0) //optimize for speed?
           break;*/
        digit = std::uint8_t(n % 10);
        n /= 10;
    };
    return result;
};

This is what I recommend as beginner stuff, not what academics teach.

As everyone suggests you can use std::vector, but for a 64 bit number, you only need 20 digits; It's not so much memory that you need to store on heap. If std::uint32_t is used, then the number of digits decreases to just 10, and for std::uint16_t, it'd be just 5.

Sign up to request clarification or add additional context in comments.

3 Comments

@francesco 😅 Now fixed
is it bad practice to use using namespace std; ? Most people Ive seen on here just use the prefix std:: instead...
@joler that could be another question. Generally using namespace must only be used in narrow scope(i.e inside an if or a for. Because it injects all the identifier names within the namespace into the declaration scope; that increases the risk of name collision, specially when multiple namespaces are involved. The inly exception is using namespace std::literals;. This is the only one recommended in global scope. It enables std UDLs("string_view"sv, "string"s, 1h+30min+15s...).
3

For a dynamic allocation, the most common solution would use a std::vector. A simple solution would just push back the remainders into the vector and then reverse the vector:

#include <algorithm>
#include <vector>

std::vector<int> seperatingInt(int num) {
    std::vector<int> arr;              // an empty vector of ints
    const int neg = num < 0 ? -1 : 1;

    do {
        // push back the (positive) remainders, growing the vector dynamically:
        arr.push_back(neg * (num % 10));
    } while (num /= 10);

    std::reverse(arr.begin(), arr.end());

    // if num was negative, make the first digit negative:
    arr.front() *= neg; // or: arr.front() = neg * arr.front();

    return arr;
}

Example usage:

#include <climits>
#include <iostream>

int main() {
    for (int test : {INT_MIN, -123, 0, 456, INT_MAX}) {
        auto res = seperatingInt(test);

        std::cout << test << ':';

        for (int val : res) {
            std::cout << ' ' << val;
        }
        std::cout << '\n';
    }
}

Possible output:

-2147483648: -2 1 4 7 4 8 3 6 4 8
-123: -1 2 3
0: 0
456: 4 5 6
2147483647: 2 1 4 7 4 8 3 6 4 7

Comments

2

Yes use std::vector as shown here

#include <sstream>
#include <iostream>
#include <vector>

// When testing "files" don't use them use this instead
std::istringstream input_file{ "\
1\n\
2\n\
3\n\
5\n\
8\n\
"};

std::vector<int> load(std::istream& is)
{
    int value;
    std::vector<int> values;
    while( is >> value )
    {
        values.push_back(value);
    }

    return values;
}

int main()
{
    //std::ifstream input_file{"filename.txt"};
    auto values = load(input_file);

    for(const int value : values) // range based for loop
    {
        std::cout << value << "\n";
    }

    return 0;
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.