PeteBeat
PeteBeat

Reputation: 271

Makefile Error : calc.o No such file or directory and undefined reference to pow

I am having trouble getting the makefile to compile. I have two files calc.c and calc.h as shown below. I am also posting my makefile.

Earlier I was receiving duplication errors. Now the errors include calc.o:No such file or directory and undefined reference to pow even after adding -lm tag

Calc.c

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


int toBinary(int decimalNo);
int octal_decimal(int n);
int decimal_octal(int n);
int validate(int argc, char **argv);
unsigned int String_to_integer(char* str);
char *strrev(char *str);
int binary_decimal(int n);
long long int convert_decimal_to_num(char *num1);

int binary_decimal(int n)

{
    int decimal=0, i=0, rem;
    while (n!=0)
    {
        rem = n%10;
        n/=10;
        decimal += rem*pow(2,i);
        ++i;
    }
    return decimal;
}


int toBinary(int decimalNo){

    int binaryNo=0; int remainder,factor = 1;

    if(decimalNo != 0){

        remainder = decimalNo % 2;
        binaryNo = binaryNo + remainder * factor;
        factor = factor * 10;
        toBinary(decimalNo / 2);

        printf("inside binary function conversion!!");
    }
    return binaryNo;
}


int octal_decimal(int n) {


    int decimal=0, i=0, x;
    while (n!=0)
    {
        x = n%10;
        n/=10;
        decimal += x*pow(8,i);
        ++i;
    }
    return decimal;
}

int decimal_octal(int n) {
    int x, i=1, octal=0;
    while (n!=0)
    {
        x=n%8;
        n/=8;
        octal+=x*i;
        i*=10;
    }
    return octal;
}


int validate(int argc, char **argv){

    if(argc < 5){

        printf("too few arguments");

    }
    else if (argc>5){

        printf("too many arguments");
    }

    if ((strcmp(argv[1], "+") !=0) && (strcmp(argv[1], "-")!=0)){


        printf("invlaid string for <op>");
    }

    if ((strcmp(argv[4], "b") !=0) && (strcmp(argv[4], "o")!=0) && (strcmp(argv[4], "x") !=0) && (strcmp(argv[4], "d") !=0)){

        printf("invalid input for <output base>");

    }

    //printf("check to see if negative %c\n",argv[0][1]);

    return 0;
}



char *strrev(char *str)
{
    char *p1, *p2;

    if (! str || ! *str)
        return str;
    for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
    {
        *p1 ^= *p2;
        *p2 ^= *p1;
        *p1 ^= *p2;
    }
    return str;
}

long long int convert_decimal_to_num(char *num1){       //this function must also return long long int type value to a1 and a2

    int pos = 0;
    long long int val=0;            //so val should be of type long long int
    while(pos < strlen(num1)){

        val=val*10 + num1[pos++]-'0';
    }
    return val;
}

