Why is my Macro in C not Working

Before asking for an explanation, please note, that the program is working correctly, I get the correct output, except LINT is complaining.

1. This is what Lint is complaining:

C2A6E4_CreateList.c(...) warning S577: Unnecessary function call duplication in function "CreateList"
*** EXPLANATION ***
You have called the "memcpy" function 3 times, but in this exercise it is only necessary and appropriate to call it once.
You have called the "SafeMalloc" function 3 times, but in this exercise it is only necessary and appropriate to call it twice.
This warning most commonly occurs when the submitted code contains more than one set of virtually identical statements, with each set being used to create and initialize a new list node. Such duplication is never necessary in this excercise since each set can easily be incorporated into one, thereby producing a much simpler algorithm. Regardless of what you have actually done, the fact that you are getting this warning indicates that your code is unnecessarily complex.

2. I have 3 Sections in my program that 9 consecutive lines of code that are identical, so to shrink the code I have to declare a macro and replaced those 3 sections with a macro. And the Macro is declared the way I learned it from www.cplusplus.com

3. After declaring the Macro, without using it yet, the program compiles no errors

4. Then I replaced the 3 sections, the one with the 9 lines of identical code, by the Macro name and when I compile it produced errors.
A. Unrecognized escape sequence,
B. Intellisence: unrecognized token.

This is what is troubling me. Did I learn #define wrong?

anyway here is the code. The one causing my headache in in function "LIST *CreateList(FILE *fp)" containing macro "INSERT_NODE_MACRO()"


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "C2A6E4_List-Driver.h"

#define LINE_LENGTH 128
#define INITIAL_VALUE 1 

//Open the file that will be use to test the function CreateList
FILE *OpenFile(const char *fileName)
{
    FILE *FilePointer;
    if ((FilePointer = fopen(fileName, "r")) == NULL)
    {
        fprintf(stderr, "Can't open \"filename\"\n");
        exit(EXIT_FAILURE);
    }
    return(FilePointer);
}

//This function will create a new NODE
static LIST *CreateNewNode()
{
    LIST *NewNode;
    if ((NewNode = (LIST *)malloc(sizeof(LIST))) == NULL)
    {
        fprintf(stderr, "Can't create Node \"pntr\"\n");
        exit(EXIT_FAILURE);
    }
    return(NewNode);
}

// Allocate the memory needed by the program and initialize to 0
static char *SafeMalloc(size_t memoryNeeded)
{
    char *pointerToEmptyMem;
    if ((pointerToEmptyMem = (char *)malloc(memoryNeeded)) == NULL)
    {
        fputs("Out of Memory\n", stderr);
        exit(EXIT_FAILURE);
    }
    return(pointerToEmptyMem);
}

