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);
}
Related
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];
}
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;
}
I've been looking for about half an hour and I can't seem to find a good process for setting up a char* that points to a string of characters which correspond to a Hexidecimal string.
Just to clarify, what I'm trying to do is take a Hexidecimal string, (say 0x0043 for example) and end up with a character string that contains "0x0043" that can be used on an LCD display or written to a file easily.
I'm sure there is a fairly easy way to do this, but have found no leads. Anyone in the know on this?
EDIT: This is for an embedded project, so I don't have any access to predefined functions.
Convert 1 hex digit at a time.
void foo(unsigned x) {
char buf[2 + sizeof x * 2 + 1];
char *p = &buf[sizeof buf - 1];
*p-- = '\0';
do {
*p-- = "0123456789ABCDEF"[x&15];
x >>= 4;
} while (p != &buf[1]);
*p-- = 'x';
*p = '0';
// Use p
}
Are you looking for something like this:
#include <stdio.h>
#define MAX_HEX_LENGTH 10
int main()
{
int x = 0x0043;
char str[MAX_HEX_LENGTH];
sprintf(str, "0x%.*x", MAX_HEX_LENGTH, x);
printf("%s\n", str);
}
OUTPUT:
0x0000000043
You can change the value MAX_HEX_LENGTH to anything you want.
This question already has answers here:
How to convert unsigned long to string
(7 answers)
Closed 8 years ago.
So I have this function:
static void doPrint (const char *s)
{
write (STDOUT_FILENO, s, strlen(s));
}
I am trying to pass it an unsigned long variable but nothing I have tried has worked so far. My question is, how do I go about doing this? I was thinking of using something along the lines of _ultoa_s or another similar function.
Any ideas? Thanks
Note: Access to printf, sprintf, ect is restricted
You could try passing the pointer to long variable and the size to your doPrint function as below
doPrint((char *)(&someLongVariable), sizeof(someLongvariable));
void doPrint(char *inpString, int size)
{
write (STDOUT_FILENO, inpString, size);
}
You didn't mention whether "restricted" means that the easy functions (printf and friends) aren't available on your (embedded?) platform, or that this is a restriction of the assignment.
Anyways, what you are doing won't work, ever. You're passing in a binary variable (a long), it won't automagically get converted to a string.
Check out this function, found here, a compact itoa function. Some tweaking required to make an ltoa out of it, but it's easy to see how it works.
//return the length of result string. support only 10 radix for easy use and better performance
int my_itoa(int val, char* buf)
{
const unsigned int radix = 10;
char* p;
unsigned int a; //every digit
int len;
char* b; //start of the digit char
char temp;
unsigned int u;
p = buf;
if (val < 0)
{
*p++ = '-';
val = 0 - val;
}
u = (unsigned int)val;
b = p;
do
{
a = u % radix;
u /= radix;
*p++ = a + '0';
} while (u > 0);
len = (int)(p - buf);
*p-- = 0;
//swap
do
{
temp = *p;
*p = *b;
*b = temp;
--p;
++b;
} while (b < p);
return len;
}
Almost certainly you do not want to pass a double to this function. It expects text to output which is the convention of stdout.
Almost certainly, you first need to represent the double's value in characters and pass that to the function. This is a complex topic, and probably the point of the exercise. Google for "convert float to ascii" for some ideas of what you have to do.
Follow up:
If you are permitted to use _ultoa_s, then certainly you could call fcvt() or ecvt().
I've got a very very simple function which simply converts a char to a char* which represents the binary value of the char with 0's and 1's as chars.
char* stringToBin(char symbol) {
int pos = 0;
int value = (int) symbol;
int rest;
char* result = (char*) malloc(sizeof(char) * 9);
while(value > 0) {
if(value % 2 == 0) {
result[7-pos] = '0';
}
else {
result[7-pos] = '1';
}
pos++;
value = value / 2;
}
while(pos < 8) {
result[7-pos] = '0';
pos++;
}
result[8] = '\0';
puts(result);
puts(strlen(result));
return result;
}
My problem is I can't print the length of the char*. Printing the whole char* works perfect but not calculating the size. I alway get a segmentation fault. I think the problem is pretty simple but I did not get it right now. So please give me the missing hint ;)
The problem is not with the NUL-termination of your string, that's fine. Instead,
puts(strlen(result));
is wrong. puts() expects a C string, and you're giving it a size_t. Write instead:
printf("%zu\n", strlen(result));
(This assumes that the C99 format specifier %zu for size_t is available. If it isn't, then use:
printf("%u\n", (unsigned)strlen(result));
instead.)