views:

174

answers:

2

When compiling a program containing this particular function,

/*
 * Function read_integer
 *
 * @Parameter CHAR* stringInt
 *
 * Parameter contains a string representing a struct integer.
 * Tokenizes the string by each character, converts each char
 * into an integer, and constructs a backwards linked list out
 * of the digits.
 *
 * @Return STRUCT* Integer
 */
struct integer* read_integer( char* stringInt )
{
    int i, n;
    struct integer *curr, *head;

    int numDigits = strlen( stringInt ); // Find the length of the struct integer
    char *tok;
    head = NULL;

    for( i = 0; i < numDigits; i++ )
    {
        tok = strtok( stringInt, NULL ); // Tokenize the string by each char
        n = atoi( tok[i] ); // Convert char to an integer

        curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
        curr->digit = n; // Digit of current node is assigned to n
        curr->next = head; // Move to the next node in the list.
        head = curr; // Move head up to the front of the list.
    }

    return head; // Return a pointer to the first node in the list.
}

I get the warning:

bigintII.c: In function ‘read_integer’:
bigintII.c:167: warning: passing argument 1 of ‘atoi’ makes pointer from integer without a cast
//usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘char’

I've tried a couple of different ways (that were mostly shots in the dark) to get rid of the warning, but to no avail. Can anybody point me in the right direction?

---///---

Original, dumb question below here, left because I don't want to be that guy.---

I'm trying to debug my assignment for CS1 so I can finish it and move onto something interesting (like working on my CLisp studies), but I've run into an error I can't get past. Now, I know the assignment isn't complete yet (i.e., it isn't going to do what I want it to even if I get it to run) but I don't want help with that (besides, what fun would that be?). If someone could just help me figure out why the following code, when compiled and executed, produces the useless (to me) Segmentation fault (core dumped), well, that'd be awesome.

/*
 * File:   struct integer.c

 * Description: Assignment in using Linked Lists
 * in order to perform struct integer addition and subtraction.
 *
 * Created on September 1, 2010, 11:38 AM
 */

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


// Constant Definitions
#define ADD 1
#define SUB 2

// Output file
char *fName = "out.txt";
FILE *outFile;


/*
 * Create a prototype of a single
 * node in the Linked List.
 * Each node will represent a single
 * integer comprising one part of a struct integer.
 */
struct integer
{
    int digit;

    struct integer *next;
};


// Function Prototypes
struct integer* read_integer( char *stringInt );
struct integer* add( struct integer *p, struct integer *q );
struct integer* subtract( struct integer *p, struct integer *q);

int compare( struct integer *p, struct integer *q );

void print( struct integer *p );


// Main function
int main( )
{
    //Variable initialization

    /*
     * Initialize pointers to the linked lists.
     * One, *head, will always point to the
     * first element, the head, of the list.
     * The other element, *curr, will point to the
     * node currently being accessed, and will be
     * used to traverse the list.
     */
    struct integer* pHead;
    struct integer* qHead;
    struct integer* tHead; // Used to contain the total

    int numOps, oper, i;
    const char *fileName = "struct integer.txt";
    char bigintstr[200];
    FILE *inputFile;

    // Open output file
    outFile = fopen(fName, "a+");


    // Open up the input file for reading
    inputFile = fopen(fileName, "r");

    // Read in the number of operations to be performed
    fscanf(inputFile, "%d", &numOps);

    /*
     * For each operation that must be performed,
     * construct a linked list for each of the
     * struct integers in the file. Then, perform the operation
     * indicated by the digit preceding them.
     */
    for( i = 0; i < numOps; i++ )
    {
        // Read in the number that dictates operation
        fscanf(inputFile, "%d", &oper);

        // Read in the first struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer string to read_integer()
         * in order to construct a linked list out of it.
         */
        pHead = read_integer( bigintstr );

        // Read in second struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer str to read_integer()
         * in order to construct a linked list out of it.
         */
         qHead = read_integer( bigintstr );

         /*
          * Depending on the operation to be performed,
          * call the corresponding function.
          */
         switch( oper )
         {
             case ADD:
                 tHead = add( pHead, qHead );
                 break;
             case SUB:
                 tHead = subtract( pHead, qHead );
                 break;
             default:
                 printf("Invalid operation parameter.\n");
         }

         print( pHead ); // Print out the first struct integer
         fprintf(outFile, " + ");
         print( qHead ); // Print out the second struct integer
         fprintf(outFile, " = ");
         print( tHead ); // Print out the sum/difference struct integer
         fprintf(outFile, "\n"); // Move to next line for next instruction set
    }
    fclose(inputFile);

    //system(PAUSE);
    return 0;
}


// Function Definitions

/*
 * Function read_integer
 *
 * @Parameter CHAR* stringInt
 *
 * Parameter contains a string representing a struct integer.
 * Tokenizes the string by each character, converts each char
 * into an integer, and constructs a backwards linked list out
 * of the digits.
 *
 * @Return STRUCT* Integer
 */
struct integer* read_integer( char* stringInt )
{
    int i, n;
    struct integer *curr, *head;

    int numDigits = strlen( stringInt ); // Find the length of the struct integer
    char *tok;
    head = NULL;

    for( i = 0; i < numDigits; i++ )
    {
        tok = strtok( stringInt, NULL ); // Tokenize the string by each char
        n = atoi( tok[i] ); // Convert char to an integer

        curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
        curr->digit = n; // Digit of current node is assigned to n
        curr->next = head; // Move to the next node in the list.
        head = curr; // Move head up to the front of the list.
    }

    return head; // Return a pointer to the first node in the list.
}

/*
 * Function print
 *
 * @Parameter STRUCT* Integer
 *
 * Given a linked list, will traverse through
 * the nodes and print out, one at a time,
 * the digits comprising the struct integer that the
 * linked list represents.
 *
 * TODO: Print to file
 */
void print( struct integer *p )
{    
    while( p )
    {
        fprintf(outFile, "%d", p->digit);
        p = p->next;
    }
}

/*
 * Function add
 *
 * @Paramater STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing
 * big integers stored in reversed order,
 * and returns a linked list containing
 * the sum of the two integers.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* add( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *sHead, *sCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    sHead = NULL;

    while( p )
    {
        sCurr = ( struct integer* ) malloc (sizeof(struct integer));
        sCurr->digit = p->digit + q->digit + carry;
        sCurr->next = sHead;
        sHead = sCurr;

        carry = 0;

        /*
         * If the current digits sum to greater than 9,
         * create a carry value and replace the current
         * value with value mod 10.
         */
        if( sCurr->digit > 9 )
        {
            carry = 1;
            sCurr->digit = sCurr->digit % 10;
        }

        /*
         * If the most significant digits of the numbers
         * sum to 10 or greater, create an extra node
         * at the end of the sum list and assign it the
         * value of 1.
         */
        if( carry == 1 && sCurr->next == NULL )
        {
            struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
            sCarry->digit = 1;
            sCarry->next = NULL;
            sCurr->next = sCarry;
        }

        p = p->next;
        q = q->next;
    }

    return sHead;
}

