Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There are a couple of problems with your program.</p> <p>What you are doing is equivalent of:</p> <pre><code>char data[SIZE]; char *p; /* get some useful value in data */ p = data; </code></pre> <p>In <a href="https://stackoverflow.com/questions/2035066/type-of-an-array/2035255#2035255">the context of the last line</a>, <code>data</code> refers to a pointer that points to the first element of the array <code>data</code> (i.e., the line is equivalent to <code>p = &amp;data[0];</code>). So, what you just did was to assign to the pointer <code>p</code> the value of the address of the first character in <code>data</code>. Later, when you change the <em>contents</em> of <code>data</code>, the pointer to the first element of <code>data</code> is still the same (<code>data</code> still exists at the same memory location). So, all your pointers refer to the same storage, and you keep overwriting what's in the storage.</p> <p>But then why does your program work when you provide literal strings? Because each literal string in C is guaranteed to exist throughout the life of the program and has a unique address. (There is a minor exception: if you use a literal string more than once in your program, it may or may not refer to the same memory.)</p> <p>So, you should dynamically allocate memory for <code>firstName</code>, <code>lastName</code>, and <code>phoneNumber</code> members of your nodes, and remember to free them when you are done with it.</p> <pre><code>void addEntry(char *fn, char *ln, char *pn) { struct bookNode *tempNode, *iterator; tempNode = malloc(sizeof *tempNode); tempNode-&gt;firstName = malloc(strlen(fn) + 1); /* +1 for terminating 0 */ tempNode-&gt;lastName = malloc(strlen(ln) + 1); tempNode-&gt;phoneNumber = malloc(strlen(pn) + 1); /* Omitted check for malloc failures for brevity */ strcpy(tempNode-&gt;firstName, fn); strcpy(tempNode-&gt;lastName, ln); strcpy(tempNode-&gt;phoneNumber, pn); /* Now continue with what you were doing */ } </code></pre> <p>Then, you will need a corresponding <code>freeEntry</code> function to free up the space.</p> <p>Another way to do this would be to declare your <code>struct</code> differently:</p> <pre><code>#define MAX 20 struct bookNode { char firstName[MAX]; char lastName[MAX]; char phoneNumber[MAX]; struct bookNode *next; } *head; </code></pre> <p>Then, your <code>addEntry</code> function doesn't need the <code>malloc()</code> calls for <code>firstName</code>, <code>lastName</code>, and <code>phoneNumber</code>, but you still need to copy data using <code>strcpy()</code>. (To know the reason, please refer to the link above.) Your corresponding <code>freeEntry()</code> function also wouldn't need to free those members.</p> <p>Now, for the rest of your program. Your way of finding a terminating newline works, but you can simplify it by using <code>strchr()</code> standard C function. The call in your case would look like:</p> <pre><code>char *nl; if ((nl = strchr(first, '\n')) != NULL) { *nl = '\0'; } </code></pre> <p>Finally, when you fix all the above, you will find that you are getting the <a href="http://c-faq.com/stdio/feof.html" rel="nofollow noreferrer">last record twice</a> in your phone book. In C, <code>feof()</code> doesn't tell you if you are at the end of file now: it tells you that the last attempt to read from the file failed because you <em>were</em> at end of the file.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload