I'm making a program to add/sub/mult numbers from bin/oct/dec/hex format and output in whatever base the user asks, run syntax:

./instruction <num1> <num2> <base1> <base2> <output base>

and, besides the stupid implicit declaration warnings I get for some unknown reason (I'd love to know why), when I run this (I'm just trying to test conversion from dec to binary right now) I get an "Illegal Instruction" error when I try and reverse the temporary array and dump it into the answer array. What's wrong with it?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

void toNeg(int num);

int main(int argc, char *argv[]){

	int x = 0, y = 0, base1, base2, outbase;
	char num1[32], num2[32], bin1[32], bin2[32];
	/*unsigned int unum1, unum2, neg1, neg2;*/

	if(strcmp(argv[0],"./add"))	x = 0;
	else if (strcmp(argv[0],"./sub")){
		x = 0;
		y = 1;
	}else if (strcmp(argv[0],"./mult")) x = 1;
	else x = 2;


	/* 0 = dec, 1 = bin, 2 = hex, 3 = oct */

	base1 = checkBase(argv[3]);			/*implicit declaration?*/
	base2 = checkBase(argv[4]);
	outbase = checkBase(argv[5]);

	if(base1 == -1 || base2 == -1 || outbase == -1){
		fprintf(stderr, "One or more of the arguments entered is invalid\n");
		exit(1);
	}

	strcpy(num1, argv[1]);
	strcpy(num2, argv[2]);

	printf("dec: %s\n",num1);

	toBin(num1, base1, bin1);			/*implicit declaration?*/
	toBin(num2, base2, bin2);

	printf("bin: %s\n",bin1);

	switch(x){
	case 0:
		if(y == 1){
			/*toNeg(unum2);*/
		}
	}

	return 0;
}

int checkBase(char str[]){
	if(strcmp("dec", str)==0){
		return 0;
	}else if(strcmp("bin", str)==0){
		return 1;
	}else if(strcmp("hex", str)==0){
		return 2;
	}else if(strcmp("oct", str)==0){
		return 3;
	}
	return -1;
}

/**************/

void toBin(char *num, int base, char *bin){		/*conflicting types for toBin?*/
	char temp[32];
	int old;
	unsigned int i=0, j=0, n, remain;

	n = atoi(num);

	if(base == 0){
		do{
			old = n;
			remain = n%2;
			n = n/2;
			printf("%d/2 = %d  remainder = %d\n", old, n, remain);
			temp[i++] = remain + '0';
			printf("%s\n",temp);
		}while(n > 0);


		/*reverse*/
		while(i >= 0) bin[j++] = temp[--i]; /*<-------THIS!!!---*/
	}else if(base == 2){

	}
}

Edited 6 Years Ago by mi.mac.rules: n/a

The implicit declarations aren't stupid. They are telling you that since you didn't provide prototypes of those functions at the beginning of your program, the compiler had to guess what their signatures are.

I didn't try to run your program but I assume the "illegal instruction" error you get is a runtime error, is that correct? Maybe because i is the length of the bin string and when i has been reduced to 0, you still enter the while loop and attempt to store one more character at position temp[-1]. You probably want:

while(i > 0)

I haven't tested this code, I just threw it together in a few minutes. It should do everything you need, and its extremely efficient.

The parameters would be like this:

./program <Number #1 hex/int/bin/oct> <Number #1> <div/add/mul/sub> <Number #2 hex/int/bin/oct> <Number #2> <Result hex/int/bin/oct>

Its not a fix to your program, but I figured this model could be a start to a better design for your app.

int num[2], Result;
char Temp[256];
char *format;

// Read and convert numbers
for (int t=0;t<2;t++) 
  switch (argv[t*3][0]) {
     // Convert Hex to Int
     case 'h': sscanf(argv[(t*3)+1], "%x", &num[t]); break;
     // Convert Octal to Int
     case 'o': sscanf(argv[(t*3)+1], "%o", &num[t]); break;
     // Read an Int
     case 'i': sscanf(argv[(t*3)+1], "%d", &num[t]); break;
     // Convert Binary to Int
     case 'b': {
         num[t] = 0;
         sscanf(argv[(t*3)+1], "%s", Temp); 
         for (i=strlen(Temp)-1;i>=0;i--)
            if (Temp[i]=='1') {
                num[t]  |= 1;
                num[t] <<= 1;
            }
     } break;
  }

// Do math
switch (argv[2][0]) {
  // divide
  case 'd': Result = num[0] / num[1]; break;
  // multiply
  case 'm': Result = num[0] * num[1]; break;
  // add
  case 'a': Result = num[0] + num[1]; break;
  // subtract
  case 's': Result = num[0] - num[1]; break;
}

