forum

Just a quick question on C (linked lists)

posted
Total Posts
16
Topic Starter
Zekira
We are going to be given a .csv file in which we don't know how many lines it contains. In that .csv, each line consists of 6 float-type integers numbers that we have to store in one node of the linked list. But seeing as how the .csv we'll be given contains an unknown amount of lines, we also wouldn't know how long our linked list should last.

OK so clearly I can't figure some stuff out. What I did previously was to create an n-number of temporary nodes (but I knew what n was back then), link them all together, then make the actual list be equal to the first temporary node. But now that I don't know how many lines I'll be facing, I can't just declare a million temporary nodes for that...

I've tried stuff out but this didn't seem to work:

 loadSpeechData(unlabelled);
do
{
data.pitchMin = getPitchMin();
data.pitchMax = getPitchMax();
data.pitchAve = getPitchAve();
data.energyMin= getEnergyMin();
data.energyMax= getEnergyMax();
data.energyAve= getEnergyAve();
strcpy(data.emotion,getEmotion());
pTemp=CreateNewNode(data);
if(pUnlabelled==NULL)
{
pUnlabelled=pTemp;

pCurrent=pUnlabelled;
}
else
{
//printf("%d", pUnlabelled->pNext);
pCurrent->pNext=CreateNewNode(data);}
pCurrent=pCurrent->pNext;
free(pTemp);
x++; i++;
}while(fetchNextData()+1);

But stuff errors at the pCurrent->pNext=CreateNewNode(data); line , because that is currently nothing. I can't also pCurrent=pCurrent->pNext; yet because as the same, pCurrent->pNext doesn't even exist yet. How can I do it such that, an empty node gets created in the loop? I was actually trying to make an array of nodes with a blank number of members, but apparently that isn't valid ._.

(btw here are the codes we use for nodes)
SPOILER
//-------------------Node Codes Here

/*
nodetype.h
*/

struct dataTag {
float pitchMin;
float pitchMax;
float pitchAve;
float energyMin;
float energyMax;
float energyAve;
char emotion[99];
};

struct nodeTag {
struct dataTag data;
struct nodeTag *pNext;
};

typedef struct dataTag dataStructType;
typedef struct nodeTag nodeStructType;

//-----End of nodetype.h

nodeStructType *InitializeList(void)
{
return NULL;
}

nodeStructType *CreateNewNode(dataStructType data)
{nodeStructType *pTemp;
if (( pTemp = malloc ( sizeof ( nodeStructType))) == NULL){
printf (" ERROR: not enough memory .\n");
exit (1);
}

/* initialize node members */
pTemp ->data = data;
pTemp ->pNext = NULL;

return pTemp ;
}

EDIT: I also had the idea of first counting the number of lines in the .csv (with the fetchNextData() function), then I'll malloc that number into the list (like pUnlabelled = malloc(sizeof(nodeStructType)*x);) , though I don't know if that'll work...
peppy
...the idea of a linked list is you DON'T need to know how many elements. You can dynamically add them to the last element.

in the simplest fashion (psuedo):

if (currentElm == null)
currentElm = CreateNewNode(data);
else
{
currentElm->next = CreateNewNode(data);
currentElm = currentElm->next;
}
Topic Starter
Zekira
Hm yeah that's what I originally thought, actually, but I'm kinda confused at the fact that won't I lose the previous nodes after I get it to next (unless of course I used a temporary list where pTemp = pCurrent)?

Hm, let me try something like that...

EDIT: Well, there's progress now, but now I'm having this problem.

  pTemp=pUnlabelled;
printf("Input unlabelled csv filename: ");
gets(unlabelled);
loadSpeechData(unlabelled);
do
{
data.pitchMin = getPitchMin();
data.pitchMax = getPitchMax();
data.pitchAve = getPitchAve();
data.energyMin= getEnergyMin();
data.energyMax= getEnergyMax();
data.energyAve= getEnergyAve();
strcpy(data.emotion,getEmotion());
if(pTemp==NULL)
{
pTemp=CreateNewNode(data); printf("1");
}
else
{
pTemp->pNext=CreateNewNode(data); printf("0");
pTemp=pTemp->pNext;}
x++; i++;
}while(fetchNextData()+1);
printf("%f", pUnlabelled->data.pitchAve);

when I try to print any value from pUnlabelled, the program errors. I thought that by making a list point to another, it would mean that anything you edit in the list will also edit the entire original list, right? But when I try to print out that last line, the program errors. It's as if pUnlabelled still didn't exist. But I think I can eventually solve this problem though, but I just wanna make sure on what's happening (since if I try to print out the address of pUnlabelled, it turns out as 0, which shouldn't be the case, right? But now pTemp has an address whereas pUnlabelled doesn't?)

EDIT2: OMG never mind, I just added pUnlabelled=pTemp; on the if statement and it suddenly worked :) apparently, pointing to NULL will make the pointer remain NULL forever unless you create something for it. This is convenient... :) many thanks!
awp
if you need to be able to browse through the list, just add a prev pointer

you won't lose earlier nodes on the linked list though, since the caller of the createLinkedList function is a pointer to the head of the list.
Topic Starter
Zekira