/*
 * Function subtract
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing struct integers.
 * Traverses through the lists, subtracting each
 * digits from the subsequent nodes to form a new
 * struct integer, and then returns the newly formed
 * linked list.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* subtract( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *dHead, *dCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    dHead = NULL;

    while( p )
    {
        dCurr = (struct integer*) malloc (sizeof(struct integer));
        dCurr->digit = p->digit - q->digit - carry;
        dCurr->next = dHead;
        dHead = dCurr;

        if( dCurr->digit < 0 )
        {
            dCurr->digit += 10;
            carry = 1;
        }

        if( dCurr->next == NULL && carry == 1 )
        {
            struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
            dCarry->digit = -1;
            dCarry->next = NULL;
            dCurr->next = dCarry;
        }

        p = p->next;
        q = q->next;
    }

    return dHead;
}

/*
 * Function compare
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes in two linked lists representing struct integers.
 * Traverses the lists one at a time, comparing the
 * digits.
 *
 * Case: p < q
 * @Return -1
 *
 * Case: p == q
 * @Return 0
 *
 * Case: p > q
 * @Return 1
 * 
 * TODO Comment me
 */
int compare( struct integer *p, struct integer *q )
{
    struct integer *pHead, *qHead;
    int comp = 0;

    pHead = p;
    qHead = q;

    while( p )
    {
        if( p->digit > q->digit )
        {
            comp = 1;
        }

        if( p->digit < q->digit )
        {
            comp = -1;
        }

        p = p->next;
        q = q->next;
    }

    return comp;
}

I'm sorry that there's a lot to wade through, I'm just trying to get in the habit of over-documenting my code because I like to go back and read through stuff I've written to review concepts. The actual program itself is fairly straightforward, though (if not broken, haha).

+3  A: 

compiling it with gcc gives this:

test.c: In function ‘read_integer’: test.c:165: warning: passing argument 1 of ‘atoi’ makes pointer from integer without a cast /usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘char’

this is 164/165

    tok = strtok( stringInt, NULL ); // Tokenize the string by each char
    n = atoi( tok[i] ); // Convert char to an integer

