How to use 'fwrite' in C? - c

I'm trying to use 'fwrite' and make snd files.
I want to make IIR Filter. I made a FIR Filter and i use the codes to IIR Filter.
(of course, change coeffs)
But I think 'fwrite' doesn't work. Because the result of IIR filter is only zero.
I think I did some mistakes in my code.
Can you give me a hint? i'm totally in panic now.
When I check output[], it looks fine. It has group of integer, as i respect.
I don't know how to write it.
I know the code is so long and looks difficult.
But I have no idea so if you give me a hand, it would be pleasured.
Thanks for reading.
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
// Filter Code Definitions
#define MAX_INPUT_LEN 80
#define MAX_FLT_LEN 14
#define BUFFER_LEN (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
double insamp[BUFFER_LEN];
// IIR inititialization
void IirFloatInit(void)
{
memset(insamp, 0, sizeof(insamp));
}
// the IIR filter function
void IirFloat(double *coeffs, double *input, double *output, int length, int
filterLength)
{
double acc;
double *coeffp;
double *inputp;
int n;
int k;
// put the new samples at the high end of the buffer
memcpy(&insamp[filterLength - 1], input, length * sizeof(double));
for (n = 0; n < length; n++) {
coeffp = coeffs;
inputp = &insamp[filterLength - 1 + n];
acc = 0;
for (k = 0; k < filterLength; k++) {
acc += (*coeffp++) * (*inputp--);
}
output[n] = acc;
}
memmove(&insamp[0], &insamp[length], (filterLength - 1) * sizeof(double));
}
double coeffs[MAX_FLT_LEN];
void intToFloat(int16_t *input, double *output, int length)
{
int i;
for (i = 0; i < length; i++) {
output[i] = (double)input[i];
}
}
void floatToInt(double *input, int16_t *output, int length)
{
int i;
for (i = 0; i < length; i++)
{
input[i] += 0.5;
if (input[i] > 32767.0)
{
input[i] = 32767.0;
}
else if (input[i] < -32768.0)
{
input[i] = -32768.0;
}
output[i] = (int16_t)input[i];
}
}
// number of samples to read per loop
int main(void)
{
int size;
int16_t input[MAX_INPUT_LEN];
int16_t output[MAX_INPUT_LEN];
double floatInput[MAX_INPUT_LEN];
double floatOutput[MAX_INPUT_LEN];
double coeffs[MAX_FLT_LEN];
FILE *in_fid;
FILE *out_fid;
FILE *filter;
// open the input waveform file
in_fid = fopen("input.snd", "rb");
if (in_fid == 0) {
printf("couldn't open input.snd");
return;
}
// open the output waveform file
out_fid = fopen("outputFloatIIR.snd", "wb");
if (out_fid == 0) {
printf("couldn't open outputFloat.snd");
return;
}
filter = fopen("coeffs_iir.txt", "r");
if (filter == NULL) {
puts("couldn't open coeffs_iir.txt");
return;
}
for (int i = 0; i < MAX_FLT_LEN; i++) {
fscanf(filter, "%le", &coeffs[i]);
printf("%le \n", coeffs[i]);
}
IirFloatInit();
do {
size = fread(input, sizeof(int16_t), MAX_INPUT_LEN, in_fid);
intToFloat(input, floatInput, size);
IirFloat(coeffs, floatInput, floatOutput, size, MAX_FLT_LEN);
floatToInt(floatOutput, output, size);
fwrite(output, sizeof(int16_t), size, out_fid);
} while (size != 0);
fclose(in_fid);
fclose(out_fid);
fclose(filter);
getchar();
return 0;
}