awp wrote:

if you need to be able to browse through the list, just add a prev pointer.
That would make it a doubly-linked list, right (like pPrev would point to the previous node)? I'm not sure how to go about on coding that, but I'll try. But for now, at least maintaining the pUnlabelled to be untouched is the best option for this.
awp
Yes, a doubly linked list. prev works kinda the same way as next.

Basically it's like ADD NEW ELEMENT()
{
if (list->next == null)
createNewNode (list->next);
if (list->next != null) //lazy error checking; it's just pseudo-code anyway
list->next->prev = list;
}


Note that your ADT should also look like the following

struct node{
data DATA;
node *prev;
node *next;
}

though I forget what sort of trickery you need to apply to use a pointer to a struct within the declaration of that struct itself. Might have to typedef it before declaring its contents. But you should already have that part figured out anyway ;D
Pasonia
This map has been deleted on the request of its creator. It is no longer available.
anonymous_old
At each step you're adding to the list. If you want to know where the start of the list is, you need to keep track of the first node somehow.

If you want to keep the list singly-lined, after this:
pTemp=CreateNewNode(data); printf("1");
add this:
pFrontOfList = pTemp;
Also, your "while(fetchNextData()+1);" looks kinda fishy. You may want to use >= 0 or != -1 instead, for clarity.

(What is pUnlabelled???)

Just a note about your style: most programmers indent their code so that after each { indention is increased one level and at each } indention is decreased one level.

So your CreateNewNode would be written more readably as:
nodeStructType *CreateNewNode(dataStructType data)
{
nodeStructType *pTemp;
if (( pTemp = malloc ( sizeof ( nodeStructType))) == NULL){
printf (" ERROR: not enough memory .\n");
exit (1);
}

/* initialize node members */
pTemp ->data = data;
pTemp ->pNext = NULL;

return pTemp ;
}
You also seem to be inconsistent with your spacing around parentheses, but I'll let that slide. ;P

What editor are you using, by the way?
Topic Starter
Zekira
Stuff actually has indentation; I just don't know why when I copy-paste them here on the text, they lose their indentations.

And yeah, I already did pUnlabelled=pTemp; after the first CreateNewNode so that pUnlabelled actually gets all the contents of pTemp and I can free(pTemp); and use it again. pUnlabelled is actually the main list I want to get.

Well I wouldn't really need to sort stuff on the linked list fortunately, but I at least have to search around them. E.G. pUnlabelled has 35 nodes while pLabelled will have 7000 -- for each of the pUnlabelled, compare it with each pLabelled data k-number of times (Euclidean Distance and KNN used, so a larger k would mean more comparison). Fortunately that's how far of linked list I'll go (unless they'll require me to use linked list on the k-number of comparisons, too? >_>), since I'm using a dynamic array (lol) for that final step:

printf("Input k");
scanf("%d", &k);
structEmoType kEmotion[k];

which oddly enough, actually works on Dev-C's compiler. (actually I can also use that trick to avoid using linked lists, but meh, most compilers don't allow declarations after functions have been called; this is the first time I'm using a compiler that can do that) (structEmoType is a typedef'd structure btw)

The fetchNextData I'm using is actually weird; it returns 0 if it's successful, and it returns -1 if it can't go to the next line of the CSV anymore, so using the +1 would yield a 1 if successful and 0 if not.

I'm using Dev-C as the main compiler btw, but I'm editting using a combination of some programs (mainly doing editting on Notepad++ to avoid syntax errors, and compiling it via Dev-C for accurate error reports... well you get the idea)
anonymous_old

Zekira wrote:

[...] I'm using a dynamic array (lol) for that final step:

printf("Input k");
scanf("%d", &k);
structEmoType kEmotion[k];

which oddly enough, actually works on Dev-C's compiler. (actually I can also use that trick to avoid using linked lists, but meh, most compilers don't allow declarations after functions have been called; this is the first time I'm using a compiler that can do that) (structEmoType is a typedef'd structure btw)
That's standard C99. That code will NOT compile as C++, however.

Zekira wrote:

The fetchNextData I'm using is actually weird; it returns 0 if it's successful, and it returns -1 if it can't go to the next line of the CSV anymore, so using the +1 would yield a 1 if successful and 0 if not.
So use != -1 instead.
Topic Starter
Zekira
This map has been deleted on the request of its creator. It is no longer available.
anonymous_old

Zekira wrote:

But that would be a waste of 16 bytes now wouldn't it? :P
What?
awp
you shouldn't be modifying a function's return codes ;(
Topic Starter
Zekira
@strager: fetchNextData()!=1 is 2 characters longer than fetchNextData()+1 rofl.

@awp: huh?
anonymous_old

Zekira wrote:

@strager: fetchNextData()!=1 is 2 characters longer than fetchNextData()+1 rofl.
Oh really now?
awp
should be !=-1, I'm guessing that was a typo

however, that doesn't matter. Like I said, you shouldn't be modifying return codes. You look at a function's return code directly (in this case, we want to know whether it is -1 or not) - doing the +1 thing is bad practice. It'll work the same if you use it properly, but it's just bad practice.
Please sign in to reply.

New reply