Return array with unknown size in C

Hello,
How can I print all of arr? we don't know what is the array size. ( Line 42)

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
#include<stdio.h>
#include<math.h>
int Palindrome(int num)
{
    int first = num;
    int result = 0;
    while (num)
    {
        result = result * 10 + num % 10;
        num /= 10;
    }
    return (first == result) ?  1 :  0;
}
int toBase10(int num, int base)
{
    int result = 0;
    int i = 0;
    while (num)
    {
        result = num % 10 * pow(base, i++);
        num /= 10;
    }
    return result;
}
int* toBase(int num, int to)
{
    int arr[50] ,i = 0;
    while (num)
    {
        arr[i++] = num % to;
        num /= to;
    }
    return arr;

}

int main()
{
    int *a = toBase(3033, 7); 
    while(*a)
    {
        printf_s("%d ",*a++); // It should print 2 6 5 1 1 but print 2 
    }
 
    return 0;
}
Last edited on
¿why do you think the array will be 0 terminated? even if that's the case, 0 is a valid value for an element of the array, ¿so how would you represent 0?
also, `arr' is a local variable, which will be destroyed when the function ends.

perhaps you should change your prototype void toBase(int num, int to, int result[], int *size);
the size of the array is on `i'
@ne555
Thank you but we don't know what is the size of arr in toBase function. The size of the arr is not fixed.
we don't know what is the size of arr in toBase function

How so?
Maybe you meant: «We don’t care to take the tally of our data while we collect them»?
Either if you ask the user for those data, or you read them from a file or a database, or you reckon them step by step at runtime, however you can know their quantity.
If you really want to write C-style code (by the way, wouldn’t it be wiser to ask about C code in a C forum?) you’d better get used to the idea you nearly always need to record the size of your C-style arrays somewhere.

You can try to simplify your life by structs – I have no idea if this basic example could be easily translated in C (please note your conversion method works only if the base to be converted to is greater than the actual number base):
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <cstdlib>
#include <cstdio>
#include <cmath>


struct MyIntArr {
    int * p;
    int capacity;
    int size;
};


MyIntArr* clear(MyIntArr* const mia);
MyIntArr* doubleIntArr(MyIntArr* const mia);
MyIntArr* initMyIntArr(MyIntArr* const mia);
MyIntArr* pushBack(MyIntArr* const mia, int val);
MyIntArr* setCapacity(MyIntArr* mia, int val);
int* copyIntArr(int* const lhs, int lhs_size, int* const rhs);
void destroyIntArr(int* p);
MyIntArr toBase(int num, int to);


int main()
{
    MyIntArr a = toBase(3033, 7); 
    for ( int i = 0; i < a.size; ++i ) {
        printf("%d ", a.p[i]);
    }
    printf("%c", '\n');
    destroyIntArr(a.p);
    return 0;
}


MyIntArr* clear(MyIntArr* const mia)
{
    setCapacity(mia, 0);
    return mia;
}


MyIntArr* doubleIntArr(MyIntArr* const mia)
{
    int new_cap = mia->capacity ? mia->capacity * 2 : 1;
    setCapacity(mia, new_cap);
    return mia;
}


MyIntArr* initMyIntArr(MyIntArr* const mia)
{
    mia->capacity = 0;
    mia->size = 0;
    mia->p = nullptr;
    return mia;
}


MyIntArr* pushBack(MyIntArr* const mia, int val)
{
    if ( mia->size == mia->capacity ) {
        doubleIntArr(mia);
    }
    mia->p[mia->size] = val;
    ++mia->size;
    return mia;
}


MyIntArr* setCapacity(MyIntArr* mia, int val)
{
    if ( val < 0 ) { return mia; }      // reject

    if ( val == 0 ) {
        if ( mia->capacity == 0 ) {
            return mia;
        }
        destroyIntArr(mia->p);
        mia->capacity = 0;
        mia->size = 0;
        return mia;
    }

    // val > 0
    if ( mia->capacity == 0 ) {
        // NO need to copy anything:
        mia->p = (int*)std::calloc( val, sizeof(int) );
        mia->capacity = val;
        return mia;
    }

    int * p = (int*)std::calloc( val, sizeof(int) );
    if ( val < mia->size ) {
        mia->size = val;
    }
    copyIntArr(mia->p, mia->size, p);
    mia->capacity = val;
    std::free( mia->p );
    mia->p = p;
    return mia;
}


