Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have used pointers to read a text file and add a new record to the file using pointer manipulation,but I can't see where I'm going wrong in this method with the pointers.I have set the pointers to next and prev to point to the list but when I call it,it's empty.
This is the method:

C#
struct contact *readFile(char * FName,struct contact *ptrList)
{

struct contact *head, *newContact;
FILE *fptr;
char oneLine[60];
char *sname, *fname, *phone,*company, *email;

head = ptrList;

fptr = fopen(FName,"r");

if(fptr == NULL)
{
    printf("\nCant open file!");
    return(ptrList);

}

fgets(oneLine, 55, fptr);
while(!feof(fptr))
{
    fgets(oneLine, 55, fptr);
    if(oneLine[strlen(oneLine)-1] == '\n')
    {
        oneLine[strlen(oneLine)-1] = '\0';

    }


    sname = strtok(oneLine,",");
    fname = strtok(NULL,",");
    phone = strtok(NULL,",");
    company = strtok(NULL,",");
    email = strtok(NULL,",");

    if(head == NULL)
    {
        head = (struct contact *)malloc(sizeof(struct contact));
        ptrList = head;
        strcpy(head->sname,sname);
        strcpy(head->fname,fname);
        strcpy(head->phone,phone);
        strcpy(head->company,company);
        strcpy(head->email, email);

        head->prev = NULL;
        head->next = NULL;


    }
    else
    {

        newContact = (struct contact *)malloc(sizeof(struct contact));
        head->next = newContact;
        newContact->prev = head;
        newContact->next = ptrList;
        //copy the data to the new one
        strcpy(head->sname,sname);
        strcpy(head->fname,fname);
        strcpy(head->phone,phone);
        strcpy(head->company,company);
        strcpy(head->email,email);

        //move down the list so that the head variable
        //points to the last contact
        head = newContact;

    }

  }//end while

  fclose(fptr);
  return(ptrList);
}


struct contact definition:

C#
struct contact {
        char sname[15];
        char fname[15];
        char phone[15];
        char company[15];
        char email[15];
        struct contact *prev;
        struct contact *next;
};




Any ideas as to why the list is not populating?
Posted
Updated 23-Apr-13 12:47pm
v2
Comments
Matthew Faithfull 23-Apr-13 18:26pm    
Can you add the definition of struct contact to your post. It's going to be hard to be sure of any theory on what's wrong without seeing that.
[no name] 23-Apr-13 18:46pm    
added :)

Ah, not so hard after all. I guess you copied and pasted this code
strcpy(head->sname,sname);
strcpy(head->fname,fname);
strcpy(head->phone,phone);
strcpy(head->company,company);
strcpy(head->email, email);

from the if to the else block without changing head to newContact so it just overwrites the head item again and again?
 
Share this answer
 
Comments
[no name] 23-Apr-13 18:48pm    
I added the struct definiton above.How exactly would I fix this? I changed around my pointers but Im still getting an access violation at head = *ptrList.
[no name] 23-Apr-13 18:54pm    
struct contact *readFile(char * FName,struct contact **ptrList)
{

struct contact *head, *newContact;
FILE *fptr;
char oneLine[60];
char *sname, *fname, *phone,*company, *email;

head = *ptrList;

fptr = fopen(FName,"r");

if(fptr == NULL)
{
printf("\nCant open file!");
return(ptrList);

}

fgets(oneLine, 55, fptr);
while(!feof(fptr))
{
fgets(oneLine, 55, fptr);
if(oneLine[strlen(oneLine)-1] == '\n')
{
oneLine[strlen(oneLine)-1] = '\0';

}

sname = strtok(oneLine,",");
fname = strtok(NULL,",");
phone = strtok(NULL,",");
company = strtok(NULL,",");
email = strtok(NULL,",");

if(head == NULL)
{
head = (struct contact *)malloc(sizeof(struct contact));
*ptrList = head;
strcpy(head->sname,sname);
strcpy(head->fname,fname);
strcpy(head->phone,phone);
strcpy(head->company,company);
strcpy(head->email, email);

head->prev = NULL;
head->next = NULL;


}
else
{

head->next = (struct contact *)malloc(sizeof(struct contact));
head = head->next;
head->next = NULL;
//copy the data to the new one
strcpy(head->sname,sname);
strcpy(head->fname,fname);
strcpy(head->phone,phone);
strcpy(head->company,company);
strcpy(head->email,email);



}

}//end while

fclose(fptr);
return(head);
}