should be

   n =  stringInt - '0'; // Convert char to an integer

the tok variable is now pointless. it doesn't crash anymore with me, and it does find the correct answer(1 + 1 = 2),

furthermore you forgot to close outputFile at the end of your program. and you apparently open the outfile in append mode(wich isn't bad, it just caught me by surprise)

then there's another inconsistency, your add function reverses the order in which your numbers are stored wich means that the input numbers are printed in reverse order whilst the anwer is printed in the correct order.

I fixed those now:

/*
 * File:   struct integer.c

 * Description: Assignment in using Linked Lists
 * in order to perform struct integer addition and subtraction.
 *
 * Created on September 1, 2010, 11:38 AM
 */

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


// Constant Definitions
#define ADD 1
#define SUB 2

// Output file
char *fName = "out.txt";
FILE *outFile;


/*
 * Create a prototype of a single
 * node in the Linked List.
 * Each node will represent a single
 * integer comprising one part of a struct integer.
 */
struct integer
{
    int digit;

    struct integer *next;
};


// Function Prototypes
struct integer* read_integer( char *stringInt );
struct integer* add( struct integer *p, struct integer *q );
struct integer* subtract( struct integer *p, struct integer *q);

int compare( struct integer *p, struct integer *q );

void print( struct integer *p );


// Main function
int main( )
{
    //Variable initialization

    /*
     * Initialize pointers to the linked lists.
     * One, *head, will always point to the
     * first element, the head, of the list.
     * The other element, *curr, will point to the
     * node currently being accessed, and will be
     * used to traverse the list.
     */
    struct integer* pHead;
    struct integer* qHead;
    struct integer* tHead; // Used to contain the total

    int numOps, oper, i;
    const char *fileName = "struct_integer.txt";
    char bigintstr[200];
    FILE *inputFile;

    // Open output file
    outFile = fopen(fName, "a+");


    // Open up the input file for reading
    inputFile = fopen(fileName, "r");

    // Read in the number of operations to be performed
    fscanf(inputFile, "%d", &numOps);

    /*
     * For each operation that must be performed,
     * construct a linked list for each of the
     * struct integers in the file. Then, perform the operation
     * indicated by the digit preceding them.
     */
    for( i = 0; i < numOps; i++ )
    {
        // Read in the number that dictates operation
        fscanf(inputFile, "%d", &oper);

        // Read in the first struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer string to read_integer()
         * in order to construct a linked list out of it.
         */
        pHead = read_integer( bigintstr );

        // Read in second struct integer into a string
        fscanf(inputFile, "%s", bigintstr);

        /*
         * Pass the struct integer str to read_integer()
         * in order to construct a linked list out of it.
         */
         qHead = read_integer( bigintstr );

         /*
          * Depending on the operation to be performed,
          * call the corresponding function.
          */
         switch( oper )
         {
             case ADD:
                 tHead = add( pHead, qHead );
                 break;
             case SUB:
                 tHead = subtract( pHead, qHead );
                 break;
             default:
                 printf("Invalid operation parameter.\n");
         }

         print( pHead ); // Print out the first struct integer
         fprintf(outFile, " + ");
         print( qHead ); // Print out the second struct integer
         fprintf(outFile, " = ");
         print( tHead ); // Print out the sum/difference struct integer
         fprintf(outFile, "\n"); // Move to next line for next instruction set
    }
    fclose(inputFile);
    fclose(outFile);
    //system(PAUSE);
    return 0;
}


// Function Definitions

/*
 * Function read_integer
 *
 * @Parameter CHAR* stringInt
 *
 * Parameter contains a string representing a struct integer.
 * Tokenizes the string by each character, converts each char
 * into an integer, and constructs a backwards linked list out
 * of the digits.
 *
 * @Return STRUCT* Integer
 */
struct integer* read_integer( char* stringInt )
{
    int i, n;
    struct integer *curr, *head;

    int numDigits = strlen( stringInt ); // Find the length of the struct integer
    char *tok;
    head = NULL;

    for( i = 0; i < numDigits; i++ )
    {
        n =  stringInt[i] - '0'; // Convert char to an integer

        curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
        curr->digit = n; // Digit of current node is assigned to n
        curr->next = head; // Move to the next node in the list.
        head = curr; // Move head up to the front of the list.
    }

    return head; // Return a pointer to the first node in the list.
}

void reverse (struct integer **p){
    if((*p)->next==0) return;
    struct integer *i=*p,*j;
    while(i->next){
        j=i;
        i=i->next;
    }//i is now the tail;
    i->next=j;
    j->next=0;
    reverse(p);
    *p=i;
}

/*
 * Function print
 *
 * @Parameter STRUCT* Integer
 *
 * Given a linked list, will traverse through
 * the nodes and print out, one at a time,
 * the digits comprising the struct integer that the
 * linked list represents.
 *
 * TODO: Print to file
 */
void print( struct integer *p )
{
    struct integer *head=p;
    reverse(&p);    
    while( p )
    {
        fprintf(outFile, "%d", p->digit);
        p = p->next;
    }
    reverse(&head);
}


/*
 * Function add
 *
 * @Paramater STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing
 * big integers stored in reversed order,
 * and returns a linked list containing
 * the sum of the two integers.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* add( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *sHead, *sCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    sHead = NULL;

    while( p )
    {
        sCurr = ( struct integer* ) malloc (sizeof(struct integer));
        sCurr->digit = p->digit + q->digit + carry;
        sCurr->next = sHead;
        sHead = sCurr;

        carry = 0;

        /*
         * If the current digits sum to greater than 9,
         * create a carry value and replace the current
         * value with value mod 10.
         */
        if( sCurr->digit > 9 )
        {
            carry = 1;
            sCurr->digit = sCurr->digit % 10;
        }

        /*
         * If the most significant digits of the numbers
         * sum to 10 or greater, create an extra node
         * at the end of the sum list and assign it the
         * value of 1.
         */
        if( carry == 1 && sCurr->next == NULL )
        {
            struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
            sCarry->digit = 1;
            sCarry->next = NULL;
            sCurr->next = sCarry;
        }

        p = p->next;
        q = q->next;
    }
    reverse(&sHead);
    return sHead;
}



