Principal Problem
One of your principal problems is that j
is out of control — it is never zeroed after it is first initialized. Rhoni-Ann causes trouble because she has lots of free periods; Ashleigh causes trouble because she has no free periods. With Rhoni-Ann, j
gets to 18, but the arrays you're indexing only go up to 9. You need to revisit that whole portion of the code. You need to read the number after the day letter and use that in place of the j
value. You should also validate that the value is small enough (a value of 9
would cause overflows again; only 0..8 is OK), and report if the day letter is not valid. Note too that the space is not zeroed when the memory is allocated. It is not clear what you're going to do afterwards, but you don't have valid strings in the M
, T
, etc arrays.
Revised code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct prefectNode
{
char *name; // prefect name
char *type; // prefect type
char *used;
struct free// structure storing the prefect's free sessions on particular days
{
char M[9];
char T[9];
char W[9];
char S[9];
char F[9];
} fses; // free sessions available to prefect;
struct prefectNode *nextPtr;// a pointer to the next node
} pNode;// Self-Referential structure used to store information about a prefect
typedef pNode *ptrNode;// Synonym for a pointer to a self-referential structure
void induct(ptrNode *list, char l[]);// induct is called when information is being retrieved from file.
void induct(ptrNode *list, char l[])
{
ptrNode curPtr = *list; // pointer to the current node
ptrNode newPtr = calloc(sizeof(*newPtr), 1);// creating new node
if (newPtr != NULL)
{
newPtr->name = strdup(strtok(l, ","));
newPtr->type = strdup(strtok(NULL, ","));
printf("Prefect: %s, type %s\n", newPtr->name, newPtr->type);
char *sesh = strtok(NULL, " ");
if (sesh == NULL)
{
fprintf(stderr, "No free sessions for %s\n", newPtr->name);
free(newPtr->name);
free(newPtr->type);
free(newPtr);
return;
}
int i = 0, j = 0;
int len = strlen(sesh);
for (i = 0; i < len; i++)
{
char c = sesh[i];
if (c == 'M')
{
newPtr->fses.M[j] = sesh[i + 1];
printf("M%c", newPtr->fses.M[j]);
}
if (c == 'T')
{
newPtr->fses.T[j] = sesh[i + 1];
printf("T%c", newPtr->fses.T[j]);
}
if (c == 'W')
{
newPtr->fses.W[j] = sesh[i + 1];
printf("W%c", newPtr->fses.W[j]);
}
if (c == 'S')
{
newPtr->fses.S[j] = sesh[i + 1];
printf("S%c", newPtr->fses.S[j]);
}
if (c == 'F')
{
newPtr->fses.F[j] = sesh[i + 1];
printf("F%c", newPtr->fses.F[j]);
}
printf("(j=%d)\n", j);
i = i + 2;
j++;
}
newPtr->nextPtr = NULL;
curPtr = *list;
if (curPtr == NULL)
{
newPtr->nextPtr = *list;
*list = newPtr;
}
else
{
while (curPtr->nextPtr != NULL)
{
curPtr = curPtr->nextPtr;
}
curPtr->nextPtr = newPtr;
}
}
else
{
printf("no memory\n");
}
}
static void free_node(pNode *node)
{
if (node != 0)
{
free(node->name);
free(node->type);
free(node);
}
}
static void free_list(pNode *node)
{
while (node != 0)
{
pNode *next = node->nextPtr;
free_node(node);
node = next;
}
}
static void print_sessions(const char *dow, const char *ses)
{
printf(" %s:", dow);
for (int i = 0; i < 9; i++)
{
if (ses[i] != '\0')
printf(" %c", ses[i]);
}
}
static void print_node(const pNode *node)
{
printf("%s [%s]", node->name, node->type);
print_sessions("Mon", node->fses.M);
print_sessions("Tue", node->fses.T);
print_sessions("Wed", node->fses.W);
print_sessions("Thu", node->fses.S);
print_sessions("Fri", node->fses.F);
putchar('\n');
}
static void print_list(const char *tag, pNode *list)
{
printf("%s:\n", tag);
while (list != NULL)
{
print_node(list);
list = list->nextPtr;
}
}
int main(void)
{
FILE *fp;
char ln[200];
ptrNode start = NULL;
const char filename[] = "thefile.txt";
fp = fopen(filename, "r");
if (fp == NULL)
{
fprintf(stderr, "File %s not found.\n", filename);
}
else
{
while (fgets(ln, sizeof(ln), fp) != 0)
{
size_t len = strlen(ln);
if (len > 0)
ln[len-1] = '\0';
printf("[%s]\n", ln);
induct(&start, ln);
}
fclose(fp);
print_list("After data read", start);
free_list(start);
}
return 0;
}
Sample run under valgrind
==54054== Memcheck, a memory error detector
==54054== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==54054== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==54054== Command: xyz
==54054==
[Denelia Alvaranga,R,M7_T4_T5_T6]
Prefect: Denelia Alvaranga, type R
M7(j=0)
T4(j=1)
T5(j=2)
T6(j=3)
[Sainna Christian,R,M4_M5_M6_T1_T2_T3_F5_F6]
Prefect: Sainna Christian, type R
M4(j=0)
M5(j=1)
M6(j=2)
T1(j=3)
T2(j=4)
T3(j=5)
F5(j=6)
F6(j=7)
[Kashielle Clarke,R,F1_T4_W4_F4_T5_W5_S5_W6_S6_M7_W7]
Prefect: Kashielle Clarke, type R
F1(j=0)
T4(j=1)
W4(j=2)
F4(j=3)
T5(j=4)
W5(j=5)
S5(j=6)
W6(j=7)
S6(j=8)
M7(j=9)
W7(j=10)
[Candice Gordon,R,M1_M2_M3_S3_T7]
Prefect: Candice Gordon, type R
M1(j=0)
M2(j=1)
M3(j=2)
S3(j=3)
T7(j=4)
[Alphene Groves,R,M2_T5_S7_W3]
Prefect: Alphene Groves, type R
M2(j=0)
T5(j=1)
S7(j=2)
W3(j=3)
[T-Anna Johnson,R,M7]
Prefect: T-Anna Johnson, type R
M7(j=0)
[Vanessa Lewis,R,M1_M2_M3_S3_T4_W4_S4_T5_S5_T6_S6]
Prefect: Vanessa Lewis, type R
M1(j=0)
M2(j=1)
M3(j=2)
S3(j=3)
T4(j=4)
W4(j=5)
S4(j=6)
T5(j=7)
S5(j=8)
T6(j=9)
S6(j=10)
[Rhoni-Ann Parkins,R,W1_S1_W2_S2_W3_S3_M4_T4_S4_F4_M5_T5_F5_M6_T6_F6_T7_F7]
Prefect: Rhoni-Ann Parkins, type R
W1(j=0)
S1(j=1)
W2(j=2)
S2(j=3)
W3(j=4)
S3(j=5)
M4(j=6)
T4(j=7)
S4(j=8)
F4(j=9)
M5(j=10)
T5(j=11)
F5(j=12)
M6(j=13)
T6(j=14)
F6(j=15)
T7(j=16)
F7(j=17)
[Ashleigh Graham,N6A ]
Prefect: Ashleigh Graham, type N6A
No free sessions for Ashleigh Graham
After data read:
Denelia Alvaranga [R] Mon: 7 Tue: 4 5 6 Wed: Thu: Fri:
Sainna Christian [R] Mon: 4 5 6 Tue: 1 2 3 Wed: Thu: Fri: 5 6
Kashielle Clarke [R] Mon: Tue: 7 4 5 Wed: 4 5 6 Thu: 7 5 6 Fri: 1 4
Candice Gordon [R] Mon: 1 2 3 Tue: 7 Wed: Thu: 3 Fri:
Alphene Groves [R] Mon: 2 Tue: 5 Wed: 3 Thu: 7 Fri:
T-Anna Johnson [R] Mon: 7 Tue: Wed: Thu: Fri:
Vanessa Lewis [R] Mon: 1 2 3 Tue: 4 5 Wed: 6 4 Thu: 3 4 5 Fri: 6
Rhoni-Ann Parkins [R] Mon: 4 Tue: 5 6 4 Wed: 1 5 3 6 7 Thu: 1 2 3 4 Fri:
==54054==
==54054== HEAP SUMMARY:
==54054== in use at exit: 26,297 bytes in 186 blocks
==54054== total heap usage: 297 allocs, 111 frees, 37,503 bytes allocated
==54054==
==54054== LEAK SUMMARY:
==54054== definitely lost: 0 bytes in 0 blocks
==54054== indirectly lost: 0 bytes in 0 blocks
==54054== possibly lost: 0 bytes in 0 blocks
==54054== still reachable: 0 bytes in 0 blocks
==54054== suppressed: 26,297 bytes in 186 blocks
==54054==
==54054== For counts of detected and suppressed errors, rerun with: -v
==54054== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The 'suppressed' memory is an artefact of running on Mac OS X (10.11.3). I'm using GCC 5.3.0. The code is clean — it releases all the memory it allocates. (That's what the zeros for 'definitely lost', 'indirectly lost', 'possibly lost', and 'still reachable' mean.)
Note that despite using valgrind
, it is not complaining about 'out of bounds' memory accesses, but you can see that j
is printed and reaches 'j=17' for Rhoni-Ann. You're definitely not writing where you intended — the output for each prefect does not match your input, because j
is out of control. It so happens that when you write to newPtr->fses.F[j]
with j
set to 17
on a 64-bit system, you are still within bounds of the memory allocated because the struct free
occupies 45 bytes, but is padded to 48 bytes to align the 8-byte pointer nextPtr
, so F[17]
is within the pointer (which you subsequently over-write). If you are compiling with a 32-bit compiler, the story might be different. (I got some 'Conditional jump or move depends on uninitialised value(s)' errors, but not an 'out of bounds' write as I expected.)
Other problems:
- See [
while (!feof(file))
is always wrong] for why your input loop is flawed.
- You shouldn't try to close the file if you failed to open it.
- You should report errors to
stderr
, not stdout
.
- You should end messages with newlines so that they're seen.
- Both
fp
and ln
should be local variables in main
.
- You overwrite the names you store because you don't make a copy of the strings for inclusion in the structure — they all point to the array
ln
.
- You don't set the
used
element to a known value.