int writeListToFile(char * theFile, struct contact *theList)
{
struct contact * curr;
FILE *fptr;

fptr = fopen(theFile,"w");
if (fptr == NULL)
{
printf("\noops");
return(0);

}

fprintf(fptr, "Surname, FirstName, Phone, Company, Email");
curr = theList;
while(curr != NULL)
{
fprintf(fptr,"\n%s,%s,%s,%s,%s",curr->sname,curr->fname,curr->phone,curr->company,curr->email);
curr = curr->next;
}
fclose(fptr);
return(1);


}//end writeFileToList
There are many mistakes:
1. function call should be:
struct contact *readFile(char * FName,struct contact** ptrList) // pointer to pointer
return fail if ptrList is NULLPTR. if *ptrList is a valid pointer find the trailing element and set head to it. i.e: for(head=*ptrList;head&&head->next;head=head->next);
2. head should be always the trailing element. So you should join it to the *ptrList if *ptrList is a NULLPTR. if(!*ptrList) *ptrList=head;
3. finally:

<br />
struct contact *readFile(char * FName,struct contact** ptrList)<br />
{<br />
	// open file and other stuff<br />
	if(!ptrList) return; // invalid pointer<br />
	for(head=*ptrList;head&&head->next;head=head->next);<br />
	while( ReadLine(fptr,oneLine) )<br />
	{<br />
	  sname = strtok(oneLine,",");<br />
	  fname = strtok(NULL,",");<br />
	  phone = strtok(NULL,",");<br />
	  company = strtok(NULL,",");<br />
	  email = strtok(NULL,",");<br />
	 <br />
		newContact = (struct contact *)malloc(sizeof(struct contact));<br />
		if(!newContact) break; // out of memory<br />
		newContact->prev = head;<br />
		newContact->next = 0;<br />
	<br />
		//copy the data to the new one<br />
		strcpy(newContact->sname,sname);<br />
		strcpy(newContact->fname,fname);<br />
		strcpy(newContact->phone,phone);<br />
		strcpy(newContact->company,company);<br />
		strcpy(newContact->email,email);<br />
	<br />
		head = newContact;<br />
		if(!*ptrList) *ptrList = head; // see: point 2<br />
	}<br />
}<br />


edit 2012-04-24: i will append a new improved solution. please read the comment lines!
C++
<span class="code-preprocessor">#pragma</span> once
<span class="code-preprocessor">#include</span> <stdio.h>
<span class="code-preprocessor">#include</span> <string.h>
<span class="code-preprocessor">#include</span> <stdlib.h>

<span class="code-keyword">typedef</span> <span class="code-keyword">unsigned</span> <span class="code-keyword">int</span>  HRESULT;
<span class="code-preprocessor">#define</span>  NULLPTR        0

<span class="code-comment">// node struct</span>
<span class="code-keyword">struct</span> contact
{
  <span class="code-keyword">char</span>            sname[15];
  <span class="code-keyword">char</span>            fname[15];
  <span class="code-keyword">char</span>            phone[15];
  <span class="code-keyword">char</span>            company[15];
  <span class="code-keyword">char</span>            email[15];
  <span class="code-keyword">struct</span> contact*  prev;
  <span class="code-keyword">struct</span> contact*  next;
};

<span class="code-comment">// error values</span>
<span class="code-keyword">enum</span>
{
  S_OK = 0,
  E_FAIL = -1,
  E_POINTER = -2,
};

<span class="code-comment">//////////////////////////////////////////////</span>
<span class="code-comment">// prototypes</span>

<span class="code-comment">// callback function type</span>
<span class="code-keyword">typedef</span> <span class="code-keyword">void</span> (*FNWALK)(<span class="code-keyword">struct</span> contact* node);

<span class="code-keyword">void</span>    DeletePtrList(<span class="code-keyword">struct</span> contact* ptrList);
HRESULT  ReadFile(<span class="code-keyword">const</span> <span class="code-keyword">char</span>* FName,<span class="code-keyword">struct</span> contact** ptrList);
<span class="code-keyword">void</span>    WalkChain(<span class="code-keyword">struct</span> contact* ptrList,FNWALK fnwalk);