// Display Result
switch (argv[5][0]) {
  case 'd': printf("\nResult in Integer: %d\n", Result); break;
  case 'h': printf("\nResult in Hex: %x\n", Result); break;
  case 'o': printf("\nResult in Octal: %o\n", Result); break;
  case 'b': 
    printf("\nResult in Binary: ");
    for (;Result==0;) {
       if (Result & 1) printf("1");
       else printf("0");
       Result >>= 1;
    }
    printf("\n");
  break;
}

A few corrections:

Line 40 should be case 'i', not case 'd'.

Line 45 should be Result!=0, not Result==0.

Edited 6 Years Ago by N1GHTS: n/a

Thanks @N1GHTS, that was somewhat helpful - I'm not sure how your binary conversions worked, as I just started working with C recently. What is the

char *format

for? And I'm really not sure what reference is made when you say argv[x][y] - argv is two-dimensional?

Since I made this in a hurry, I programed it assuming I was going to use a format pointer, but I didn't need it. So your right, its useless.

As for the argv[x][y] thing, if your first parameter was "hex", then arv[0][1] would be 'e', the second letter of the first parameter. Therefore, its argv[param count][character]

By the way, I just caught a few errors with the code, specifically in the binary conversion sections. Simple mistakes. I will now repost the code with all the corrections including some additional comments to help you understand what I am actually doing. Thanks for your patience.

int num[2],     // Where we will store both numbers
    Result;     // Where the result is stored
char Temp[256]; // Used in the binary conversions
int t, i;       // Loop iterators

// Read and convert numbers.
//
// We are dealing with 2 parameters,
// so loop through them
for (t=0;t<2;t++) 

  // Grab the first letter of parameter 0,
  // then parameter 3
  switch (argv[t*3][0]) {

     // Convert Hex to Int
     case 'h': sscanf(argv[(t*3)+1], "%x", &num[t]); break;

     // Convert Octal to Int
     case 'o': sscanf(argv[(t*3)+1], "%o", &num[t]); break;

     // Read an Int
     case 'i': sscanf(argv[(t*3)+1], "%d", &num[t]); break;

     // Convert Binary to Int
     case 'b': {

         // Start the converted number at zero
         num[t] = 0;

         // Grab the binary string
         sscanf(argv[(t*3)+1], "%s", Temp); 

         // loop through the binary string in reverse order
         // since the least significant digit is on the
         // right side.
         for (i=strlen(Temp)-1;i>=0;i--) {

            // If the current character is a '1'...
            if (Temp[i]=='1') 
                num[t]  |= 1;  // Set the least significant bit to 1
            
            // Shift the entire number to the left by 1
            num[t] <<= 1; 
         }
            
     } break;
  }

// Do math
switch (argv[2][0]) {
  // divide
  case 'i': Result = num[0] / num[1]; break;
  // multiply
  case 'm': Result = num[0] * num[1]; break;
  // add
  case 'a': Result = num[0] + num[1]; break;
  // subtract
  case 's': Result = num[0] - num[1]; break;
}

// Display Result
switch (argv[5][0]) {
  case 'i': printf("\nResult in Integer: %d\n", Result); break;
  case 'h': printf("\nResult in Hex: %x\n", Result); break;
  case 'o': printf("\nResult in Octal: %o\n", Result); break;
  case 'b': 
    printf("\nResult in Binary: ");

    // Clear the Temp buffer
    Temp[0] = '\0';

    // The number in Result will be 'eaten up' by our conversion,
    // so loop forever until Result is zero
    for (;Result!=0;) {

       // Convert the least significant bit to a string digit and
       // append it to Temp. This will load in reverse order, but
       // we will fix it later
       strcat(Temp, (Result & 1)?"1":"0");

       // Now that we finished dealing with this digit, shift it
       // out of the result so we can perform the conversion on 
       // the next bit.
       Result >>= 1;
    }

    // Print the binary result on the screen, but since it is stored
    // in reverse order, print it in reverse order to correct the
    // order of the digits.
    for (t=strlen(Temp)-1; t>=0; t--)
       printf("%c", Temp[t]);

    // newline
    printf("\n");
  break;
}

Edited 6 Years Ago by N1GHTS: n/a

Comments
Thanks, you were a lot of help.

the way i'm doing it, and the way it's supposed to be done, is to store the binary in an array of 1's and 0's (for overflow checking and such when adding), and I'm having a lot of trouble converting hex to binary. i used your sscanf technique to convert a read hex to an int, but i need to convert that to a binary and store it in an array, like [1][1][0][1] for 13... i tried making my technique work with your's, but it tells me i can't do that

void hex2bin(char *num, char *bin){
	char temp[33];
	unsigned int i=0, j = 0, m, n;

	sscanf(num, "%x", &n);

	temp[0] = '\0';

	for(;n != 0;){
		strcat(temp, (n & 1)?"1":"0");
		n >>= 1;
	}

	for(i = strlen(temp)-1; n>=0; i--) bin[j++] = temp[i];
}