Into the manual (man printf) I can read this:
eE The double argument is rounded and converted in the style [-]d.ddde+-dd where there is one digit before the decimal-point
character and the number of digits after it is equal to the precision;
if the
precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the
letter E' (rather thane') to introduce the exponent. The exponent
always contains at least two digits; if the value is zero, the exponent is 00.
Into your file where coefficients are stored, are into that format? If you use a debugger, what happen with the value read into fscanf?
I mean, probably the format is not the expected and because of that you get 0. Maybe you want to use fscanf(filter, "%lf", &coeffs[i]); ?
What is the value returned by fscanf? Into the manual (man fscanf) can be read this:
RETURN VALUES
These functions return the number of input items assigned. This can be fewer than provided for, or even zero, in the event of a
matching failure. Zero indicates that, although there was input
available, no
conversions were assigned; typically this is due to an invalid input character, such as an alphabetic character for a `%d'
conversion. The value EOF is returned if an input failure occurs
before any conver-
sion such as an end-of-file occurs. If an error or end-of-file occurs after conversion has begun, the number of conversions which
were successfully completed is returned.

Related

Not able to print this 2D array (weird output) in C

I am trying to read a text file with 100 numbers like 1 2 45 55 100 text file here (all on a single line) and then put them in a 10x10 array (2D array).
736.2 731.6 829.8 875.8 568.3 292.2 231.1 868.9 66.7 811.9 292.0 967.6 419.3 578.1 322.5 471.7 980.0 378.8 784.1 116.8 900.4 355.3 645.7 603.6 409.1 652.1 144.1 590.6 953.1 954.0 502.0 689.3 685.6 331.9 565.1 253.9 624.1 796.2 122.8 690.7 608.0 414.8 658.3 27.3 992.9 980.8 499.0 972.8 359.7 283.1 89.7 260.1 638.4 735.4 863.6 47.5 387.5 7.7 638.1 340.6 961.7 140.1 29.8 647.3 471.9 594.9 901.2 96.0 391.1 24.0 786.7 999.1 438.7 445.0 26.4 431.6 425.9 525.4 404.4 785.6 808.5 494.1 45.7 447.0 229.5 909.3 494.4 617.0 917.0 132.5 957.5 878.8 272.6 987.4 526.1 744.5 582.3 427.3 840.5 973.3
Here is my code:
#include <stdio.h>
#define NR 10
#define NC 10
int main(void) {
int numbers[9][9];
int i = 0;
int count;
int j = 0;
FILE *file;
file = fopen("numbers.txt", "r");
for (count = 1; count < 101; count++) {
fscanf(file, "%d", &numbers[i][j]);
j++;
if ((count != 1) && (count % 10 == 0)) {
i++;
j = 0;
}
}
fclose(file);
int p = 0;
int q = 0;
for (p = 0; p < NR; p++) {
for (q = 0; q < NC; q++) {
printf("%d", numbers[p][q]);
}
printf("\n");
}
return 0;
}
As SparKot noted in a comment, to read a 10x10 matrix, you need to define the matrix with 10x10 elements:
int numbers[10][10];
That has to be one of the weirder ways of reading a 10x10 matrix that I've ever seen. Why not go for a simple approach of nested loops. Since the data contains floating-point numbers, you need to read them as double (or perhaps float) values.
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
double double_val;
if (fscanf(file, "%lf", &double_val) != 1)
{
fprintf(stderr, "failed to read matrix[i][j]\n", i, j);
exit(EXIT_FAILURE);
}
numbers[i][j] = double_val;
}
}
The mess with double_val works around the data containing floating point numbers and your original code trying to read integers. You'll get one valid value; thereafter, fscanf() will return 0 because the . is not a part of a valid integer. This highlights the importance of checking the return value from fscanf() and its relatives.
Frankly, you should be using double numbers[10][10]; for the data from the file. Then you could read directly into the array:
if (fscanf("%lf", &numbers[i][j]) != 1)
But you'd need to check (and probably change) all the rest of the code too.
There are multiple issues in your code:
the matrix is too small, make it numbers[NR][NC].
you do not check for fopen failure: you will have undefined behavior if the file numbers.txt is not in the current directory or cannot be open for reading.
you read the file contents as integers, but the file contains floating point numbers with a . decimal separator: the second and subsequent fscanf() will get stuck on the . and keep returning 0 without modifying the destination number, leaving the matrix mostly uninitialized. Make the matrix double numbers[NR][NC], read the numbers with %lf and test for conversion failure.
the counting method in the reading loop is weird. Just use 2 nested for loops with proper counter and tests.
printing the matrix contents, you should output at least a space between numbers so the output is readable.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define NR 10
#define NC 10
int main() {
double numbers[NR][NC];
FILE *file;
file = fopen("numbers.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open numbers.txt: %s\n", strerror(errno));
return 1;
}
for (int i = 0; i < NR; i++) {
for (int j = 0; j < NC; j++) {
if (fscanf(file, "%lf", &numbers[i][j]) != 1) {
fprintf(stderr, "error reading number at row %d, col %d\n",
i + 1, j + 1);
fclose(file);
return 1;
}
}
}
fclose(file);
for (int p = 0; p < NR; p++) {
for (int q = 0; q < NC; q++) {
printf(" %5g", numbers[p][q]);
}
printf("\n");
}
return 0;
}
Clear all a common condition that causes programs to crash; they are often associated with a file named core.
code is showing segmentation fault.

Converting negative decimal to two's complement in C

I'm writing a program that, assuming the input is always a valid negative decimal integer, returns the two's complement binary representation (16 bit).
My logic here is that I take in inputs from the command line, and convert that with a simple conversion to binary and add them to the initialized binary array. Then, I take the one's complement (just change 0's to 1's and vise versa) and put that in the onesCom array. However, for the adding 1 part to find the two's complement, I think this is where the issue is but I'm struggling to find it. I am performing binary addition to the least significant bit.
When converting from one-complement to two-complement, i.e. adding 1, your loop should start from the LSB, not from the MSB.
Therefore,
for (j=15; j>=0; j--) { // <-- Error Here
if (onesCom[j] == 1 && carryOver == 1) {
twosCom[j] = 0;
} else if (onesCom[j] == 0 && carryOver == 1) {
twosCom[j] = 1;
carryOver = 0;
} else {
twosCom[j] = onesCom[j];
}
}
Should be replaced by:
for (j=0; j<=15; j++) {
if (onesCom[j] == 1 && carryOver == 1) {
twosCom[j] = 0;
} else if (onesCom[j] == 0 && carryOver == 1) {
twosCom[j] = 1;
carryOver = 0;
} else {
twosCom[j] = onesCom[j];
}
}
In your code, you calculate the one-complement then deduce the two-complement. Please note that it is easier to directly calculate the two-complement, in case you don't need the one-complement, like this:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int binary[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
if (argc == 1) return 1;
int decimal = atoi(argv[1]);
int counter = 0;
if (decimal > -32768 && decimal < 0) {
decimal = 65536 + decimal;
while(decimal > 0) {
binary[counter] = decimal%2;
decimal = decimal/2;
counter++;
}
for (int length = 15; length >=0; length--) {
printf("%d", binary[length]);
}
printf ("\n");
}
return 0;
}
As your snippet is completely blurred, I can only suggest you two approaches to the problem:
The first assuming you are doing two's complement arithmethic all the time, in which case the digit adding must be done with sign.
The second assuming you only parse unsigned values and retaining the sign to make the sign exchange at the end.
Probably both approaches will lead to almost the same efficiency and be compiled into very similar code. I have no preference for any of them.
int decode(char *str, int base)
{
int result = 0,
c,
neg = FALSE;
/* skip whitespace, delete this if you don't
* want to cope with whitespace */
for (; isspace(c = *str); str++) {
continue;
}
if (*str == '-') {
neg = TRUE; /* negative */
str++; /* skip it */
}
/* the next characters might be all digits */
for (; isdigit(c = *str); str++) {
/* multiply by the base */
result *= base;
/* add positive for positives and
* subtract it for negatives */
int d = c - '0'; /* convert c to the digit value */
/* negative if number is negative */
if (neg) d = -d;
/* and add/subtract it */
result = result + d;
}
/* :) got it!! */
return result;
}
and the second approach is:
int decode(char *str, int base)
{
int result = 0,
c,
neg = FALSE;
/* skip whitespace, delete this if you don't
* want to cope with whitespace */
for (; isspace(c = *str); str++) {
continue;
}
if (*str == '-') {
neg = TRUE; /* negative */
str++; /* skip it */
}
/* the next characters might be all digits */
for (; isdigit(c = *str); str++) {
/* multiply by the base */
result *= base;
/* add positive for positives and
* subtract it for negatives */
int d = c - '0'; /* convert c to the digit value */
/* and add/subtract it */
result = result + d;
}
/* :) got it!! */
return neg ? -result : result;
}
Can you see the differences? (hint, I have eliminated one line in the loop and changed one line at the end :) )
If you want to run this code in a full, complete and verifiable example, there's one below, just put one of the above functions in place of the other, and run it.
#include <stdio.h>
#include <ctype.h>
/* these macros are for easy printing, and outputting the file, line and
* function name where the trace is being made */
#define F(_f) __FILE__":%d:%s:"_f, __LINE__, __func__
#define P(_f, ...) printf(F(_f), ##__VA_ARGS__)
/* I use these for portability, as <stdbool.h> is not always available */
#define FALSE (0)
#define TRUE (!FALSE)
int decode(char *str, int base)
{
/* substitute here the body of the function above you want to test */
}
int main()
{
static char *tests[] = {
"0", "-1", "-210", "-211", "-222", "1",
"210", "211", "222", "5400",
/* add more testing cases to your wish */
NULL,
};
int i, passed = 0;
for (i = 0; tests[i]; i++) {
char *test = tests[i];
int expected, actual;
P("Testing '%s' conversion\n", test);
/* expected, decoded with system routines */
if (sscanf(test, "%i", &expected) != 1) {
P("problem scanning %s\n", test);
continue;
}
/* actual, decoded with our function */
actual = decode(test, 10);
char *operator = actual == expected ? "==" : "!=";
P("Test result: actual(%i) %s expected(%i)\n",
actual, operator, expected);
if (actual == expected)
passed++;
}
P("passed %d/%d tests\n", passed, i);
}
Edit
The following code will allow you to easily convert your value to binary:
#define CHK(_n) ((_n) <= sz)
char *to_binary(int p_val, char *buf, size_t sz)
{
CHK(2); /* at least two bytes of buffer space */
buf += sz; /* we start from the end, backwards to avoid having to use
* one bit masks moving all the time around */
*--buf = '\0'; /* this is the last '\0' that should end the string */
sz--; /* update buffer size */
/* we operate better with unsigned, as the
* sign doesn't get involved in shifts (we are reinterpreting
* the sign bit as a normal bit, which makes the assumption that
* integers are stored in two's complement. This is essentially
* nonportable code, but it will work in the stated assumptions. */
unsigned val = (unsigned) p_val;
/* the first below is the second char we check
* above */
do {
*--buf = val & 1 ? '1' : '0';
sz--;
val >>= 1;
} while (CHK(1) && val);
return buf; /* return what we have */
}
And the final main() code looks like this:
int main()
{
static char *tests[] = {
"0", "-1", "-210", "-211", "-222", "1",
"210", "211", "222", "5400",
NULL,
};
int i, passed = 0;
for (i = 0; tests[i]; i++) {
char *test = tests[i];
int expected, actual;
P("Testing '%s' conversion\n", test);
/* expected, decoded with system routines */
if (sscanf(test, "%i", &expected) != 1) {
P("problem scanning %s\n", test);
continue;
}
/* actual, decoded with our function */
actual = decode(test, 10);
char *operator = actual == expected ? "==" : "!=";
char buff[100]; /* temporary variable to hold the
* converted value to binary */
P("Test result: actual(%i/0b%s)\n",
actual,
to_binary(actual, buff, sizeof buff));
P(" %s expected(%i/0b%s)\n",
operator,
expected,
to_binary(expected, buff, sizeof buff));
if (actual == expected)
passed++;
}
P("passed %d/%d tests\n", passed, i);
}

Boyer Moore replace more than one pattern

I am working on a string search and replace project. I can only change 1 of the target pattern in the sentence. But I can find both.
Example: just do it. you will do it.
find: do
replace: think
expected---> just think it. you will think it.
what actually happened ---> just do it. you will think it.
How can I replace both of them?
I read the sentence from file input.txt
# include <limits.h>
# include <string.h>
# include <stdio.h>
#include <sys/time.h>
# define NO_OF_CHARS 256
# define MAX 10000
int sum = 0;
int control = 0;
// A utility function to get maximum of two integers
int max (int a, int b) { return (a > b)? a: b; }
// The preprocessing function for Boyer Moore's bad character heuristic
void badCharHeuristic( char *str, int size, int badchar[NO_OF_CHARS]) {
int i;
// Initialize all occurrences as -1
for (i = 0; i < NO_OF_CHARS; i++)
badchar[i] = -1;
// Fill the actual value of last occurrence of a character
for (i = 0; i < size; i++)
badchar[(int) str[i]] = i;
}
/* A pattern searching function that uses Bad Character Heuristic of Boyer Moore Algorithm */
void search( char *txt, char *pat,char temp3[MAX],int k,char*r) {
int m = strlen(pat);
int n = strlen(txt);
char src[MAX],p[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int badchar[NO_OF_CHARS],i,leng,l,count;
char v;
/* Fill the bad character array by calling the preprocessing function badCharHeuristic() for given pattern */
badCharHeuristic(pat, m, badchar);
leng = strlen(pat);
strcpy(tempP,r);
//strcat(tempP,"</mark>");
leng = strlen(pat);
l = strlen(txt);
int s = 0; // s is shift of the pattern with respect to text
while(s <= (n - m)) {
int j = m-1;
/* Keep reducing index j of pattern while characters of pattern and text are matching at this shift s */
while(j >= 0 && pat[j] == txt[s+j]) {
count++;
j--;
}
/* If the pattern is present at current shift, then index j will become -1 after the above loop */
if (j < 0) {
//printf("pattern occurs at shift = %d\n", s);
/* Shift the pattern so that the next character in text
aligns with the last occurrence of it in pattern.
The condition s+m < n is necessary for the case when
pattern occurs at the end of text */
printf("The desired pattern was found starting from %d. line at position %d\n",k,s+1);
strncpy(temp, txt, s);
temp[s] = '\0';
//strcat(temp,"<mark>");
control++;
strcat(temp,tempP);
for(i=0;i<MAX;i++) {
if((s+leng+i)<strlen(txt))
temp2[i] = txt[s+leng+i];
else
temp2[i] = v;
}
strcat(temp,temp2);
strcpy(temp3,temp);
s += (s+m < n)? m-badchar[txt[s+m]] : 1;
}
else
/* Shift the pattern so that the bad character in text
aligns with the last occurrence of it in pattern. The
max function is used to make sure that we get a positive
shift. We may get a negative shift if the last occurrence
of bad character in pattern is on the right side of the
current character. */
s += max(1, j - badchar[txt[s+j]]);
}
sum +=count;
}
/* Driver program to test above funtion */
int main() {
char txt[MAX],p[MAX],r[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int k = 1;
FILE *input = fopen("input.txt","r");
FILE *output = fopen("output.txt","w");
printf("Enter the text in which pattern is to be searched:");
fgets(p, MAX, stdin);
printf("Enter the text in which pattern is to be replaced:");
fgets(r, MAX, stdin);
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
p[strlen(p)-1]='\0';
temp[1]='a';
while(!feof(input)){
if(fgets (txt, MAX, input)!=NULL) {
txt[strlen(txt)-1] = '\0';
search(txt, p,temp,k,r);
if(temp[1]!='a') {
fprintf(output,"%s\n",temp);
temp[1]='a';
}
else
fprintf(output,"%s\n",txt);
}
k++;
}
if(control==0) {
printf("\nThe pattern was not found in the given text\n\n");
}
gettimeofday(&tv2, NULL);
printf ("Total time = %f seconds\n", (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 + (double) (tv2.tv_sec - tv1.tv_sec));
fclose(input);
fclose(output);
printf("The number of character comparison: %d\n",sum);
return 0;
}

Stack around the variable 'ch' was corrupted

I am in the process of writing a decipher algorithm for Vegenere Variant Cipher and ran into some C specific issues(I am not too familiar with C).
I get
"Run-Time Check Failure #2 - Stack around the variable 'ch' was corrupted" error.
If I understand the error right, ch is not available when I try to read/write to it(ch in this case represents a HEX value read from the text file, I have posted the code of the function below).
But, for the life of me, I can't figure out where it happens. I close the file way before the I exit the function(exception is thrown at the time I leave the function).
Can you take a look an let me know where I have it wrong? Thanks in advance.
P.S. I am tagging the question with C++ as well as it should pretty much be the same except, maybe, how we read the file in.
Anyways, my code below:
int getKeyLength(char *cipherTxtF){
int potKeyL = 1;
float maxFreq = 0.00;
int winKL = 1;
for (potKeyL = 1; potKeyL <= 13; potKeyL++)// loop that is going through each key size startig at 1 and ending at 13
{
unsigned char ch;
FILE *cipherTxtFi;
cipherTxtFi = fopen(cipherTxtF, "r");
int fileCharCount = 0;
int freqCounter[256] = { 0 };
int nThCharCount = 0;
while (fscanf(cipherTxtFi, "%02X", &ch) != EOF) {
if (ch != '\n') {
if (fileCharCount % potKeyL == 0){
int asciiInd = (int)ch;
freqCounter[asciiInd] += 1;
nThCharCount++;
}
}
fileCharCount++;
}
fclose(cipherTxtFi);
float frequenciesArray[256] = { 0 };
float sumq_iSq = 0;
int k;
for (k = 0; k < 256; k++){
frequenciesArray[k] = freqCounter[k] / (float)nThCharCount;
}
for (k = 0; k < 256; k++){
sumq_iSq += frequenciesArray[k] * frequenciesArray[k];
printf("%f \n", sumq_iSq);
}
if (maxFreq < sumq_iSq) {
maxFreq = sumq_iSq;
winKL = potKeyL;
}
}
return winKL;
}
You are trying to read an hexadecimal integer with fscanf() (format "%02X", where X means "integer in hex format") and store it into a char.
Unfortuantely fscanf() just receives the address of the char and doesn't know that you've not provided the address of an int. As int is larger than a char, the memory gets corrupted.
A solution could be:
int myhex;
while (fscanf(cipherTxtFi, "%02X", &myhex) != EOF) {
ch = myhex;
...

Decimal to Binary conversion not working

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int myatoi(const char* string) {
int i = 0;
while (*string) {
i = (i << 3) + (i<<1) + (*string -'0');
string++;
}
return i;
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
long int dec = myatoi(decimal);
long int fraction;
long int remainder;
long int factor = 1;
long int fractionfactor = .1;
long int wholenum;
long int bin;
long int onechecker;
wholenum = (int) dec;
fraction = dec - wholenum;
while (wholenum != 0 ) {
remainder = wholenum % 2; // get remainder
bin = bin + remainder * factor; // store the binary as you get remainder
wholenum /= 2; // divide by 2
factor *= 10; // times by 10 so it goes to the next digit
}
long int binaryfrac = 0;
int i;
for (i = 0; i < 10; i++) {
fraction *= 2; // times by two first
onechecker = fraction; // onechecker is for checking if greater than one
binaryfrac += fractionfactor * onechecker; // store into binary as you go
if (onechecker == 1) {
fraction -= onechecker; // if greater than 1 subtract the 1
}
fractionfactor /= 10;
}
bin += binaryfrac;
*binary = bin;
free(decimal);
}
int main(int argc, char **argv) {
char *data;
data = malloc(sizeof(char) * 32);
int datai = 1;
if (argc != 4) {
printf("invalid number of arguments\n");
return 1;
}
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
free(data);
return 0;
}
In this problem, myatoi works fine and the decimal2binary algorithm is correct, but every time I run the code it gives my output as 0. I do not know why. Is it a problem with pointers? I already set the address of variable data but the output still doesn't change.
./dec2bin "-d" "23" "-b"
The line:
long int fractionfactor = .1;
will set fractionfactor to 0 because the variable is defined as an integer. Try using a float or double instead.
Similarly,
long int dec = myatoi(decimal);
stores an integer value, so wholenum is unnecessary.
Instead of
i = (i << 3) + (i<<1) + (*string -'0');
the code will be much more readable as
i = i * 10 + (*string - '0');
and, with today's optimizing compilers, both versions will likely generate the same object code. In general, especially when your code isn't working, favor readability over optimization.
fraction *= 2; // times by two first
Comments like this, that simply translate code to English, are unnecessary unless you're using the language in an unusual way. You can assume the reader is familiar with the language; it's far more helpful to explain your reasoning instead.
Another coding tip: instead of writing
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
you can refactor the nested if blocks to make them simpler and easier to understand. In general it's a good idea to check for error conditions early, to separate the error-checking from the core processing, and to explain errors as specifically as possible so the user will know how to correct them.
If you do this, it may also be easier to realize that both of the original conditions should be negated:
if (strcmp(argv[1], "-d") != 0) {
printf("Error: first parameter must be -d\n");
else if (strcmp(argv[3], "-b") != 0) {
printf("Error: third parameter must be -b\n");
} else {
decimal2binary(argv[2], &datai);
printf("Output is: %d\n" , datai);
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
...
}
The above lines of code allocate a new block of memory to decimal, which will then no longer point to the input data. Then the line
long int dec = myatoi(decimal);
assigns the (random values in the) newly-allocated memory to dec.
So remove the line
decimal = malloc(sizeof(char) * 32);
and you will get the correct answer.
if(!strcmp(argv[3] , "-b"))
if(!strcmp(argv[3] , "-d"))
The result of the string compare function should be negated so that you can proceed. Else it will print invalid parameter. Because the strcmp returns '0' when the string is equal.
In the 'decimal2binary' function you are allocating a new memory block inside the function for the input parameter 'decimal',
decimal = malloc(sizeof(char) * 32);
This would actually overwrite your input parameter data.

Resources