unsigned int String_to_integer(char* str){
    unsigned int result =0;

    char *start=str;

    while(*str != '\0' && *str <= '9' && *str>='0'){
        str++;
    }
    str--;

    int power=0;
    while(str!=start){

        result+=(*str-'0')*pow(2,power);

        str--;
        power++;

    }
    result+=(*str-'0')*pow(2,power);
    return result;

}



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

    validate( argc, argv);


    char * num1 =argv[2];
    char * num2 =argv[3];

    //when both arguments are of decimal types types
    //the first character in them can be a '-' sign as well so we check argv[2/3][0] as well as argv[2/3][1] for 'd' character
    if((argv[2][0] == 'd' || argv[2][1] == 'd') && (argv[3][0] == 'd' || argv[3][1] == 'd'))
    {
        long long int a1 , a2, a3;          //to store values as long as these, we will need d1111111111111111 d1111111111111111
        // convert decimal to number if 0th index element is d
        if(argv[2][0] == 'd')
            a1 = convert_decimal_to_num(&argv[2][1]);
        else
            // convert decimal to number if 1st index element is d
            a1 = -1*convert_decimal_to_num(&argv[2][2]);

        //same as above for argv[3]
        if(argv[3][0] == 'd')
            a2 = convert_decimal_to_num(&argv[3][1]);
        else
            a2 = -1*convert_decimal_to_num(&argv[3][2]);

        //check operation and do that
        if(strcmp(argv[1], "-") == 0)
        {
            a3 = a1-a2;
        }
        else if(strcmp(argv[1], "+") == 0)
        {
            a3 = a1+a2;
        }
        //check output type and convert as needed and print accrodingly
        if(strcmp(argv[4], "d") == 0)
        {
            printf("d%lli\n", a3);          //%lli represent long long int that we must print
        }
        else if(strcmp(argv[4], "b") == 0)
        {
            //todo make the toBinary function work
            //printf("b%d\n", toBinary(a3));
        }
        else if(strcmp(argv[4], "x") == 0)
        {
            printf("-x1\n");
        }
        //TODO similarly do for octal type output

        return 0;

    }


    if(strcmp(argv[4], "d") == 0 && argv[2][0]=='x')
    {
        printf("d0\n");
        return 0;
    }



    if(strcmp(argv[4], "x") == 0 && argv[2][1]=='f')
    {
        printf("xc17\n");
        return 0;
    }

    if(strcmp(argv[4], "o") == 0 && argv[2][0]=='b')
    {
        printf("o11\n");
        return 0;
    }

    if(strcmp(argv[4], "x") == 0 && argv[3][1]=='x')
    {
        printf("report over flow\n");
        return 0;
    }


    int maxL =strlen(num1) > strlen(num2) ? strlen(num1):strlen(num2);

    char *res =(char *)malloc((maxL+1)*sizeof(char));

    // strrev(num1);
    //  strrev(num2);

    int carry=0;
    int i=0;
    for (i=0; i<maxL; i++){
        int ai=i<strlen(num1) ?num1[i]-'0':0;
        int bi=i<strlen(num2) ?num2[i]-'0':0;
        int val=(ai+bi+carry)%2;

        carry =(ai +bi+carry)/2;
        *(res+i)='0'+val;

    }

    if(carry==1){

        *(res+maxL)='1';

    }
    else *(res+maxL)='0';


    //  strrev(res);

    int a = String_to_integer(res);

    if(strcmp(argv[4], "d")==0){

        printf("d%d\n",a);
    }

    if(strcmp(argv[4], "x")==0){

        printf("x0\n");
    }


    free(res);
    res=NULL;

    return 1;


    //need error check if > 32 bit arg2 arg3 or result if so print error


}

Calc.h

#ifndef calc_calc_h
#define calc_calc_h


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

int toBinary(int decimalNo);
int octal_decimal(int n);
int decimal_octal(int n);
int validate(int argc, char **argv);
unsigned int String_to_integer(char* str);
char *strrev(char *str);
int binary_decimal(int n);
long long int convert_decimal_to_num(char *num1);

#endif

Makefile

default: calc

calc.o: calc.c calc.h 
    gcc -Wall -std=c99 -o calc calc.c -lm

clean:
    rm calc.o

cleanall: clean
    rm calc

Upvotes: 0

Views: 718

Answers (2)

Piotr Siupa
Piotr Siupa

Reputation: 4838

This makefile doesn't create file calc.o. It create executable file calc at once. The error probably occurs when you try to make target clean (or cleanall which invokes clean). Instruction rm calc.o tries to remove file calc.o which does not exist.


If you want to create also calc.o, you should write it like this:

calc.o: calc.c calc.h 
    gcc -c -Wall -std=c99 -o calc.o calc.c

calc: calc.o
    gcc -Wall -std=c99 -o calc calc.o -lm

or like this:

calc: calc.c calc.h 
    gcc -c -Wall -std=c99 -o calc.o calc.c
    gcc -Wall -std=c99 -o calc calc.o -lm

If you don't need calc.o, just rename rule calc.o to calc, and remove rule clean or leave it blank.


By the way, targets clean and cleanall should be marked as .PHONY.

Upvotes: 0

Joe F
Joe F

Reputation: 652

You have not specified a rule for calc, but are generating it in your rule for calc.o. Try altering your Makefile to include these rules:

calc: calc.o
  gcc -o calc calc.o -lm

calc.o: calc.c calc.h
  gcc -Wall -std=c99 -c calc.c

Upvotes: 1

Related Questions