0

I'm trying to write a simple C code for the following function:

Given an encoding for the letters a-d:

'a'->00, 'b'->01, 'c'->10, 'd'->11,

and a node in a linked-list defined as:

typedef struct listNode{
 unsigned char data;
 struct listNode* next;
}ListNode;

typedef struct list{
  ListNode* head;
  ListNode* tail;
}List;

where head points to the first node of the list, and the tail to the last one.

I need to write a function char* SumList(List arr[], int n), which returns a string which contains all the encoded letters in all the nodes of all lists in arr in row.

This is what I wrote so far:

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

int isBitISet(char, int);

typedef struct listNode {
    unsigned char data;
    struct listNode* next;
} ListNode;

typedef struct list {
    ListNode* head;
    ListNode* tail;
} List;

int isBitISet(char ch, int i) {

    char mask;
    mask=1<<i;
    return (mask & ch);
}

int totalNodes(List arr[], int n) {
    int i;
    int counter=0;

    for (i=0; i<n; ++i) {
        ListNode* head= arr[i].head;
        while (head!=NULL) {
            counter++;
            head=head->next;
        }
    }
    return counter;
}

char* whatToadd(char data) {
    int a, b;
    a=isBitISet(data, 0);
    b=isBitISet(data, 1);
    char* result;
    result=(char *) calloc(2, sizeof(char));
    if ((a!=0) && (b!=0))
        result="d";
    else if ((a!=0) && (b==0))
        result="b";
    else if ((a==0) && (b!=0))
        result="c";
    else
        result="a";
    return result;

}

char* SumLists(List arr[], int n) {

    char* final;
    int nodes=totalNodes(arr, n);
    final= (char*) calloc(nodes, sizeof(char)); //how would I know the final length?//
    int i;

    for (i=0; i<n; ++i) {
        ListNode* head= (arr[i].head);
        while (head!=NULL) { //Why do I need a tail?//
            char* result;
            result=whatToadd(((head->data)&(00000011)));
            strcat(final, result);
            free(result);
            result=whatToadd(((head->data)&(00001100))>>2);
            strcat(final, result);
            free(result);
            result =whatToadd(((head->data)&(00110000))>>4);
            strcat(final,result);
            free(result);
            result=whatToadd(((head->data)&(11000000))>>6);
            strcat(final,result);
            free(result);

            head=head->next;

        }
    }
    return final;
}

int main() {
    .....

    free(final);
    ...
}

Probably, Tail has given from some reason- but (1)- can't I run on the lists the way I did? without using the tail? and if not, how should I use it?

(2)- Do I need to free result the way I did each time I get a new result from whatToAdd?

I'm new to C, trying to work it by myself, I would really appricate tips and corrections. Thanks a lot.

Numerator
  • 1,389
  • 3
  • 21
  • 40
  • `result=whatToadd(((head->data)&(00000011)));` if this intended as a bitmask, you probably want 0x03, 0x0c, 0x30 and 0xc0, respectively. You could also first do the shift and then mask with 3 : `result=whatToadd((head->data >> 6) & 3);` for the last one. – wildplasser Jul 17 '12 at 12:20

1 Answers1

1

Do I need to free result the way I did each time I get a new result from whatToAdd?

No, as the address of a string literal is being returned. Don't calloc() memory for result as it is unrequired. Change the return value of whatToadd() to const char*, as string literals are read-only.

Just to clarify, the following does not copy "d" into result:

result="d";

but instead makes result point to the address of the string literal "a": it is a pointer assignment. If you wanted to copy into result you could do either:

  • strcpy(result, "d");
  • *result = 'd'; *(result + 1) = 0;

in which case you would free() the returned pointer.

Only pass a pointer to free() if it is the result of a previous call to calloc(), malloc() or realloc() and has not already been free()d.

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • But then won't I return a local which would be lost after the function ends? – Numerator Jul 17 '12 at 09:46
  • @Numerator, no. String literals will be valid for the lifetime of the program. If you had a local array `char result[2];` and returned it then that would be lost. – hmjd Jul 17 '12 at 09:47
  • what is different from this example: http://stackoverflow.com/questions/11517298/strings-and-string-functions-in-c? Is it because the function in the example returns a pointer? – Numerator Jul 17 '12 at 09:51
  • @Numerator, it is because he is returning the address of a local array (same as the example I gave in my previous comment). – hmjd Jul 17 '12 at 09:52