Click here to Skip to main content
15,898,035 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 :)

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.
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

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