//This is the section of the program that gets the word from the file one by one and count
//the times each word has occured in the file.
LIST *CreateList(FILE *fp)
{
    //variable used on the linklist
    int createHeaderDone = 0, duplicateFound, doneProcessingTheline = 0;
    LIST  *currentList = NULL, *headerList = NULL, *secondTraverserList;
    
    //Variable used on parsing the file
    char oneLine[LINE_LENGTH], *obtainedWord = " ", *firstTraverser, *delimiter = " \n";       
    int leadingSpace, dynamicMemSize = 1; 

    #define INSERT_NODE_MACRO()  /*count how many letters are in the obtained word*/    \
            firstTraverser = obtainedWord;                                              \
            dynamicMemSize = 1;                                                         \
            while (*firstTraverser++ != '\0') dynamicMemSize++;                         \ 
            currentList = CreateNewNode();                                              \
            currentList->next = headerList;                                             \
            headerList = currentList;                                                   \
            currentList->str = (char *)SafeMalloc(dynamicMemSize);                      \
            memcpy(currentList->str, obtainedWord, dynamicMemSize);                     \
            currentList->count = INITIAL_VALUE;

    //obtain and process one line of the file
    while (fgets(oneLine, LINE_LENGTH, fp)) 
    { 
        //immediately exit when the file is empty, however it is not considered a failure
        if (oneLine == NULL)
        {
            printf("The File is Empty\n");
            exit(EXIT_SUCCESS);
        }

        //skip the leading white space of the line
        leadingSpace = 0;
        while (isspace(oneLine[leadingSpace++]))
            ;

        //this portion gets the section of a string up to but not including the  delimiter.Create a header 
        // with one list element, this happens only during the beginning when the file is read for the first time.
        if (!createHeaderDone)
        {   
            headerList = NULL;          
            obtainedWord = strtok(oneLine, delimiter); 

            INSERT_NODE_MACRO()
            //set the flag which will prevent this if statement from getting executed again
            createHeaderDone = 1; 
        }
        
        //this is executed only processing lines two and above and only the first word of each line line 
        if (doneProcessingTheline) 
        {
            obtainedWord = strtok(oneLine, delimiter); 
            if (obtainedWord != NULL)
            {
                duplicateFound = 0;
                secondTraverserList = headerList;

                // This will scan the list from the beginning to the end and check if the new word is already
                // in one of the node. And if a duplicate is found the count of that node is incremented
                // and no insertion is done
                do
                {                     
                    if (!(strcmp(secondTraverserList->str, obtainedWord)))
                    {
                        secondTraverserList->count++;
                        duplicateFound = 1;
                    }
                    secondTraverserList = secondTraverserList->next;
                } while (secondTraverserList->next != NULL);

                //If the duplicate is not found then this section is executed
                if (!duplicateFound)
                {
                    INSERT_NODE_MACRO()
                    doneProcessingTheline = 0;
                } 
            }
        }

        //This is executed on the body of the file except the first word of each line
        do
        {             
            obtainedWord = strtok(NULL, delimiter); 
            //when the EOF is reached the rest of the program is bypassed if not the program will
            //try to process a bad pointer and the program crashes.
            if (obtainedWord != NULL)
            {
                duplicateFound = 0;
                secondTraverserList = headerList;

                // This will scan the list from the beginning to the end and check if the new word is already
                // in one of the node. And if a duplicate is found the count of that node is incremented
                // and no insertion is done
                do
                { 
                    if (!(strcmp(secondTraverserList->str, obtainedWord)))
                    {
                        secondTraverserList->count++;
                        duplicateFound = 1;
                    }
                    secondTraverserList = secondTraverserList->next;
                } while (secondTraverserList != NULL);

                //If the duplicate is not found then this section is executed
                if (!duplicateFound)
                {
                    INSERT_NODE_MACRO()
                }
            } 
        } while (obtainedWord != NULL);

        //Set the Flag indicating that the end of the line has been reached
        doneProcessingTheline = 1;
    } 
    return(headerList);
}

//This function prints the word and how many times it has occurred
LIST *PrintList(const LIST *head) 
{
    LIST *localTraverser;
    localTraverser = (LIST *)head;
    do
    {
        printf("The File has word  %15s  ", localTraverser->str);
        printf("\t%3d  times\n", localTraverser->count);
        localTraverser = localTraverser->next;
    } while (localTraverser != NULL);
    return((LIST *)head);
}

//Free the node that were created
void FreeList(LIST *head)
{
    LIST *trailingNode;
    while (head != NULL)
    {
        trailingNode = head;
        head = head->next;
        free(trailingNode);
    }
    return;
}
Macros are simply a text substitution facility. Each time you invoke the macro, the compiler simply substitutes the 9 lines of code from the definition. If you enable the the compiler listing and the define expansion option, when you look at the code the compiler processed, you will see your 9 lines of code in place of each invocation of the macro. Macros can make your source code neater, but they don't eliminate or reduce code.

#4) Check line 61. You have a space following the \. The \ must be immediately followed by the newline character. This is what is causing the unrecognized escape sequence and unrecognized token.

If you want to eliminate redundant code, put the repetitive code in a function.



Topic archived. No new replies allowed.