Im trying to read into a linked list from a textfile. The text file has the title of the book, author and year separated by ":". each book is on a separate line. the textfile entries look like this:
Absalom, Absalom!:William Faulkner:1936
After Many a Summer Dies the Swan:Aldous Huxley:1939
Ah, Wilderness!:Eugene O'Neill:1933
i'm rewriting it from scratch. comments would be appreciated.
#include <stdlib.h>
#include <stdio.h>
struct BookNode
{
char linebuffer[128];
char delim[]=":";
char * Title[50];
char * Author[50];
char * Year[5];
struct BookNode *next;
// char *token = NULL;
};
int main(void)
{
static const char booklist[]= "booklist.txt";
FILE *fr=fopen("booklist.txt", "r");
if ( fr != NULL)
{
char Title[50];
char Author[50];
char Year[5]
struct BookNode Booknode;
while (fgets(linebuffer,128, fr) != NULL &&
sscanf(line, "%49s %49s %4s",
&BookNode.Title, BookNode.Author, BookNode.Year)==3)
{
printf("%50s %50s %5s",
BookNode.Title, BookNode.Author, BookNode.Year);
}
}
There are multiple problems in your code right now.
The first one (I kid you not) is with code formatting and indentation. Your pasted sample didn't have a regular format or indentation to speak of. It's more difficult to follow code flow even in short samples such as this. Always indent your code, and pick a coding style (there are several) and stick to it.
Regarding code flow, the first problem is in error checking. Namely, you check for fopen return status, but do not take sufficient action should opening a file fail.
The second problem is a conceptual one. You don't seem to realise that an array of N characters can only hold a string with a lenght of N-1. Therefore, char[4] is hardly ever a suitable format for storing years as strings.
Now that those issues have been dealed with, here are the actual flaws that would prevent your code from working in any case:
1) The fgets function will read up until it either fills your buffer or reaches an end-of-line or an end-of-file character. Yet you still call fgets thrice to try and read a single-line entry in your file. It's unlikely what you want to do. You have to re-think the contents of your loop.
2) Your "main" loop condition is likely to be flawed. This is a very common misunderstanding of the use of feof & co. Assuming your data file contains a newline at the end (and it would only be regular for it to do so), your loop will execute one time too many.
It's better to structure your line reading loops like this:
while (fgets(buffer, BUF_SIZE, stdin)) { /* parse buffer */ }
3) You have elementary problems with memory management in your code: namely, the function addEntry fails to allocate memory to store your records. Instead, all entries in your linked list will end up pointing to the same shared buffer you allocate in your main function.
There are several ways to fix this. One is to use several calls to malloc for each member of your BookNode structs (title, author, and year). Another, perhaps preferable method is to use variable-size structs, like this:
struct BookNode {
char *title;
char *author;
char *year;
struct BookNode *next;
char buffer[]; // this shorthand requires C99
};
For each struct BookNode you allocate enough storage after them, so that you can copy there the contents of your shared buffer. title, author, and year then point to this appended storage. This way you won't end up overwriting the contents of other BookNodes in the next iteration of your loop. And you only need one free to free an entire node.
I probably didn't list all the problems in your code here. Perhaps instead of another rewrite, you should first try to tackle a smaller subproblem such as reading a single entry from stdin and building up from there?
addEntry should allocate memory for title, author and year.
Also, doing fgets three times would read 3 lines. You need one fgets per loop, and split the result to different parts (e.g. using strtok_r).
What you do is save a pointer to a static buffer. When reading the next line, this buffer is overwritten with new data.
Note that if you allocated data, you must eventually free it. The entry's destructor will need to free.
example of strtok
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char line[] = "Absalom, Absalom!:William Faulkner:1936\n";
char *p;
char * Title;
char * Author;
char * Year;
p = strtok(line, ":");
Title = strdup(p);
Author = strdup(strtok(NULL, ":"));
Year = strdup(strtok(NULL, ": \n"));
printf("\"%s\",\"%s\",\"%s\"\n", Title, Author, Year);
free(Title);
free(Author);
free(Year);
}
//result:"Absalom, Absalom!","William Faulkner","1936"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct BookNode {
char * Title;
char * Author;
char * Year;
struct BookNode * next;
} * head;
void addEntry(char * T, char * A, char * Y);
void display();
int numEntries();
//void writeBookData(struct BookNode * selection);
void free_book(struct BookNode *bnp){
if(bnp == NULL) return;
free(bnp->Title);
free(bnp->Author);
free(bnp->Year);
free_book(bnp->next);
free(bnp);
}
int main() {
FILE * fpointer;
fpointer=fopen("booklist.txt","r");
if(fpointer == NULL){
printf("Booklist could not be opened.\n");
exit(EXIT_FAILURE);
}
char Title[50+1];
char Author[50+1];
char Year[4+1];
head = NULL;
while (EOF!=fscanf(fpointer, "%50[^:]%*c%50[^:]%*c%4[^\n]%*c", Title, Author, Year)){
//note:The input number of characters is limited (Eg50), it (because minutes in excess of the limit is used in the following items) there must be large enough.
addEntry(Title, Author, Year);
}
fclose(fpointer);
int entryCount = numEntries();
printf("There are %d entries in this Book list\n", entryCount);
display();
free_book(head);
return 0;
}
void addEntry(char * T, char * A, char * Y){
struct BookNode * tempNode, * iterator;
tempNode = (struct BookNode *)malloc(sizeof(struct BookNode));
tempNode->Title = (char *)malloc(strlen(T)+1);
strcpy(tempNode->Title, T);
tempNode->Author = (char *)malloc(strlen(A)+1);
strcpy(tempNode->Author, A);
tempNode->Year = (char *)malloc(strlen(Y)+1);
strcpy(tempNode->Year, Y);
tempNode->next = NULL;
iterator = head;
if (head == NULL){
head = tempNode;
} else {
while(iterator->next != NULL){
iterator = iterator->next;
}
iterator->next = tempNode;
}
}
int numEntries(){
if(head == NULL)
return 0;
else{
int count;
struct BookNode *iterator;
for(count=0, iterator=head; iterator!=NULL; iterator = iterator->next, ++count)
;
return count;
}
}
void display(){
if(head == NULL)
return ;
else{
struct BookNode *iterator;
for(iterator=head; iterator!=NULL; iterator = iterator->next)
fprintf(stdout, "%s:%s:%s\n", iterator->Title, iterator->Author, iterator->Year);
}
}
Related
I have a struct called Person, that contains two attributes - first and last name.
After successfully dynamic allocation of memory for a variable of Person type, giving values to the attributes I would like to free the memory, but I keep getting a runtime error (the program window just crashes)
this it the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char firstName[15];
char lastName[15];
} Person;
void main(){
int len = 0;
char firstName[]="danny", lastName[]="johnes";
Person *temp = (Person*)malloc(sizeof(Person));
if (temp == NULL)
return;
len = strlen(firstName);
temp->firstName[len] = (char*)malloc(sizeof(char)*(len));
if (temp->firstName == NULL)
return;
strcpy(temp->firstName, firstName);
len = strlen(lastName);
temp->lastName[len] = (char*)malloc(sizeof(char)*(len));
if (temp->firstName == NULL)
return;
strcpy(temp->lastName, lastName);
freePerson(temp);
system("pause");
return;
}
This is the function I use to free the memory:
void freePerson(Person* ps) {
if (ps != NULL) {
free(ps->firstName);
free(ps->lastName);
free(ps);
}
}
All I want the code to do - is to store the name in a dynamically allocated structure, and free it.
Later on, I plan to replace the hard-coded names with values inputed from file.
Any ideas about the error? Thank you.
You have already space allocated for firstName, so you have to copy the name within the size constraits (15 bytes). You can do this best with snprintf like this:
snprintf(temp->firstName, sizeof(temp->firstName), "%s", firstName);
Same goes for lastName. Mind that both might be truncated if the length exceeds the size of the field.
The other option is to allocate the fields dynamically. Then your struct members should be pointers, not char arrays:
typedef struct {
char *firstName;
char *lastName;
} Person;
You can then allocate and assign the names like this:
temp->firstName = strdup(firstName); // (same for lastName)
But mind that you have to free these fields seperately if you want to free the whole item.
If you don't want to specify a maximum size for the names in the structure, you need to declare them as pointers, not arrays.
typedef struct {
char *firstName;
char *lastName;
} Person;
Then you should assign the result of malloc() to the member, without indexing it. You also need to add 1 to strlen(firstName), to make space for the null terminator.
temp->firstName = malloc(strlen(firstName)+1);
if (temp->firstName == NULL) {
return;
}
strcpy(temp->firstName, firstName);
This is how I would write this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FIRSTNAME_MAXLEN 15
#define LASTNAME_MAXLEN 15
typedef struct
{
char firstName[FIRSTNAME_MAXLEN+1];
char lastName[LASTNAME_MAXLEN+1];
} person_t;
void freePerson(person_t *ps) {
if (ps) {
free(ps); ps=NULL;
}
}
int main(){
const char *firstName="danny";
const char *lastName="johnes";
person_t *temp = calloc(1, sizeof(person_t));
if (!temp) return 1;
strncpy(temp->firstName, firstName, FIRSTNAME_MAXLEN);
strncpy(temp->lastName, lastName, LASTNAME_MAXLEN);
printf("test: firstname: %s\n", temp->firstName);
printf("test: lastname: %s\n", temp->lastName);
freePerson(temp);
return 0;
}
You allocate enough room on the heap and cleanup things with calloc(), then you copy your string with strncpy() limiting to the bytes reserved and avoiding buffer overflow. At the end you need to free() the memory returned by calloc().
Since you allocated char firstName[] and char lastName[] inside your struct you don't need to reserve other memory with malloc() for those members, and you also don't need to free() them.
At least 5 issues:
To duplicate a string, insure allocation includes enough room for the characters including the null character.
Otherwise the strcpy() writes outside the allocation which is undefined behavior (UB).
len = strlen(firstName);
// temp->firstName[len] = (char*)malloc(sizeof(char)*(len ));
temp->firstName = (char*)malloc(sizeof(char)*(len + 1));
// + 1
...
strcpy(temp->firstName, firstName);
Same for lastName.
Also assign to the pointer, not the char. #Barmar
Person members are arrays. For dynamic allocation, they should be pointers. #NthDeveloper
typedef struct {
// char firstName[15];
// char lastName[15];
char *firstName;
char *lastName;
} Person;
2nd test is wrong
// if (temp->firstName == NULL)
if (temp->lastName == NULL)
int vs. size_t.
int len = 0; assumes the string length fits in a int. Although this is exceedingly common, the type returned from strlen() is size_t. That unsigned type is right-sized for array indexing and sizing - not too wide, not too narrow. Not a key issue in this learner code.
// int len = 0;
size_t len = 0;
Tip: cast not needed. Allocate to the referenced object, not the type. Easier to code right, review and maintain.
// Person *temp = (Person*)malloc(sizeof(Person));
Person *temp = malloc(sizeof *temp);
// temp->firstName[len] = (char*)malloc(sizeof(char)*(len + 1));
temp->firstName = malloc(sizeof *(temp->firstName) * (len + 1));
Tip: Although not C standard, many platforms provide strdup() to allocated and copy strings. Sample strdup() code.
temp->firstName = strdup(firstName);
Tip: Likely the most valuable one: A good compiler with warnings well enabled should have warned about temp->firstName[len] = (char*)malloc(sizeof(char)*(len)); as it is a questionable type mis-match in the assignment. These warnings save you and us all time. Insure your next compilation has all warning enabled.
I have a text file that looks like this:
Author; Title
Author; Title
etc...
I need to open this file and read it line by line into a linked list. So far I have this, but I'm not sure how to use strtok() since it's not reading correctly.
Can someone please help me with it?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
struct node
{
char* author;
char* title;
struct node* next;
};
int main()
{
struct node *root;
struct node *c;
root = malloc( sizeof(struct node) );
root->next = 0;
c = root;
FILE *f;
f = fopen("books.txt", "r");
char line[255];
while( fgets( line, sizeof(line),f) != NULL)
{
char *token = strtok(line, ";");
while(token!=NULL)
{
fread( &c->author, sizeof( c->author ), 1, f );
token = strtok(NULL, " ");
}
fread( &c->title, sizeof( c->title ), 1, f );
//printf("%s",&c->author);
}
fclose(f);
return 0;
}
Looks wrong. You always need to:
Read enough data.
Parse the data.
Allocate memory from heap.
Copy the data.
The line variable is just a temporary buffer, while the char *author and char *title variables can't live without allocated memory. Calling fread() is an utter nonsense in your code. You already called fgets(), that's where you read the data from the file. The rest should be only string operations.
A typical way is to get char *start pointed to the beginning of the data you are interested in, char *end to the first character behind the data you are interested in, and then request heap-allocated copy using author = strndup(start, end-start) or perform the same using a combination of malloc() and memcpy() or strncpy().
Here I'm taking a sentence a checking if it is a palindrome or not.I'm doing this in the process of learning stacks.
Is there a way i can use pointers instead of char array 'sent' so that the number of input characters need not be constrained to 20 in the following code?
The code is working fine, but should there be any improvements in terms of performance or anything else?
is there anything important about pointers i should remember while using stacks, like initializing it to NULL?
Thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node
{
char data;
struct node *link;
}StackNode;
void insertData(StackNode **);
void push(StackNode **, char);
void checkData(StackNode **);
bool pop(StackNode **,char *);
char sent[20] = "";
void main()
{
StackNode *stackTop;
stackTop = NULL;
insertData(&stackTop);
checkData(&stackTop);
printf("\n");
return;
}
void insertData(StackNode **stackTop)
{
char c;
int len;
printf("Enter the Sentence\n");
while( ( ( c = getchar() ) != '\n'))
{
if( ( ( c>='a' &&c<='z') || (c>='A' && c<='Z')))
{
if((c>='A' && c<='Z'))
{
int rem;
rem = c-'A';
c='a' + rem;
}
push(stackTop,c);
len = strlen(sent);
sent[len++]=c;
sent[len]='\0';
}
}
printf("Letters are %s\n\n",sent);
}
void push(StackNode **stackTop,char c)
{
StackNode *pNew;
pNew = (StackNode*) malloc(sizeof(StackNode));
if(!pNew)
{
printf("Error 100:Out of memory\n");
exit(100);
}
pNew->data = c;
pNew->link = *stackTop;
*stackTop = pNew;
}
void checkData(StackNode **stackTop)
{
char c;
int i=0;
while(pop(stackTop,&c))
{
if( c !=sent[i++])
{
printf("Not palindrome");
return;
}
}
printf("Palindrome");
}
bool pop(StackNode **stackTop,char *c)
{
StackNode *pNew;
pNew = *stackTop;
if(pNew == NULL)
return false;
*c = pNew->data;
*stackTop = pNew->link;
printf("char poped %c\n",*c);
free(pNew);
return true;
}
As far as I know, there is no way to have an "infinite array" or an array with no limitations. However, if you use malloc you can produce a section of memory large enough that you won't need to worry about the limitations as much. I see that later on in the code you have used malloc, so I assume you know how it works. However, I would use something like this;
char * sent = malloc(sizeof(char) * 100);
if(sent == NULL){
printf("OUT OF MEMORY!");
return 1;
}
Where 100 is the buffer size you wish to have. I have used a size up to 10000 and had no problems at runtime, so that may be what you need.
In C, arrays are really pointers to statically allocated memory. It is pretty straightforward to create a pointer to an array, or any element in an array. For example, suppose we have you array char sent[20]. If we wanted to create a pointer that pointed to the exact same memory as sent, we can declare char *sentP = sent. We can now replace any use of sent with sentP. We can even create a pointer to the middle of sent: char *sentMidP = sent + 9. Now, sentMidP[0] is the same as sent[9] and sentMidP[-9] is the same as sent[0].
However, unlike sent, we can change where sentP and sentMidP point (think of sent as a constant pointer char * const, which you can't change). Thus, if you had another array char sent2[100]'. You can set the value ofsentPtosent2. What's cool about this is that you can do it *at runtime*, which effectively means that you can change the size ofsentP` depending on the size of your input.
However, there is no need to limit yourself to statically allocated input. C provides the malloc function (see here) to allocate memory at runtime. Thus, if you don't know the size of your sentence at compile time, but you will know it at runtime (say in a variable called sentenceLength), you can allocate `sentP' like the following.
char *sentP = malloc(sizeof(char) * (sentenceLength + 1)); // Plus one for the NUL termination byte in C strings
if (sentP == NULL) {
fprintf(stderr, "No more memory :(");
exit(EXIT_FAILURE);
}
Note how we now have to handle out-of-memory errors. In general, dynamic allocation introduces more overhead, because there is a possibility that we run out of memory, a requirement that we ensure we only access what was allocated, and a need to release the memory with free once we're done.
When you're done with the sentP pointer, be sure to free it with:
free(sentP);
That's it! You can use the sentP pointer we made in your code, and everything should work great. Good luck!
I'm trying to assign input to a number of structures with an array of pointers, pointing to each allocated structure. I've been attempting to fill one structure and printing it, but keep getting errors and can't find out why. Any ideas?
Thanks for the help.
/* Structure declaration */
struct personCatalog {
char name[50];
char address[50];
char cityState[50];
char zipCode[7];
} ;
//function to fill structures
void getPerson (struct personCatalog *ArrayOfPointers[]);
int main(int argc, const char * argv[])
{
struct personCatalog *pointerArray[51];
getPerson(pointerArray);
}
void getPerson (struct personCatalog *ArrayOfPointers[]){
struct personCatalog *tempPointer;
char stringCollector[512];
int maxNumberOfPeople = 51;
int num = 0;
while ((gets(stringCollector) != NULL) && (num < maxNumberOfPeople)) {
tempPointer = (struct personCatalog *) malloc(sizeof(struct personCatalog));
strcpy(tempPointer->name, stringCollector);
gets(tempPointer->address);
gets(tempPointer->cityState);
gets(tempPointer->zipCode);
ArrayOfPointers[num] = tempPointer;
num++;
printf("%s", ArrayOfPointers[num]->name);
printf("%s", ArrayOfPointers[num]->address);
printf("%s", ArrayOfPointers[num]->cityState);
printf("%s", ArrayOfPointers[num]->zipCode);
}
ArrayOfPointers[num] = '\0';
}
Corrected it a little bit, try it out, but more work to do....
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Structure declaration */
struct personCatalog {
char name[50];
char address[50];
char cityState[50];
char zipCode[7];
} ;
const int maxNumberOfPeople = 3; // was 51;
//function to fill structures
void getPerson (struct personCatalog *ArrayOfPointers[]);
int main(int argc, const char * argv[]) {
struct personCatalog *pointerArray[maxNumberOfPeople];
getPerson(pointerArray);
}
void getPerson (struct personCatalog *ArrayOfPointers[]){
struct personCatalog *tempPointer;
char stringCollector[512];
int num = 0;
while ((num < maxNumberOfPeople) && (gets(stringCollector) != 0) ) {
tempPointer = (struct personCatalog *) malloc(sizeof(struct personCatalog));
strcpy(tempPointer->name, stringCollector);
gets(tempPointer->address);
gets(tempPointer->cityState);
gets(tempPointer->zipCode);
ArrayOfPointers[num] = tempPointer;
printf("name %s\n", ArrayOfPointers[num]->name);
printf("address %s\n", ArrayOfPointers[num]->address);
printf("cityState %s\n", ArrayOfPointers[num]->cityState);
printf("zipCode %s\n", ArrayOfPointers[num]->zipCode);
num++;
}
//ArrayOfPointers[num] = '\0'; this crashed at end of array
}
Interestingly enough the code works for me with the necessary includes added:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
However, this only holds for reasonable input - the code has a bit of room for improvement, but more on that later on.
The reason you don't see any output is that you are incrementing the index num after you assign the data to the struct, but before you print it - i.e. in the loop you are always dereferencing not yet assigned poiter, in other words garbage. It is only a question of time, when you try to dereference a null pointer (or anything not in your process' memory and segfault.
Now for the flaws:
malloc() always comes with two things: a check for return value and a corresponding free()! The free() is missing, but I understand that there are/will be some other parts of code that could take care of that once the data is not needed any-more. However, you are not checking whether it doesn't return NULL (i.e. failed to allocate memory). That would bring your program down immediately (SEGFAULT due to null pointer dereference).
gets() - I suggest reading the manpage for this function (if you are on Windows, look it up on the internet) - it doesn't guarantee any limits for reading data, hence you can easily overflow your buffer. Use fgets() instead. An alternative might be scanf() with width specifier to %s.
strcpy() - the same as for gets(). Use strncpy() instead, unless you are dead-sure that it won't smash your data. Moreover, you are copying char stringCollector[512] into char personCatalog.name[50] - don't do that. It's inconsistent and if you base your bounds checks on the size of of the former, you are bound to have problems (rather sooner than later).
Last but not the least: an off-by-one error (it really is sometimes hard to get this right).
struct personCatalog *pointerArray[51];
...
int maxNumberOfPeople = 51;
if (num < maxNumberOfPeople)) {
...
num++;
...
}
ArrayOfPointers[num] = '\0'
In the worst case, you are going to write behind ArrayOfPointers (to ArrayOfPointers[51] to be specific).
Use macros and decide whether you want to NULL-terminate the array:
#define MAXPEOPLE 50
struct personCatalog *pointerArray[MAXPEOPLE+1]; /* +1 for the NULL terminator */
if (num < MAXPEOPLE)) ...
I am new to linked list in C and the problem I have is that I am trying to make a linked list of Strings, but when I try to print that list it prints first char from two different strings. I think I am messing some pointers. Any help please?
Here is my code...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
typedef struct _song{char *songTitle; char *songAuthor; char *songNote; struct _song *next;}SONG;
int songCount =4;
char SongTitle[songCount];
char AuthorName[songCount];
char SongNotes[songCount];
char songTitle0[21] = "19 problems";
char songArtist0[21]="JayZ";
char songNotes0[81]="JiggaWhoJiggaWhat";
SongTitle[0]=*songTitle0;//points at string songTitle0
AuthorName[0]=*songArtist0;
SongNotes[0]=*songNotes0;
char songTitle1[21] = "Cig Poppa";
char songArtist1[21]="Biggie Smalls";
char songNotes1[81]="I Luv it When you call me big poppa";
SongTitle[1]=*songTitle1;
AuthorName[1]=*songArtist1;
SongNotes[1]=*songNotes1;
SONG *CurrentSong, *header, *tail;
int tempCount=0;
header = NULL;
for(tempCount=0;tempCount<songCount;tempCount++)
{
CurrentSong = malloc(sizeof(struct _song));
CurrentSong->songTitle= &SongTitle[tempCount];
CurrentSong->songAuthor=&AuthorName[tempCount];
CurrentSong->songNote=&SongNotes[tempCount];
if(header == NULL)
{
header=CurrentSong;//head points to first thing in memory
}
else
{
tail->next=CurrentSong;
}
tail = CurrentSong;//always the last thing in the list
tail->next=NULL;//the next pointer is null always
}
tempCount =0;
for(CurrentSong=header; CurrentSong!=NULL; CurrentSong=CurrentSong->next)
{
printf("\n%d: ", tempCount);
printf("Title: %s ",CurrentSong->songTitle);
printf("Author: %s ",CurrentSong->songAuthor);
tempCount++;
}
return 0;
}
That's not how you're supposed to use linked lists.
It's
typedef struct list {
void *data;
struct list *next;
}
SONG *s = (SONG *)songList->data;
Likewise, for cloning strings, you need to use strdup.
E.g.
s->songTitle = strdup(SongTitle);
s->songAuthor = strdup(AuthorName);
s->songNote = strdup(SongNotes);
Don't forget to free the strings once you're done with them.
SongTitle[0]=*songTitle0;//points at string songTitle0
The comment is not true. You're copying the first character songTitle0 into the first position of SongTitle.
Your setup far too complex. You'll want to just assign songTitle0, without any * or &, to the songTitle element of the list's first link; both are of type char*, so that's just a pointer copy. Skip the SongTitle, AuthorName and SongNotes variables, they serve no purpose.
The three variables SongTitle, AuthorName and SongNotes are array of char, not array of string. You need to change their declaration to:
char* SongTitle[songCount];
char* AuthorName[songCount];
char* SongNotes[songCount];
Then, you need to update them like that:
SongTitle[0] = songTitle0;//points at string songTitle0
AuthorName[0] = songArtist0;
SongNotes[0] = songNotes0;
And when you store them in the linked list:
CurrentSong = malloc(sizeof(struct _song));
CurrentSong->songTitle = SongTitle[tempCount];
CurrentSong->songAuthor = AuthorName[tempCount];
CurrentSong->songNote = SongNotes[tempCount];