Edited 6 Years Ago by mi.mac.rules: n/a

bug fix:

for(i = strlen(temp)-1; i>=0; i--) bin[j++] = temp[i];

You might also want to copy ints to the bin array, rather than char representations of ints, like this:

for(i = strlen(temp)-1; i>=0; i--) bin[j++] = (temp[i]=='1')?1:0;

(condition) ? (true expression) : (false expression)

Its a shortcut for:

if (condition) (true expression); else (false expression);

therefore...

char *Result = (x==2)?"correct":"incorrect";

is the same as...

char *Result;
  if (x==2)
    Result = "correct";
  else
    Result = "incorrect";

Its sometimes easier to read, and useful when you need to perform last minute conditional expressions in "tight spaces", such as within other more complex expressions. When the compiler encounters either of these methods, it converts it to the exact same assembly code.

Think of the [?:] shortcut in the same family as [++] and [+=] shortcuts. It just allows you to do more in a complex expression.

Edited 6 Years Ago by N1GHTS: n/a

i just found out i can't typecast, so i need to do it the way i was doing it before :(

Why can't you cast? Is it because you are getting errors or is it because this is a school assignment and the instructor is defining limitations to the allowed techniques?

Also, what line of code is illegal under your specific constraints? I'm curious to know.

i'm fairly sure it's the

for(i = strlen(temp)-1; i>=0; i--) bin[j++] = temp[i];

statement, but i haven't tried it with that if statement (the ?1:0 one) yet

i need to convert hex to dec, where the hex is read as a string from argv and i can't sdalkjfaljdslkj :(

i started to rewrite the whole thing and it works so far lol it's pretty basic and not intelligent at all, but here it is:

/*
 * work.c
 *
 *  Created on: Oct 26, 2010
 *      Author: Charlie
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void dec2bin(char *num, char *binary);
void hex2bin(char *num, char *binary);
void oct2bin(char *num, char *binary);

int main(int argc, char *argv[]){
	char bin1[256] = "", bin2[256] = "";
	int i;

	switch(argv[3][0]){
	case 'd': dec2bin(argv[1], bin1); break;
	case 'h': hex2bin(argv[1], bin1); break;
	case 'o': oct2bin(argv[1], bin1); break;
	case 'b': strcpy(bin1, argv[1]);
	}

	switch(argv[4][0]){
	case 'd': dec2bin(argv[2], bin2); break;
	case 'h': hex2bin(argv[2], bin2); break;
	case 'o': oct2bin(argv[2], bin2); break;
	case 'b': strcpy(bin2, argv[2]);
	}




	printf("num: %s\tbin: %s\n",argv[1], bin1);
	printf("num: %s\tbin: %s\n",argv[2], bin2);

	return 0;
}

void dec2bin(char *num, char *binary){
	char temp[256];
	int old;
	unsigned int i=0, j=0, n=0, remain;

	n = atoi(num);

	i = 0;

	while(n > 0){
		old = n;
		remain = n%2;
		n = n/2;
	/*	printf("%d/2 = %d  remainder = %d\n", old, n, remain); */
		temp[i++] = remain + '0';
	}

	/*reverse*/
	while(i > 0) binary[j++] = temp[--i];
	binary[j] = '\0';

}

void hex2bin(char *num, char *binary){
	char temp[256] = "";
	int i;

	for(i=0 ; i<strlen(num) ; i++){
		switch(num[i]){
		case '0': strcat(temp, "0000"); break;
		case '1': strcat(temp, "0001"); break;
		case '2': strcat(temp, "0010"); break;
		case '3': strcat(temp, "0011"); break;
		case '4': strcat(temp, "0100"); break;
		case '5': strcat(temp, "0101"); break;
		case '6': strcat(temp, "0110"); break;
		case '7': strcat(temp, "0111"); break;
		case '8': strcat(temp, "1000"); break;
		case '9': strcat(temp, "1001"); break;
		case 'A': strcat(temp, "1010"); break;
		case 'B': strcat(temp, "1011"); break;
		case 'C': strcat(temp, "1100"); break;
		case 'D': strcat(temp, "1101"); break;
		case 'E': strcat(temp, "1110"); break;
		case 'F': strcat(temp, "1111");
		}
	}

	i=0;

	while(temp[i] == '0') i++;

	strcpy(binary, temp+i);
}

void oct2bin(char *num, char *binary){



}

i just have to make oct2bin, bin2dec, bin2hex, and bin2oct methods, which shouldn't be too hard (i hope)

**and i have to make my add.c, sub.c, and mult.c to add the binary strings

Edited 6 Years Ago by mi.mac.rules: n/a

This question has already been answered. Start a new discussion instead.