int* copyIntArr(int* const lhs, int lhs_size, int* const rhs)
{
    for ( int i = 0; i < lhs_size; ++i ) {
        rhs[i] = lhs[i];
    }
    return rhs;
}


void destroyIntArr(int* p)
{
    std::free( p );
    p = nullptr;
}


MyIntArr toBase(int num, int to)
{
    MyIntArr mia;
    initMyIntArr( &mia );
    int num_length = static_cast<int>( std::log10(num) ) + 1;
    for (int i = 0; i < num_length; ++i) {
        pushBack( &mia, num % to );
        num /= to;
    }
    return mia;
}


Output:
2 6 5 1

Sorry! Modify toBase() this way to get the correct output:
1
2
3
4
5
6
7
8
9
10
MyIntArr toBase(int num, int to)
{
    MyIntArr mia;
    initMyIntArr( &mia );
    while ( num ) {
        pushBack( &mia, num % to );
        num /= to;
    }
    return mia;
}


2 6 5 1 1

[ edit: the toBase() function below fails if the output number contains zero digits within it. See Enoizat's post below.]

Pass the result array to toBase() so you don't return a local variable. To null terminate it, including the special case of zero, exit from the middle of the loop:
1
2
3
4
5
6
7
8
9
10
11
12
// Convert num to base "to" and store the result in arr, which must be
// large enough. Each value in arr contains one base-"to" digit with
// arr[0] holding the least significant. The most significant digit will always be zero.
void toBase(int num, int to, int arr[])
{
    int i = 0;
    while (true) {
        arr[i++] = num % to;
        if (num == 0) break;
        num /= to;
    }
}


Create a function to print a number. This needs to handle the special case of zero explicitly. Or at least I couldn't figure out another way:
1
2
3
4
5
6
7
8
9
10
void printArr(int *a)
{
    if (*a == 0) {
        printf("%d ", *a);      // special case for zero
    } else {
        do {
            printf("%d ",*a++);
        } while (*a);
    }
}

and to test it:
1
2
3
4
5
6
7
8
9
10
11
int main()
{
    int arr[50];
    toBase(3033, 7, arr);
    printArr(arr);
    putchar('\n');
    toBase(0, 7, arr);
    printArr(arr);
    putchar('\n');
    return 0;
}

$ ./foo
2 6 5 1 1
0

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int * toBase( int n, int base )
{
   int length = 1;
   for ( int nn = n; nn >= base; nn /= base ) length++;   // count chars
   int *result = new int[ length + 1 ]{};                 // initialisation needed for edge case
   result[length] = -1;                                   // sentinel terminator
   for ( ; n; n /= base ) result[--length] = n % base;    // REVERSE ORDER
   return result;
}

int main()
{
   int * a = toBase( 3033, 7 );
   for ( int i = 0; a[i] >= 0; i++ ) std::cout << a[i] << ' ';
   delete [] a;
}


1 1 5 6 2
Last edited on
@dhayden, could you please clarify me how your code works? What happens if a converted number has got a zero among its digits?
Let’s say I want to convert base ten 6868 into base seven. Shouldn’t it be 26011? What does your code print?

(Aside note: we can assume we are speaking of C++ – are there booleans in C? Does while (true) really compile?)
nn >= base; nn /= base
@lastchance, abs() to avoid issues with negative numbers?
are there booleans in C?

Since C99 <stdbool.h>

https://en.cppreference.com/w/c/types/boolean

There is <cstdbool> for C++, but it is meaningless since the C macros are C++ keywords.

<cstdbool> was added in C++11, deprecated in C++17 and will be removed in C++20.
Last edited on
Thank you, Furry Guy.
Topic archived. No new replies allowed.