Segmentation fault at base converting in C - c

trying to convert dec to 32-base, and then print it to a file.
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
char* baseConverter(int num, int base)
{ char* res;
int i=0;
if (num == 0 || base == 10)
{
snprintf(res,"%03x",num);
return *res;
}
while( num > 0 )
{
*(res+i) = digits[num%base];
num=num/base;
}
return *res;
}
and then at the output code :
sprintf(line, "%03s", baseConverter(i, 32);
but I keep getting that Segmentation fault (core dumped) error at running.

There are several things going on here:
First an uninitialised local pointer has an indeterminate value; it doesn't point anywhere in particular. The NULL pointer doesn't point anywhere either, but at least you can test for a NULL pointer easily. Make a habit of initalising a pointer to make it point to valid memory or to make it explicitly null.
The pointer is supposed to point to a char buffer. The way your function looks like, you must allocate memory for that buffer on the heap with malloc. (You can't use local storage, because that would be invalidated immediately.)
Don't make base 10 a special case. (You're even doing it wrong by printing base 10 numbers as hex.)
Your method of printing is okay, but you print the number backwards. So determine the required klength first and then decrement the position you print at.
Here, you deal with the raw characters. Use res[i] rather than do complicated things with the standard library functions. In particular, don't build strings by concatenating or printing strings to themselves. That's very likely undefined behaviour.
A possible implementation of your function could look like:
int ndigits(int num, int base)
{
int n = 0;
while (num) {
n++;
num /= base;
}
if (n == 0) n++;
return n;
}
char* baseConverter(int num, int base)
{
if (num >= 0 && base > 1 && base <= 36) {
int n = ndigits(num, base);
char *res = malloc(n + 1);
int i = n;
res[n] = '\0';
if (num == 0) res[--i] = '0';
while (num) {
res[--i] = digits[num % base];
num /= base;
}
return res;
}
return NULL;
}
Note how an auxiliary function is used to determine the length of the string. The string is then filled backwards, staring with the null terminator. Also note how invalid cases are handled by returning NULL.
Your calling code must explicitly free the string after using it:
int n = rand() % 100000 + 1;
int m = rand() % 10 + 2;
char *p = baseConverter(n, m);
if (p) printf("%d#%d == %s\n", n, m, p);
free(p);
C has manual memory management and keeping track of allocated stuff is tedious. You can't, for example, call baseConverter from inside printf, because you'd lose the handle to the allocated string.
Another popular variant is to have the calling code allocate the memory and then pas a buffer and its size to the function to fill it. A prototype could then look like this:
void sbase(char buf, size_t buflen, int num, int base);
It would then be called like this:
char buf[33]; // Maximum, when base 2 is printed
sbase(buf, sizeof(buf), 5000, 13);
puts(buf);
Because buf is an automatic variable, no freeing is to be done. (How to implement thins and how to properly enforce that the buffer size isn't exceeded is left as an exercise. :))

The main errors have already been pointed out.
Here is another suggested routine (it doesn't require malloc)
The function sets the value of a pointer to the number of converted digits, to make it easy to print out the required digits.
#include <stdio.h>
/* function takes pointer to array, size of array + number/base
and pointer for number of digits in conversion */
void make32(int *res32, int len, int num, int base, int *rln);
int main()
{
int digits32[20]; // size according to max conversion number in base 32
int len32 = sizeof(digits32)/sizeof(digits32[0]);
int in32, resln, n;
/* convert this number */
in32 = 10000;
/* call function with pointer + size & number/base & ptr to # converted digits*/
make32(digits32, len32, in32, 32, &resln);
/* print out result - reverse order - use number of digits */
for(n = resln; n >= 0; n--) {
printf("%d ", digits32[n]);
}
printf("\n");
return (0);
}
void make32(int *res32, int len, int num, int base, int *rln)
{
int i = 0;
while( num > 0 && i <= len ) {
res32[i] = num % base;
num = num / base;
i++;
}
/* set the number of converted digits */
*rln = i - 1;
}

Related

I made a function which covert decimal to binary. but it does not work

#include <stdio.h>
void DectoBin(int *n);
int *p;
int position;
int main()
{
int num;
printf("Input number : ");
scanf("%d", &num);
DectoBin(&num);
for (int i = position - 1; i >= 0; i--)
{
printf("%d", p[i]);
}
}
when launch this code, this code compile well...
but I have a error message 'zsh : segmentation fault'
void DectoBin(int *n)
{
int binary[20] = { 0, };
p = binary;
while (1)
{
binary[position++] = *n % 2;
*n = *n / 2;
if (n == 0)
break;
}
return;
}
so, What parts should be corrected to solve the problem??
I think the minimum change to make it seem to work is this:
// you use *n as an integer, but test "n"
// (which is its address, and will never be zero).
// So the while loop goes on indefinitely, eventually overflowing the buffer.
if (*n == 0)
break;
A more serious problem is that the buffer is allocated backwards: you have the pointer outside the function and the buffer is allocated on the stack inside the function. So, as soon as the function exits, the buffer is no longer "legal". The data is probably still there (on my system, it is) and you might even be able to use it as if nothing was amiss. On a short program, and depending on your system, you might not notice that the code has become a time bomb.
You ought to estimate how much of a buffer you need (how many binary digits), then allocate memory on the heap, using malloc(), check it worked, and pass that memory to the function - which will allocate nothing - together with the allocated size, so it can ensure it doesn't overflow the buffer.
The function would then return how many digits to actually print.
#include <stdio.h>
#include <malloc.h>
size_t DectoBin(size_t maxdigits, int *digits, int number);
int main() {
int num;
int *buffer;
size_t maxdigits, position;
printf("Input number : ");
scanf("%d", &num);
// Always check your inputs.
if (num < 0) {
printf("Negative numbers are not supported yet\n");
return 1;
}
maxdigits = 1;
{
// Calculate how many digits are required. Could use ceiling of base-2 logarithm of num.
int tmp = num;
while (tmp > 0) {
maxdigits ++;
tmp /= 2;
}
}
buffer = malloc(maxdigits * sizeof(int));
if (NULL == buffer) {
fprintf(stderr, "Out of memory\n");
return 2;
}
position = DectoBin(maxdigits, buffer, num);
for (size_t i = position; i > 0; i--) {
printf("%d", buffer[i-1]);
}
printf("\n");
return 0;
}
size_t DectoBin(size_t maxdigits, int *digits, int number) {
size_t pos = 0;
do {
digits[pos++] = number % 2;
number /= 2;
} while (number && pos < maxdigits);
return pos;
}
For starters there is a typo
if (n == 0)
It seems you mean
if (*n == 0)
Though there is no any sense to accept a number indirectly through a pointer to it.
You are using the local array binary with automatic storage duration within the function DectoBin
void DectoBin(int *n)
{
int binary[20] = {
0,
};
//...
that will not be alive after exiting the function. So the pointer p will have an invalid value.
Also it is unclear why you are using the magic number 20 in the array declaration. At least you should use the value of the expression sizeof( int ) * CHAR_BIT.
Also it is a bad idea to use global variables.
At Least you could declare the array within the function with the storage-class specifier static and return a pointer to the array from the function.
Pay attention to that for negative numbers you can get an incorrect result.
For example the function can be implemented the following way as shown in the demonstration program below.
#include <stdio.h>
#include <limits.h>
#include <string.h>
const char * DecToBin( int n )
{
static char binary[CHAR_BIT * sizeof( int ) + 1 ];
memset( binary, 0, sizeof( binary ) );
unsigned int un = n;
char *p = binary + sizeof( binary ) - 1;
do
{
*--p = '0' + ( un & 1 );
} while ( un >>= 1 );
return p;
}
int main( void )
{
printf( "%d -> %s\n", 123, DecToBin( 123 ) );
printf( "%d -> %s\n", -123, DecToBin( -123 ) );
}
The program output is
123 -> 1111011
-123 -> 11111111111111111111111110000101

Global variable losing data in C?

I am trying to create a array of array of string where each row (if considered matrix) should have 3 strings of any length and a maximum of 10 rows
The data Structure is correct but I am very much surprised with the output I get in the global variable. So the matrix would act as the database to the program and hence kept in global space
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Maximum buffer size needed
#define MAX_NUM_ITEMS 10
#define MAX_ITEM_PER_ROW 3
static char *array[MAX_NUM_ITEMS][MAX_ITEM_PER_ROW];
#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)
char *itoa_base(char *, int , int);
#define TO_BASE(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
char *itoa_base(char *s, int x, int base) {
s += ITOA_BASE_N - 1;
*s = '\0';
if (base >= 2 && base <= 36) {
int x0 = x;
do {
*(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
x /= base;
} while (x);
if (x0 < 0) {
*(--s) = '-';
}
}
return s;
}
int main(void)
{
int count = 0;
for (int i = 0; i < MAX_NUM_ITEMS; i++){
for (int j = 0; j < MAX_ITEM_PER_ROW; j++ ){
++count;
array[i][j] = TO_BASE(count, 16);
}
}
for (int i = 0; i < MAX_NUM_ITEMS; i++){
for (int j = 0; j < MAX_ITEM_PER_ROW; j++ ){
printf("%s ",array[i][j]);
}
printf("\n");
}
return 0;
}
From my logic I should see
1 2 3
4 5 6
7 8 9 and so on and not E E E
can't understand why that is happening
First, this:
(char [ITOA_BASE_N]){0}
Does not get you a new instance of a character array, unlike say golang. So, every time you call itoa(), you are calling it with the same character array. Somewhat worse, the character array is occupying a reclaimable stack address [ its scope is only that inner loop ], so it can be over written with random stuff shortly after. It is remarkably consistent though; I will give it that.
Changing the invocation to:
array[i][j] = strdup(TO_BASE(count, 16));
and adding a #include at the top produces the output you wanted.
If dynamic allocation is not permissible in your application, you will have to use a static allocation scheme, which you could make a bounded version of strdup like:
char *strnew(char *s) {
static char strspace[ITOA_BASE_N * MAX_NUM_ITEMS * MAX_ITEM_PER_ROW ];
static char *strnext = strspace;
if (strlen(s) + strspace >= &strspace[sizeof strspace]) {
s = "<error: out of space>"; /* something more clever is possible */
} else {
strcpy(strnext, s);
s = strnext;
strnext += strlen(strnext)+1;
}
return s;
}
which you could substitute for strdup. If you do the next person down the line a favour and use a more descriptive notion like MAX_STRING_SPACE which is based on the calculation; and rather than insert a "bad value", cause some sort of exception, I am sure they would appreciate it.
The problem is here:
itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
^^^^^^^^^^^^^^^^^^^^^^^
you are allocating a temp array (on the stack) which is only valid up to the end of the containing expression statement. So when the time comes to print them, the pointers you've stored in the matrix are dangling. What the compiler ends up doing is reusing the same memory for every call, so the strings end up overwriting.
You could instead use a static matrix of arrays rather than pointers:
static char array[MAX_NUM_ITEMS][MAX_ITEM_PER_ROW][ITOA_BASE_N];
then your call in the first loop becomes
itoa_base(array[i][j], count, 16);
you'll also need to "fix" itoa_base so it puts the result in the front of the array rather than the back. Obvious way is with a recursive loop like:
char *itoa_base(char *s, int x, int base) {
if (base >= 2 && base <= 36) {
if (x < 0) {
*s++ = '-';
x = -x; }
if (x >= base)
s = itoa_base(s, x/base, base);
*s++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[x % base];
}
*s = '\0';
return s;
}

While trying to write the recursive version of atoi, what is the meaning of itoa(n /10, s) and why is it advisable to avoid static int i = 0?

I'm sorry if my question is quite vague, because it is without context. So I was trying to solve a question: Write a recursive version of the function itoa(i) which converts an integer i into a string.
As I ran out of idea how to solve it, I started looking online to find solutions and I came across some of them which usually use this line: itoa(n/10, s);. For example, from this StackOverflow question: itoa recursively. I can't understand what it does to i.
So I went on and searched for more solutions and I found one that actually works, the program looks like this:
#include <stdio.h>
char *itoa(int n, char s[]);
int main()
{
char number[100];
printf("-90 to string = %s\n", itoa(-90, number));
return 0;
}
char *itoa(int n, char s[])
{
static int i = 0;
if (n < 0) {
s[i++] = '-';
n = -n; /* does not work for largest negative number in two complement */
}
if (n / 10)
itoa(n /10, s);
s[i++] = n % 10 + '0';
s[i] = '\0';
return s;
}
Problem is, according to the solutions I found on other websites, people said that we should avoid using static int i. I did not read why we should do so because I don't know how static works so I don't know if this program is fine or needs improvements.
Your function pretty much almost right, that is for a recursive method. If you were going to parse the digit to string backward, it is right. Otherwise, I just did a couple fix.
For parsing digit to string, the digits that are being parsed are from the right digits to left digits as the remainder is what being used. Thus, when storing those into a string, we will need to go from high to low indexes. If we use remainders for parsing, we will not know the length of the number that is being parsed. Thus, in most parse cases there will be some extra spaces at the beginning of your string or char array.
For using the static i, you can pass a version of it around but it would make it harder to use as you would need to know to always have to pass i at 11. "i" is at 11 because the maximum digits for an int is 10(digits) + 1 sign and the 12th character which not counted by "i" is the null char. To make it easier to use the function, I configured the third parameter to be a void pointer. However, do not pass it an actual pointer, pass it a NULL. When it see NULL as the third parameter, it know that, that is the first call.
#include <stdio.h>
#include <string.h>
char *itoa(int n, char s[], void * );
int main()
{
char number[100] = {0};
printf("-90 to string = %s\n", itoa(154, number, NULL));
printf("-15 to string = %s\n", itoa(-15, number, NULL));
printf("-2147483648 to string = %s\n", itoa(-2147483648, number, NULL));
return 0;
}
// The reason why I pass a void pointer is because
// instead of passing the value is because it easier to use function without needing to know that the string have to go from right left.
// When you first call it just use NULL as the third parameter. Anything else can ruin it.
char *itoa(int n, char s[], void * firstCall )
{
static int i;
if ( firstCall == NULL ) {
i = 11;
s[11] = 0;
}
int neg = 0;
if (n < 0) {
if ( n == -2147483648 ) {
strcpy(s, "-2147483648");
return s;
}
neg=1;
n = -n; /* does not work for largest negative number in two complement */
}
s[--i] = (n % 10) ^ 48;
if ( n / 10 ) itoa(n / 10, s, s);
if ( neg == 1 ) s[--i] = '-';
return &s[i];
}

c from integer to string function

void to_string(int x)
{
int value, i = 0;
char numericalChar[] = "0123456789";
char *string;
do
{
value = x % 10;
string[i++] = numericalChar[value];
x /= 10;
} while(x >= 0);
printf("%s\n", string);
}
I am trying to write a function that turns an integer into a string. I don't think there is nothing with my logic but I am getting a segfault and my printf() is not printing anything out. I probably missing something obvious. I have been sitting in front of the computer for an hour and still, I can't figure it out. Thanks in advance.
I guess you know that there are in fact standard function for this (e.g. sprintf - see example below) but just want to write it yourself, right...
In that case:
First of all you need to assign memory to hold the string. Using a char pointer is not enough. You get a seg fault because of that. A uninitialized pointer just points somewhere into memory where you are (most likely) not allowed to write. So when do... it seg faults. In this case just use a short fixed size char array instead.
Second it is much easier just to add each digit to the char '0' to get the correct digit. No need for an array as look up table.
Something like:
void to_string(int x)
{
char string[32] = "0";
if (x > 0)
{
char temp[32] = {0};
int i = 31;
// Build a temp string from from the end (right to left)
while(x > 0)
{
temp[--i] = '0' + (x % 10);
x /= 10;
}
// Copy the temp string to the target variable
strcpy(string, &temp[i]);
}
printf("%s\n", string);
}
Notice that this code only handles integers greater than or equal to zero. I'll leave negative integers as an exercise.
If you want to use e.g. sprintf it's as easy as:
int n = 42;
char string[32];
sprintf(string, "%d", n);
printf("%s\n", string);
So as people already commented on your question, you have not allocated space so:
char *string;
should be
char *string = malloc ( sizeof (char) * numberOfDigits);
and there is another seg fault that I could not figure out, while I fix it I will give you this:
itoa solutions
void to_string(int x) {
string s = "";
while(x){
s += (x % 10) + 48;
x /= 10;
}
printf("%s\n", s);
}

Cast int to char array in C

Is is possible to convert int to "string" in C just using casting? Without any functions like atoi() or sprintf()?
What I want would be like this:
int main(int argc, char *argv[]) {
int i = 500;
char c[4];
c = (char)i;
i = 0;
i = (int)c;
}
The reason is that I need to generate two random ints (0 to 500) and send both as one string in a message queue to another process. The other process receives the message and do the LCM.
I know how to do with atoi() and itoa(). But my teachers wants just using cast.
Also, why isn't the following possible to compile?
typedef struct
{
int x;
int y;
} int_t;
typedef struct
{
char x[sizeof(int)];
char y[sizeof(int)];
} char_t;
int main(int argc, char *argv[])
{
int_t rand_int;
char_t rand_char;
rand_int.x = (rand() % 501);
rand_int.y = (rand() % 501);
rand_char = (char_t)rand_int;
}
Of course it's not possible, because an array is an object and needs storage. Casts result in values, not objects. Some would say the whole point/power of C is that you have control over the storage and lifetime of objects.
The proper way to generate a string containing a decimal representation of an integer is to create storage for it yourself and use snprintf:
char buf[sizeof(int)*3+2];
snprintf(buf, sizeof buf, "%d", n);
You have to convert 500 to "500".
"500" is the same as '5' then '0' then '0' then 0. The last element 0 is the null terminator of a string.
500 is equal to 5 * 100 + 0 * 10 + 0 * 1. You have to do some math here. Basically you have to use the / operator.
Then this could be also useful: '5' is the same as '0' + 5.
Without giving away an exact coded answer, what you'll want to do is loop through each digit of the integer (by computing its remainder modulo 10 via the % operator), and then add its value to the ASCII value of '0', casting the result back to a char, and placing that result in a null-terminated string.
An example which pretends like implicit casts don't exist might look like this:
char c = (char) ( ((int) '0') + 5 ); // c should now be '5'.
You can determine the length of the resulting string by computing the log base 10 of the number, or by simply allocating it dynamically as you go using realloc().
Casting is a horrible way to do this due to endianness, but here is an example anyhow - there are some occasions where it is useful (unions work better these days though, due to compiler handling of these types of casts).
#include <stdio.h> //for printf
#define INT(x) ((int*)(x)) //these are not endian-safe methods
#define CHAR(x) ((char*)(x))
int main(void)
{
int *x=INT(&"HI !");
printf("%X\n",*x); //look up the ascii and note the order
printf("%s\n",CHAR(x));
return 0;
}
For an int with a value <500, if the most significant byte comes first, then you get a "string" (pointer to a char array) of "" (or {0}) but if the endianness is LSB first (x86 is little endian) then you would get a usable 3 byte "string" char* (not necessarily human readable characters) but there is no guarantee that there will be a zero byte in an integer and since all you have is a pointer to the address where the int was stored, if you were to run normal string functions on it, they would go past the end of the original int into no-mans-land (in small test programs it will often be environment variables) ... anyhow for more portability you can use network byte order (which for little endian is a no-op):
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
These functions just byteswap as necessary to get network byte order. On your x86 they will be optimized away, so you might as well use them for portability.
Just because it is not listed yet: Here a way to convert int to char array with variable size allocation by using snprintf:
int value = 5
// this will just output the length which is to expect
int length = snprintf( NULL, 0, "%d", value );
char* valueAsString = malloc( length + 1 );// one more for 0-terminator
snprintf( valueAsString, length + 1, "%d", value );
get the number of divisions then add one by one to your buffer
char *int2str(int nb) {
int i = 0;
int div = 1;
int cmp = nb;
char *nbr = malloc(sizeof(char) * 12);
if (!nbr)
return (NULL);
if (nb < 0)
nbr[i++] = '-';
while ((cmp /= 10) != 0)
div = div * 10;
while (div > 0) {
nbr[i++] = abs(nb / div) + 48;
nb = nb % div;
div /= 10;
}
nbr[i] = '\0';
return (nbr);
}
Even more compact:
char *lotaa(long long nb) {
int size = (nb ? floor(log10(llabs(nb))) : 0) + (nb >= 0 ? 1 : 2);
char *str = malloc(size + 1);
str[0] = '-';
str[size] = 0;
for(nb = llabs(nb); nb > 0 || (size > 0 && str[1] == 0); nb /= 10)
str[--size] = '0' + nb % 10;
return (str);
}

Resources