<span class="code-comment">//////////////////////////////////////////////</span>
<span class="code-comment">// debug trace function</span>
<span class="code-keyword">void</span> trace_node(<span class="code-keyword">struct</span> contact* node)
{
  <span class="code-keyword">if</span>(node)
  {
    printf(<span class="code-string">"--- node ---\n"</span>);
    printf(<span class="code-string">"sname  : %s\n"</span>,node->sname  );
    printf(<span class="code-string">"fname  : %s\n"</span>,node->fname  );
    printf(<span class="code-string">"phone  : %s\n"</span>,node->phone  );
    printf(<span class="code-string">"company: %s\n"</span>,node->company);
    printf(<span class="code-string">"email  : %s\n"</span>,node->email  );
  }
}

<span class="code-comment">// program entry point</span>
<span class="code-keyword">int</span> main(<span class="code-keyword">int</span> argc, <span class="code-keyword">char</span>* argv[])
{
  <span class="code-comment">// command line: exe [file1] [file2] ...</span>
  <span class="code-keyword">if</span>(1<argc)
  {
    <span class="code-keyword">struct</span> contact*  ptrList = 0;
    <span class="code-comment">// try to load the file into a chained list of nodes</span>
    <span class="code-keyword">if</span>(S_OK==ReadFile(argv[1],&ptrList))
    {
      printf(<span class="code-string">"file loaded: %s\n"</span>,argv[1]);
      <span class="code-comment">// at this point you can load another file to chain it</span>
      <span class="code-keyword">if</span>(2<argc)
      {
        <span class="code-comment">// ptrList is valid. all new nodes will be chained to the trail</span>
        <span class="code-keyword">if</span>(S_OK==ReadFile(argv[2],&ptrList))
        {
          printf(<span class="code-string">"file loaded: %s\n"</span>,argv[2]);
        }
      }

      <span class="code-comment">// show all nodes loaded</span>
      WalkChain(ptrList,trace_node);
      <span class="code-comment">// free the memory for the node chain</span>
      DeletePtrList(ptrList);
      <span class="code-comment">// wait for key press</span>
      _fget<span class="code-keyword">char</span>();
    }
  }
  <span class="code-keyword">return</span> 0;
}

<span class="code-comment">// read the next line from a file</span>
HRESULT ReadLine(FILE* file,<span class="code-keyword">char</span>* line,<span class="code-keyword">const</span> <span class="code-keyword">unsigned</span> <span class="code-keyword">int</span> size)
{
  <span class="code-keyword">if</span>(feof(file)) <span class="code-keyword">return</span> E_FAIL;
  <span class="code-keyword">return</span> NULL==fgets(line, size, file) ? E_FAIL:S_OK;
}

