I have a function in which the second pass gives me segfault every time and I have no idea how to fix it. Any advice would be appreciated.
char* testBefore(int k){
char* bin;
bin = calloc(1,1);
while(k > 0) {
bin = realloc(bin, strlen(bin)*sizeof(char)+1);
bin[strlen(bin) - 1] = (k % 2) + '0';
bin[strlen(bin)] = '\0';
k = k / 2;
}
printf("\n%s.", bin);
return bin;
}
strlen does not give the size of the array.
This will not enlarge the memory:
bin = realloc(bin, strlen(bin)*sizeof(char)+1); //0+1 == 1
And then calling strlen on that memory will produce undefined behavior since the result strlen(bin) - 1 will be negative:
bin[strlen(bin) - 1] = (k % 2) + '0'; //bin[0-1]
In you case you should use an extra variable that keeps the size of the allocated memory.
sample to fix.
char* testBefore(int k){
char* bin;
int i = 0;
bin = calloc(1,1);
while(k > 0) {
bin = realloc(bin, (i+1)*sizeof(char)+1);
bin[i++] = (k % 2) + '0';
k = k / 2;
}
bin[i] = '\0';
printf("\n%s.", bin);//reversed
return bin;
}
char* bin;
bin = calloc(1,1);
Now bin points to a 1-byte space containing 0.
while(k > 0) {
bin = realloc(bin, strlen(bin)*sizeof(char)+1);
Not sure about what k would be. Anyway, strlen(bin) == 0 since bin[0] == '\0'.
Afterward, bin points to another 1-byte space storing 0.
bin[strlen(bin) - 1] = (k % 2) + '0';
Here strlen(bin) returns 0 again, and accessing bin[0-1] is obviously out-of-bound and thus undefined behavior happened.
Related
verylong multiply_verylong(verylong vl1, verylong vl2)'verylong defines as typedef char* verylong'
{
size_t maxln, minln;
int carry=0, placeSaver=1, i, k ,sum=0,dif,newln,newln2,ln1,ln2;
verylong newNum , maxVl,minVl,tempvl,addvl;
ln1 = strlen(vl1); // 'length of first str'
ln2 = strlen(vl2);'length of second str'
if (ln1 >= ln2)
{
maxln = ln1;
minln = ln2;
maxVl = (verylong)calloc(maxln + 1, sizeof(char));
assert(maxVl);
minVl = (verylong)calloc(minln + 1, sizeof(char));
assert(minVl);
strcpy(maxVl, vl1);
strcpy(minVl, vl2);
dif = maxln - minln;
}
else 'stops debuging here'
{
maxln = ln2;
minln = ln1;
maxVl = (verylong)calloc(maxln + 1, sizeof(char));
assert(maxVl);
minVl = (verylong)calloc(minln + 1, sizeof(char));
assert(minVl);
strcpy(maxVl, vl2);
strcpy(minVl, vl1);
dif = maxln - minln;
}
newln = 2 * maxln + 1; 'maximum length of new required string'
newln2 = newln - 1; 'the index of the new string'
newNum = (verylong)calloc(newln,sizeof(char));
addvl = (verylong)calloc(newln, sizeof(char));
tempvl = (verylong)calloc(newln, sizeof(char));
for (i = minln - 1; i >= 0; i--) ' elementry school multiplication'
{
for (k = maxln - 1; k >= 0; k--)
{
sum = ((minVl[i] - '0')*(maxVl[k] - '0')*placeSaver)+carry;
if (sum >= 10)
carry = sum / 10;
if (k == 0)
newNum[newln2] = '0' + sum;
else
newNum[newln2] = '0' + sum%10;
newln2--;
}
placeSaver*=10;
addvl=add_verylong(newNum,tempvl);'sending the 2 strings to a previous function that adds 2 strings'
strcpy(tempvl, addvl);
}
return addvl;
}
void main()
{
char vl1[80], vl2[80];
printf("enter large number\n");
gets(vl1);
printf("enter large number\n");
gets(vl2);
verylong res = multiply_verylong(vl1, vl2);'saves the string '
printf("%s", res);
free(res);
}
I tried to multiply the first digit of the first number from right with all of the digits from the second number moving forward to the second digit of the first number and then to multiply the placesaver by 10 .
***
the problem is that the code outputs usually nothing and sometimes just inccorect result
***
Your approach is basically right, but there are some mistakes in the implementation.
You allocate space for addvl, but overwrite that pointer later with the return value of add_verylong(). This gives a memory leak. Further memory leaks are produced by not freeing tempvl, maxvl, minvl and newNum.
You forgot to initialize tempvl to the number "0".
We cannot shift the intermediate product by multiplying each digit with the power of ten placeSaver. What we can do is place 0 digits to the right of the product newNum.
You failed to correctly set carry in each loop cycle.
You missed that even the leftmost digits can produce a carry.
This code has the mentioned mistakes corrected:
newNum = calloc(newln, sizeof(char));
// do not allocate space for addvl - it would be lost
tempvl = malloc(newln);
strcpy(tempvl, "0"); // don't forget to initialize tempvl to "0"
for (i = minln - 1; i >= 0; i--) // elementry school multiplication
{
newln2 = newln - 1; // the index of the new string
for (carry = 0, k = maxln - 1; k >= 0; k--) // clear carry before each loop
{
sum = (minVl[i] - '0')*(maxVl[k] - '0') + carry;
carry = sum/10;
newNum[--newln2] = '0' + sum%10;
}
if (carry) newNum[--newln2] = '0' + carry;
addvl = add_verylong(newNum+newln2, tempvl); // number starts at +newln2
free(tempvl); // free obsolete number
tempvl = addvl; // rather than strcpy()
newNum[--newln-1] = '0'; // instead of placeSaver*=10
}
free(maxVl), free(minVl), free(newNum);
return addvl;
It works for the example multiply_verylong("23345", "34565"), but you should do further tests.
I'm a newcomer to programming, and I chose C as my first language(been learning it for a month or so).
I've been trying to solve this palindrome question for hours and still couldn't come up with a satisfying solution.
The question is here (from SPOJ), and here's my code:
#include <stdio.h>
#include <string.h>
void plus_one(char *number);
int main(void)
{
char number[1000001];
int i, j, m, k, indicator;
int a;
scanf("%d", &j);
for (i = 0; i < j; i++) {
scanf("%s", number);
k = 1;
while (k != 0) {
plus_one(number);
a = strlen(number);
indicator = 1;
for (m = 0; m < a / 2; m++) {
if (number[m] != number[a - m - 1]) {
indicator = 0;
break;
}
}
if (indicator != 0) {
printf("%s\n", number);
k = 0;
}
}
}
return 0;
}
void plus_one(char *number)
{
int a = strlen(number);
int i;
number[a - 1]++;
for (i = a; i >= 0; i--){
if (number[i - 1] == ':') {
number[i - 1] = '0';
number[i - 2]++;
}
else
break;
}
if (number[0] == '0') {
number[0] = '1';
strcat(number, "0");
}
return;
}
My idea was to examine every number greater than the input until a palindrome is found, and it worked well on my computer. But SPOJ responded "time limit exceeded", so I guess I need to find the next palindrome possible myself instead of using brute force. Can someone please give me a hint about how I can make this go faster? Thanks!
Since you're asking for a hint and not for C code (which I'm notoriously bad at), here's what I would do:
Determine if the number k has an even or odd number of digits, store that in a boolean called odd.
Take the first half of the number k, including the middle digit if odd is true, and store it in a variable called half.
808 -> 80
2133 -> 21
Mirror the half variable, taking care to not duplicate the middle digit if odd is true, and store it in a variable called mirror.
80 -> 808
21 -> 2112
Check if mirror > k
If true: you found your result
If false: increment half and start over from step 3.
(After maximum one increment you're guaranteed to have found your result.)
80 -> 81 -> 818
21 -> 22 -> 2222
Here's a JavaScript implementation for your reference:
const palin = (k) => {
const mirror = (half, odd) => half + Array.from(half).reverse().join('').substring(odd);
const s = k.toString();
const odd = s.length % 2;
const half = s.substring(0, Math.floor(s.length / 2) + odd);
let mirrored = mirror(half, odd);
if (+mirrored <= k) {
mirrored = mirror((+half + 1).toString(), odd);
}
return mirrored;
}
console.log(palin(5));
console.log(palin(808));
console.log(palin(2133));
Welcome to the site. What you have posted is commendable for someone who has only been using C for a month! Anyway ... I think your suspicion is correct. Using 'brute force' to find the next palindrome is probably the not to way go.
This question is as much about algorithm design as about C. Nonetheless, how you handle char[] representations of integers in C is interesting and relevant. FWIW, my attempt is pasted below.
It accepts a char[] representation of the number (n) and the number of digits (k) as arguments, and returns 1 on success or 0 on failure (another pass needed).
static int next_palindrome(char *n, size_t k) {
unsigned i = 0, carry = 0;
char tmp = 0;
int finished = 1;
for (i = 0; i < k; i++) {
if (carry) {
finished = 0;
*(n + k - i - 1) = *(n + k - i - 1) + 1;
if (*(n + k - i - 1) == 10) {
*(n + k - i - 1) = 0;
carry = 1;
} else
carry = 0;
continue;
}
if (i >= k / 2) continue;
if (*(n + k - i - 1) == *(n + i)) continue;
tmp = *(n + k - i - 1);
*(n + k - i - 1) = *(n + i);
if (tmp > *(n + i)) {
carry = 1;
}
}
return finished;
}
I have only tested it on numbers with < 64 digits so far, but have no reason to believe it will fail for larger numbers of digits.
Sample usage: http://codepad.org/3yyI9wEl
i build a program that translate base 10 ti base 2 and base 16:
#include <stdio.h>
int main(void)
{
int b10, b2, b16;
scanf("%d", &b10);//getting a number in base 10
b16 = b10;
b2 = b10;
//******print the number in base 2
int* ba2 = (int*)malloc(b10/2*4);
int i = 0,j;
while (b2 > 0){
ba2[i] = b2 % 2;
b2=b2 / 2;
i++;
}
for (j = i-1; j >= 0; j--){
printf("%d", ba2[j]);
}
free(ba2);
//**************************
//******print the number in base 16
printf("\n");
int* ba16 = (int*)malloc(b10 / 16 * 4);
i = 0;
while (b16 > 0){
ba16[i] = b16 % 16;
b16 = b16 / 16;
i++;
}
for (j = i - 1; j >= 0; j--){
if (ba16[j] < 10)
printf("%d", ba16[j]);
else
printf("%c", 'A' + (ba16[j] - 10));
}
free(ba16);
//****************************
getch();
return 0;
}
for some reason the program stop at the second free().
when i created a break point the program just stoped when i got to the free, no msg or warning.
can someone help me with is?
You are allocating memory as ba10/16 * 4. For input values less that 16, that evaluates to zero. As per malloc documentation, you will either get null pointer or a unique pointer which can be passed to free. But you are assigning values in ba16[0]. Same holds true for input value of 16. you have allocated 4 bytes. But the program goes on to assign ba16[0] and ba16[1], which will corrupt the array. The same problem exists with ba2 as well. I don't know if you tested with input values less than 16 or 2. Hope this helps.
I'm coding for a microcontroller-based application and I need to convert a float to a character string, but I do not need the heavy overhead associated with sprintf(). Is there any eloquent way to do this? I don't need too much. I only need 2 digits of precision.
Here's a version optimized for embedded systems that doesn't require any stdio or memset, and has low memory footprint. You're responsible for passing a char buffer initialized with zeros (with pointer p) where you want to store your string, and defining CHAR_BUFF_SIZE when you make said buffer (so the returned string will be null terminated).
static char * _float_to_char(float x, char *p) {
char *s = p + CHAR_BUFF_SIZE; // go to end of buffer
uint16_t decimals; // variable to store the decimals
int units; // variable to store the units (part to left of decimal place)
if (x < 0) { // take care of negative numbers
decimals = (int)(x * -100) % 100; // make 1000 for 3 decimals etc.
units = (int)(-1 * x);
} else { // positive numbers
decimals = (int)(x * 100) % 100;
units = (int)x;
}
*--s = (decimals % 10) + '0';
decimals /= 10; // repeat for as many decimal places as you need
*--s = (decimals % 10) + '0';
*--s = '.';
while (units > 0) {
*--s = (units % 10) + '0';
units /= 10;
}
if (x < 0) *--s = '-'; // unary minus sign for negative numbers
return s;
}
Tested on ARM Cortex M0 & M4. Rounds correctly.
Try this. It should be nice and small. I've output the string directly - doing a printf, rather than a sprintf. I'll leave it to you to allocate space for the return string, as well as copying the result into it.
// prints a number with 2 digits following the decimal place
// creates the string backwards, before printing it character-by-character from
// the end to the start
//
// Usage: myPrintf(270.458)
// Output: 270.45
void myPrintf(float fVal)
{
char result[100];
int dVal, dec, i;
fVal += 0.005; // added after a comment from Matt McNabb, see below.
dVal = fVal;
dec = (int)(fVal * 100) % 100;
memset(result, 0, 100);
result[0] = (dec % 10) + '0';
result[1] = (dec / 10) + '0';
result[2] = '.';
i = 3;
while (dVal > 0)
{
result[i] = (dVal % 10) + '0';
dVal /= 10;
i++;
}
for (i=strlen(result)-1; i>=0; i--)
putc(result[i], stdout);
}
// convert float to string one decimal digit at a time
// assumes float is < 65536 and ARRAYSIZE is big enough
// problem: it truncates numbers at size without rounding
// str is a char array to hold the result, float is the number to convert
// size is the number of decimal digits you want
void FloatToStringNew(char *str, float f, char size)
{
char pos; // position in string
char len; // length of decimal part of result
char* curr; // temp holder for next digit
int value; // decimal digit(s) to convert
pos = 0; // initialize pos, just to be sure
value = (int)f; // truncate the floating point number
itoa(value,str); // this is kinda dangerous depending on the length of str
// now str array has the digits before the decimal
if (f < 0 ) // handle negative numbers
{
f *= -1;
value *= -1;
}
len = strlen(str); // find out how big the integer part was
pos = len; // position the pointer to the end of the integer part
str[pos++] = '.'; // add decimal point to string
while(pos < (size + len + 1) ) // process remaining digits
{
f = f - (float)value; // hack off the whole part of the number
f *= 10; // move next digit over
value = (int)f; // get next digit
itoa(value, curr); // convert digit to string
str[pos++] = *curr; // add digit to result string and increment pointer
}
}
While you guys were answering I've come up with my own solution which that works better for my application and I figure I'd share. It doesn't convert the float to a string, but rather 8-bit integers. My range of numbers is very small (0-15) and always non-negative, so this will allow me to send the data over bluetooth to my android app.
//Assumes bytes* is at least 2-bytes long
void floatToBytes(byte_t* bytes, float flt)
{
bytes[1] = (byte_t) flt; //truncate whole numbers
flt = (flt - bytes[1])*100; //remove whole part of flt and shift 2 places over
bytes[0] = (byte_t) flt; //truncate the fractional part from the new "whole" part
}
//Example: 144.2345 -> bytes[1] = 144; -> bytes[0] = 23
I can't comment on enhzflep's response, but to handle negative numbers correctly (which the current version does not), you only need to add
if (fVal < 0) {
putc('-', stdout);
fVal = -fVal;
}
at the beginning of the function.
Its a Liitle large method, but It would work for both int and float, decimalPoint parameter is passed with zero value for Integer, Please let me know if you have smaller function than this.
void floatToStr(uint8_t *out, float x,int decimalPoint)
{
uint16_t absval = fabs(x);
uint16_t absvalcopy = absval;
int decimalcount = 0;
while(absvalcopy != 0)
{
absvalcopy /= 10;
decimalcount ++;
}
uint8_t *absbuffer = malloc(sizeof(uint8_t) * (decimalcount + decimalPoint + 1));
int absbufferindex = 0;
absvalcopy = absval;
uint8_t temp;
int i = 0;
for(i = decimalcount; i > 0; i--)
{
uint16_t frst1 = fabs((absvalcopy / pow(10.0, i-1)));
temp = (frst1 % 10) + 0x30;
*(absbuffer + absbufferindex) = temp;
absbufferindex++;
}
if(decimalPoint > 0)
{
*(absbuffer + absbufferindex) = '.';
absbufferindex ++;
//------------------- Decimal Extractor ---------------------//
for(i = 1; i < decimalPoint + 1; i++)
{
uint32_t valueFloat = (x - (float)absval)*pow(10,i);
*(absbuffer + absbufferindex) = ((valueFloat) % 10) + 0x30;
absbufferindex++;
}
}
for(i=0; i< (decimalcount + decimalPoint + 1); i++)
{
*(out + i) = *(absbuffer + i);
}
i=0;
if(decimalPoint > 0)
i = 1;
*(out + decimalcount + decimalPoint + i) = 0;
}
I do not know why, gcc version 4.9.2 (Ubuntu 4.9.2-10ubuntu13 x86_64)
Breakpoint 1, convertToTitle (n=1000000001) at excel_sheet_column_title.c:14
14 printf("%d\n", n);
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400697 in convertToTitle (n=1000000001) at excel_sheet_column_title.c:14
14 printf("%d\n", n);
(gdb) p n
$1 = 1000000001
The complete code of the function, just called the function with 1000000001 in the main function:
char *convertToTitle(int n)
{
int mod, idx, last = n / 26 + 1;
char str[last], *title, *tp;
printf("%d\n", n);
idx = last;
while (n > 26) {
mod = n % 26;
if (mod > 0) {
str[--idx] = mod - 1 + 'A';
} else if (mod == 0) {
str[--idx] = 'Z';
n -= 1;
}
n /= 26;
}
if (n > 0) {
str[--idx] = n - 1 + 'A';
}
title = (char *)malloc((last - idx + 1) * sizeof(char));
tp = title;
for (; idx < last; idx++) {
*tp++ = str[idx];
}
*tp = '\0';
return title;
}
Your last is very large. Move it outside of local function (or mark it static) to avoid segfault.
As an alternative (and correct) solution, calculate correct value of last.
(I think you wanted log26n + 1)
26last >= nlast = log26n
last = ceil(log(n) / log(26)) + 1;
Weak calculation of needed buffer size for str[] resulted in an excessively large array size last of 1000000001/26 + 1. This array size was unsupportable as coded as a local variable.
What is needed is a much smaller array about log26(n).
There is little need to "right-size" the buffer per various values of int n. Simply use a constant size that works for INT_MAX.
As the bit size of an int is about log2(INT_MAX)+1,
#include <limits.h>
#define ABOUT_LOG2_26 4.7
#define BUF26_SIZE ((int)(sizeof(int)*CHAR_BIT/ABOUT_LOG2_26 + 2))
char *convertToTitle(int n) {
char str[BUF26_SIZE];
...
// Also cope with negative values of n
if (n < 0) Handle_Error();