/*
 * Function subtract
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing struct integers.
 * Traverses through the lists, subtracting each
 * digits from the subsequent nodes to form a new
 * struct integer, and then returns the newly formed
 * linked list.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* subtract( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *dHead, *dCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    dHead = NULL;

    while( p )
    {
        dCurr = (struct integer*) malloc (sizeof(struct integer));
        dCurr->digit = p->digit - q->digit - carry;
        dCurr->next = dHead;
        dHead = dCurr;

        if( dCurr->digit < 0 )
        {
            dCurr->digit += 10;
            carry = 1;
        }

        if( dCurr->next == NULL && carry == 1 )
        {
            struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
            dCarry->digit = -1;
            dCarry->next = NULL;
            dCurr->next = dCarry;
        }

        p = p->next;
        q = q->next;
    }

    return dHead;
}

/*
 * Function compare
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes in two linked lists representing struct integers.
 * Traverses the lists one at a time, comparing the
 * digits.
 *
 * Case: p < q
 * @Return -1
 *
 * Case: p == q
 * @Return 0
 *
 * Case: p > q
 * @Return 1
 * 
 * TODO Comment me
 */
int compare( struct integer *p, struct integer *q )
{
    struct integer *pHead, *qHead;
    int comp = 0;

    pHead = p;
    qHead = q;

    while( p )
    {
        if( p->digit > q->digit )
        {
            comp = 1;
        }

        if( p->digit < q->digit )
        {
            comp = -1;
        }

        p = p->next;
        q = q->next;
    }

    return comp;
}

i wrote reverse for you:

void reverse (struct integer **p){
    if((*p)->next==0) return;
    struct integer *i=*p,*j;
    while(i->next){
        j=i;
        i=i->next;
    }//i is now the tail;
    // 1->2->3->4->NIL

    i->next=j;
    // 1 -> 2 -> 3 <-> 4

    j->next=0;
    // 1 -> 3 -> 3 <- 4
    //           |
    //           v
    //          NIL
    reverse(p);// p looks like 1 -> 2 -> 3 now recurse
    *p=i;
}
flownt
Yeah, I re-tooled the question to be more specific and to work out that issue first.
Andrew
+3  A: 

Your problem is caused by passing the wrong thing to atoi. atoi expects a string, which as you know in C is a char pointer. You're passing a single char, which is not a char pointer. atoi attempts to treat the value of the character as a memory address, which is almost certainly an address you're not allowed to access, so your program goes bang.

To get the numerical value of a char containing an ASCII digit, subtract '0' from it, ie change

n = atoi( tok[i] );

to

n = tok[i] - '0';

But you don't need strtok:

for (i = 0; i < numDigits; i++) {
    n = stringInt[i] - '0';
    // etc
}
Jon
The subtraction of '0' from a digit character to obtain the value "works", in `C`, for every character set in existence, obsolete, or not yet invented.
pmg