<span class="code-comment">// read the file into a chained list</span>
HRESULT ReadFile(<span class="code-keyword">const</span> <span class="code-keyword">char</span>* FName,<span class="code-keyword">struct</span> contact** ptrList)
{
  FILE*            fptr;
  <span class="code-keyword">struct</span> contact*  head;
  <span class="code-keyword">struct</span> contact*  newContact;
  <span class="code-keyword">char</span>*            sname, *fname, *phone,*company, *email;
  <span class="code-keyword">char</span>            line[60];

  fptr = fopen(FName,<span class="code-string">"r"</span>);
   <span class="code-keyword">if</span>(NULL==fptr)
  {
    printf(<span class="code-string">"\nCant open file!"</span>);
    <span class="code-keyword">return</span> E_FAIL;
  }

  <span class="code-keyword">if</span>(!ptrList) <span class="code-keyword">return</span> E_POINTER; <span class="code-comment">// invalid result pointer</span>

  <span class="code-comment">// get the trailing node</span>
  <span class="code-keyword">for</span>(head=*ptrList;head&&head->next;head=head->next);

  <span class="code-comment">// begin to read the next line</span>
  <span class="code-keyword">while</span>(S_OK==ReadLine(fptr,line,<span class="code-keyword">sizeof</span>(line)/<span class="code-keyword">sizeof</span>(line[0])-2))
  {
    sname   = strtok(line,<span class="code-string">","</span>);
    fname   = strtok(NULL,<span class="code-string">","</span>);
    phone   = strtok(NULL,<span class="code-string">","</span>);
    company = strtok(NULL,<span class="code-string">","</span>);
    email   = strtok(NULL,<span class="code-string">","</span>);

    <span class="code-comment">// create a new node</span>
    newContact = (<span class="code-keyword">struct</span> contact *)malloc(<span class="code-keyword">sizeof</span>(<span class="code-keyword">struct</span> contact));
    <span class="code-keyword">if</span>(!newContact) <span class="code-keyword">break</span><span class="code-comment">// out of memory</span>
    <span class="code-comment">// chain the new node</span>
    newContact->prev = head;
    newContact->next = NULLPTR;

    <span class="code-comment">//copy the data to the new one</span>
    <span class="code-comment">// !! the strcpy() function is usafe - maybe buffer overruns.</span>
    <span class="code-comment">// !! thats when the source length exceeds the target buffer size.</span>
    strcpy(newContact->sname,sname);
    strcpy(newContact->fname,fname);
    strcpy(newContact->phone,phone);
    strcpy(newContact->company,company);
    strcpy(newContact->email,email);

    <span class="code-comment">// chain the nodes</span>
    <span class="code-keyword">if</span>(head) head->next = newContact;
    <span class="code-comment">// head is the trailing node</span>
    head = newContact;
    <span class="code-comment">// set the result pointer</span>
    <span class="code-keyword">if</span>(NULLPTR==*ptrList) *ptrList = head;
  }
  fclose(fptr);
  <span class="code-keyword">return</span> head ? S_OK : E_FAIL <span class="code-comment">/* something wrong */</span>;
}

<span class="code-comment">// delete the chain elements</span>
<span class="code-keyword">void</span> DeletePtrList(<span class="code-keyword">struct</span> contact* ptrList)
{
  <span class="code-keyword">struct</span> contact*  head;
  <span class="code-keyword">struct</span> contact*  next;
  <span class="code-keyword">for</span>(head = ptrList;head;head=next)
  {
    next = head->next;
    free(head);
  }
}

<span class="code-comment">// walk through the chain using a callback function</span>
<span class="code-keyword">void</span> WalkChain(<span class="code-keyword">struct</span> contact* ptrList,FNWALK fnwalk)
{
  <span class="code-keyword">struct</span> contact*  head;
  <span class="code-keyword">for</span>(head = ptrList;head;head=head->next)
  {
    fnwalk(head);
  }
}


Regards.
 
Share this answer
 
v4
Comments
[no name] 23-Apr-13 19:20pm    
This is the edited version using your code,is this correct? I seem to be getting an error still.The error is an access violation.This code has followed your above guidelines.Any ideas as to where I'm going wrong?

struct contact *readFile(char * FName,struct contact** ptrList)
{

struct contact *head, *newContact;
FILE *fptr;
char oneLine[60];
char *sname, *fname, *phone,*company, *email;

head = *ptrList;

fptr = fopen(FName,"r");

if(fptr == NULL)
{
printf("\nCant open file!");
return(ptrList);

}
fgets(oneLine, 55, fptr);
while(!feof(fptr))
{
fgets(oneLine, 55, fptr);
if(oneLine[strlen(oneLine)-1] == '\n')
{
oneLine[strlen(oneLine)-1] = '\0';

}



// open file and other stuff
if(!ptrList) return; // invalid pointer
for(head=*ptrList;head&&head->next;head=head->next);
while( ReadLine(fptr,oneLine) )
{
sname = strtok(oneLine,",");
fname = strtok(NULL,",");
phone = strtok(NULL,",");
company = strtok(NULL,",");
email = strtok(NULL,",");

newContact = (struct contact *)malloc(sizeof(struct contact));
if(!newContact) break; // out of memory
newContact->prev = head;
newContact->next = 0;

//copy the data to the new one
strcpy(newContact->sname,sname);
strcpy(newContact->fname,fname);
strcpy(newContact->phone,phone);
strcpy(newContact->company,company);
strcpy(newContact->email,email);

head = newContact;
if(!*ptrList) *ptrList = head; // see: point 2
}
}
mbue 24-Apr-13 7:25am    
Sorry i forgot to set the head->next ;(. Set after the newContact as follows if(head) head->next=newContact;.
Regards.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900