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;
}
|