How to efficiently find last key and value in GTree - c
I need to develop a set of functions to extend glib2 GTree with:
find first element
find last
find nearest (floor, ceil, greatest less than, least greater than)
Finding first is easy. You simply stop the g_tree_foreach() calback after first. But how to find the last element without traversing the whole tree?
I thought I could use g_tree_search() with a callback that keeps returning a positive value until found, but how do I know I'm currently on the last element?
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <glib.h>
static
gint compare_int(gconstpointer p1, gconstpointer p2) {
int i1 = GPOINTER_TO_INT(p1);
int i2 = GPOINTER_TO_INT(p2);
//printf("%d %d\n", i1, i2);
return i1 == i2 ? 0 : i1 > i2 ? 1 : -1;
}
static
gboolean traverse(gpointer key, gpointer value, gpointer data) {
//int ikey = GPOINTER_TO_INT(key);
const char *sval = (const char *)value;
printf("%s\n", sval);
return FALSE;
}
static
gint find_last(gconstpointer p, gpointer user_data) {
return 1;
}
static inline const char *NULS(const char *s) {
return s ? s : "NULL";
}
int main(int argc, char *argv[]) {
GTree *tree = g_tree_new(compare_int);
g_tree_insert(tree, GINT_TO_POINTER(10), "ten");
g_tree_insert(tree, GINT_TO_POINTER(-99), "minus ninety-nine");
g_tree_insert(tree, GINT_TO_POINTER(8), "eight");
g_tree_foreach(tree, traverse, NULL);
printf("=======\n%s\n", NULS((const char*)g_tree_search(tree, (GCompareFunc)find_last, NULL)));
return 0;
}
I didn't want to fully implement my own tree, because I wanted to perform advanced search on GTree instances received from 3rd-party code.
Instead I thought that Glib authors would hardly change their internal structures these days and that I could use their fields directly.
The result is the extended version of the internal function g_tree_find_node() from gtree.c. I added two parameters to control whether I want first, last or nearest node. The algorithm for nearest nodes differs from java's TreeMap, because our node doesn't have a pointer to its parent. Full code with the unit test is here: gtreeex.c.
typedef enum {
FIND_EXACT = 0,
FIND_FLOOR = 0x2,
FIND_CEIL = 0x20,
FIND_LOWER = (FIND_FLOOR + 1),
FIND_HIGHER = (FIND_CEIL + 1)
} find_mode;
static GTreeNode *
g_tree_find_node_ex (GTree *tree,
gconstpointer key,
GCompareDataFunc key_compare,
find_mode mode
)
{
GTreeNode *node;
gint cmp;
GTreeNode *last_lesser_node = NULL;
GTreeNode *last_greater_node = NULL;
node = tree->root;
if (!node)
return NULL;
while (1)
{
cmp = key_compare (key, node->key, tree->key_compare_data);
if (cmp == 0) {
if (mode == FIND_LOWER) {
cmp = -1;
} else if (mode == FIND_HIGHER) {
cmp = 1;
} else {
return node;
}
}
if (cmp < 0)
{
if (!node->left_child) {
if ( (mode & FIND_FLOOR) ) {
return last_lesser_node; /* can be null */
}
if ( (mode & FIND_CEIL) ) {
return node;
}
return NULL;
}
last_greater_node = node;
node = node->left;
}
else
{
if (!node->right_child) {
if ( (mode & FIND_CEIL) ) {
return last_greater_node; /* can be null */
}
if ( (mode & FIND_FLOOR) ) {
return node;
}
return NULL;
}
last_lesser_node = node;
node = node->right;
}
}
}
For better performance it's possible to use preprocessor macros instead of the two new parameters, replace if with #if and include the bits header multiple times.
Related
Linux kernel windows-like event implementation
We need to implement Windows-like kernel event for Linux. These functions are intended to behave as corresponding KeInitializeEvent, KeSetEvent, KeResetEvent, KePulseEvent, and KeWaitForSingleObject from Windows kernel. Synchronization event is called auto reset here, and Notification event is called manual reset. Here is the code: Event.h #define WAIT_FOREVER -1 #define event_init(event, manual_reset, initial_state) __event_init(event, manual_reset, initial_state) #define event_set(event) __event_set(event) #define event_reset(event) __event_reset(event) #define event_pulse(event) __event_pulse(event) #define event_wait(event, ms_timeout) __event_wait(event, (ms_timeout == WAIT_FOREVER) ? (WAIT_FOREVER) : ((ms_timeout * HZ) / 1000)) typedef struct _wait_t { atomic_t b; wait_queue_head_t q; struct list_head list; } wait_t; typedef struct _event_t { struct list_head Wait; bool AutoReset; bool State; } event_t; void __event_init_lib(void); void __event_init(event_t *event, bool manual_reset, bool initial_state); bool __event_set(event_t *event); bool __event_reset(event_t *event); bool __event_pulse(event_t *event); status_t __event_wait(event_t *event, time_t timeout); Event.c wait_t g_stor[100]; spinlock_t g_lock; void __event_init_lib(void) { wait_t *ptr; for (int i = 0; i < ARRAY_SIZE(g_stor); ++i) { ptr = &g_stor[i]; atomic_set(&ptr->b, 2); init_waitqueue_head(&ptr->q); INIT_LIST_HEAD(&ptr->list); } spin_lock_init(&g_lock); } void __event_init(event_t *event, bool manual_reset, bool initial_state) { INIT_LIST_HEAD(&event->Wait); event->State = initial_state; event->AutoReset = !manual_reset; } status_t __event_wait(event_t *event, time_t timeout) { bool b; wait_t *ptr; status_t status; spin_lock(&g_lock); if (event->State) { if (event->AutoReset) event->State = false; spin_unlock(&g_lock); return s_success; } for (int i = 0; i < ARRAY_SIZE(g_stor); ++i) { ptr = &g_stor[i]; if (atomic_cmpxchg(&ptr->b, 2, 0) == 2) break; } list_add_tail(&ptr->list, &event->Wait); // note: we need to insert in the end of the list spin_unlock(&g_lock); if (timeout == WAIT_FOREVER) wait_event(ptr->q, b = (atomic_cmpxchg(&ptr->b, 1, 2) == 1)); else wait_event_timeout(ptr->q, b = (atomic_cmpxchg(&ptr->b, 1, 2) == 1), timeout); if (b) status = s_success; else status = s_timeout; return status; } bool __event_set(event_t *event) { bool PrevState; struct list_head *entry; wait_t *Wait; //if (!event->AutoReset && event->State) return true; spin_lock(&g_lock); PrevState = event->State; event->State = true; if (!PrevState && !list_empty(&event->Wait)) // check if we became signaled right now // and we have waiters { if (event->AutoReset) { entry = event->Wait.next; Wait = container_of(entry, wait_t, list); atomic_set(&Wait->b, 1); wake_up(&(Wait->q)); event->State = false; list_del(entry); } else { entry = event->Wait.next; while (entry != &event->Wait) { Wait = container_of(entry, wait_t, list); atomic_set(&Wait->b, 1); wake_up(&(Wait->q)); entry = entry->next; list_del(entry->prev); } } } spin_unlock(&g_lock); return PrevState; } bool __event_reset(event_t *event) { bool PrevState; spin_lock(&g_lock); PrevState = event->State; event->State = false; spin_unlock(&g_lock); return PrevState; } bool __event_pulse(event_t *event) { bool PrevState; struct list_head *entry; wait_t *Wait; spin_lock(&g_lock); PrevState = event->State; if (!PrevState && !list_empty(&event->Wait)) // check if we became signaled right now // and we have waiters { if (event->AutoReset) { entry = event->Wait.next; Wait = container_of(entry, wait_t, list); atomic_set(&Wait->b, 1); wake_up(&(Wait->q)); list_del(entry); } else { entry = event->Wait.next; while (entry != &event->Wait) { Wait = container_of(entry, wait_t, list); atomic_set(&Wait->b, 1); wake_up(&(Wait->q)); entry = entry->next; list_del(entry->prev); } } } event->State = false; spin_unlock(&g_lock); return PrevState; } I think each waiting thread needs its own condition variable, because if we have one condition variable and set it to true, new waiter may arrive and pass through wait_event unintentionally without even falling to sleep. So we need to maintain list of condition variables, hence to wake up correct thread we also need multiple wait queues. Also ReactOS source suggest that event maintains the list of waiters. Since we can't use thread local storage variables in kernel mode (at least in no easy way) I decided to implement array of wait blocks. When we need to insert waiter in the list we loop this array in search for free wait block. This leads me to believe that we need to use single global lock as ReactOS does (dispatcher lock), not separate lock for each event object. We need event object for our video camera driver ported from Windows. Everything seems to work fine, however frames per second sometimes drops from 14 fps to 10 (and image flickers). It led me to believe that there is something wrong with the implementation of event. If you have some suggestions, please share. Thank you.
Mors Alphabet Segmentation Fault
My code doesn't adding second node to tree. It gives me SIGSEGV fault when i'm adding the second node.I think its about strcmp function but when i'm trying to understand how it works properly at the very bottom of main func it returns -1 so i've wrote it like this.And most of my variables named Turkish so here are the translations of them to make you understand more easily dugum=node,kok=root;sol=left;sag=right;anne=mother // C program to demonstrate insert operation in binary search tree #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct tree { char *harf; char *morskodu; struct tree *left; struct tree *right; } agac; agac *kok = NULL; void ekle(char *harf, char *morskodu) { if (kok == NULL) { kok = (agac *)malloc(sizeof(agac)); kok->harf = harf; kok->morskodu = morskodu; kok->left = NULL; kok->right= NULL; } else { agac *yeni = (agac *)malloc(sizeof(agac)); yeni->harf = harf; yeni->morskodu = morskodu; yeni->left = NULL; yeni->right = NULL; agac *dugum = kok, *anne; while (dugum != NULL) { anne = dugum; if (harf <= dugum->harf) dugum = dugum->left; else dugum = dugum->right; } if (harf <= dugum->harf) anne->left = yeni; else anne->right = yeni; } } void dolas(agac *dugum) { if (dugum != NULL) { printf(" %s ", dugum->harf); dolas(dugum->left); dolas(dugum->right); } } void main() { ekle("a", "-"); ekle("b", "-."); dolas(kok); int x = strcmp("A", "B"); printf("%d", x); }
You try to dereference a NULL pointer. while (dugum != NULL) { anne = dugum; if (harf <= dugum->harf) dugum = dugum->sol; else dugum = dugum->sag; } This loop ends when dugum is NULL. Directly after you try to access dugum->harf: if (harf <= dugum->harf) This leads to undefined behavior. Also note that this comparisons compare the pointers to string literals, and is therefore also undefined behavior. To compare two C strings you should use strcmp.
Trouble using strcmp in c code
I've used strcmp before and it worked as expected, but it's not working for me in my current code. I'm reading a .csv file with the names of a bunch of famous people. "Mark Zuckerberg" is the key name that triggers things that my code will eventually do (once I get past this bump in the road and this has nothing to do with what he's been in the news for lately). I'm using a counter (queue_size) to count the number of lines in the .csv file. My goal is to save the value of the counter when strcmp(temp_name, key) == 0 but I'm not entering that if statement and I can't see why. The key appears in the .csv file as "Mark,Zuckerberg". I've tried using strtok to eliminate the comma. I was successful in doing that but strcmp() still isn't working (I adjusted the key to be "MarkZuckerberg"). I also added memset to clean the slate with each iteration but that didn't resolve the issue either. Commenting the line, temp_name[strlen(temp_name) - 1] = '\0'; doesn't appear to change anything either. I know that my struct is getting all of the names because printf (I've since deleted) and my print_list function prints as expected. I really need help finding out why I'm not entering that if statement. Thanks in advance for any help that anyone can provide. I think that it's something dumb that I'm overlooking but I just can't find it. Here's my code: #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct char_node { char name[40]; struct char_node *next; } char_node; typedef struct char_queue { char_node *q_head; char_node *q_tail; int q_size; } char_queue; void enqueue(char_queue *q_ptr, char new_name[40]); //int dequeue(char_queue *q_ptr); void print_list(char_queue *queue); int main() { int queue_size = 0; int m_z_position; char_queue queue; char temp_name[40]; char key[] = "Mark,Zuckerberg"; queue.q_head = NULL; queue.q_tail = NULL; queue.q_size = 0; FILE *file_input; file_input = fopen("party.csv", "r"); memset(temp_name, '\0', sizeof(temp_name)); while(fgets(temp_name, sizeof(temp_name), file_input)) { temp_name[strlen(temp_name) - 1] = '\0'; if(strcmp(temp_name, key) == 0) { printf("test\n"); m_z_position = queue_size; } enqueue(&queue, temp_name); memset(temp_name, '\0', sizeof(temp_name)); queue_size++; } fclose(file_input); //print_list(&queue); printf("m_z_position = %d\n", m_z_position); return 0; } void enqueue(char_queue *q_ptr, char new_name[40]) { char_node *new_node = (char_node*)malloc(sizeof(char_node)); strcpy(new_node->name, new_name); new_node->next = NULL; int num; if(q_ptr->q_size == 0) { q_ptr->q_tail = new_node; q_ptr->q_head = new_node; } else { q_ptr->q_tail->next = new_node; q_ptr->q_tail = new_node; } (q_ptr->q_size)++; return; } void print_list(char_queue *queue) { char_node *temp_list; if(queue->q_head != NULL) { temp_list = queue->q_head; while(temp_list != NULL) { printf("%s\n", temp_list->name); temp_list = temp_list->next; } } printf("\n"); return; } I can't figure out how to add the file but here are the contents of the .csv file Jeff,Bezo Bill,Gates Warren,Buffett Berkshire,Hathaway Bernard,Arnault Amancio,Ortega Carlos,Slim Charles,Koch David,Koch Larry,Ellison Michael,Bloomberg Larry,Page Sergey,Brin Jim,Walton S,Robson Alice,Walton Ma,Huateng Francoise,Bettencourt Mukesh,Ambani Jack,Ma Sheldon,Adelson Steve,Ballmer Li,Ka-shing Hui,Ka Lee,Shau Wang,Jianlin Beate,Heister Phil,Knight Jorge,Paulo Francois,Pinault Georg,Schaeffler Susanne,Klatten David,Thomson Jacqueline,Mars John,Mars Joseph,Safra Giovanni,Ferrero Dietrich,Mateschitz Michael,Dell Masayoshi,Son Serge,Dassault Stefan,Quandt Yang,Huiyan Paul,Allen Leonardo,Del Dieter,Schwarz Thomas,Peterffy Theo,Albrecht Len,Blavatnik He,Xiangjian Lui,Che James,Simons Henry,Sy Elon,Musk Hinduja,family Tadashi,Yanai Vladimir,Lisin Laurene,Powell Azim,Premji Alexey,Mordashov Lee,Kun-Hee Lakshmi,Mittal Wang,Wei Leonid,Mikhelson Charoen,Sirivadhanabhakdi Pallonji,Mistry Ray,Dalio Takemitsu,Takizaki William,Ding R,Budi Gina,Rinehart German,Larrea Carl,Icahn Stefan,Persson Michael,Hartono Joseph,Lau Thomas,A Vagit,Alekperov James,Ratcliffe Donald,Bren Iris,Fontbona Gennady,Timchenko Abigail,Johnson Vladimir,Potanin Lukas,Walton Charlene,de Zhang,Zhidong Petr,Kellner Andrey,Melnichenko David,A Klaus-Michael,Kuehne Li,Shufu Mikhail,Fridman Rupert,Murdoch Dhanin,Chearavanont Robert,Kuok Emmanuel,Besnier Shiv,Nadar Viktor,Vekselberg Aliko,Dangote Harold,Hamm Steve,Cohen Dustin,Moskovitz Marcel,Herrmann Reinhold,Wuerth Charles,Ergen Eric,Schmidt Philip,Anschutz Jim,Kennedy Blair,Parry-Okeden Alain,Wertheimer Gerard,Wertheimer Leonard,Lauder Heinz,Hermann Dilip,Shanghvi Hasso,Plattner Stephen,Schwarzman Lei,Jun Hans,Rausing Alisher,Usmanov Donald,Newhouse Peter,Woo Luis,Carlos Robin,Li Carlos,Alberto Seo,Jung-Jin Kumar,Birla Alexander,Otto Stefano,Pessina Udo,A Wang,Wenyin Andrew,Beal Lee,Man John,Menard Xu,Shihui Zhou,Hongyi Gong,Hongjia Michael,Otto David,Tepper Roman,Abramovich Liu,Qiangdong Robert,A Alberto,Bailleres Uday,Kotak Pierre,Omidyar Walter,PJ Dietmar,Hopp Graeme,Hart Eduardo,Saverin Yan,Zhi Radhakishan,Damani German,Khan Ronald,Perelman Gautam,Adani Micky,Arison Pan,Zhengmin Joseph,Tsai Thomas,Frist Mikhail,Prokhorov Galen,Weston Zong,Qinghou Eyal,Ofer Charles,Schwab Gianluigi,A Herbert,Kohler Viktor,Rashnikov Harry,Triguboff August,von Yao,Zhenhua Jan,Koum Cyrus,Poonawalla James,Goodnight Ken,Griffin Giorgio,Armani Ernesto,Bertarelli Savitri,Jindal Sunil,Mittal James,Chambers Katharine,Rayner Margaretta,Taylor Terry,Gou Gordon,Moore James,Irving Stanley,Kroenke Melker,Schorling Johann,Graf Guo,Guangchang John,Malone Xavier,Niel Silvio,Berlusconi Carl,Cook David,Geffen Hui,Wing Walter,Kwok George,Soros Edward,Johnson Massimiliana,Landini David,Duffield George,Kaiser Patrick,Soon-Shiong Zhou,Qunfei Nicky,Oppenheimer Sun,Piaoyang Wu,Yajun Alexei,Kuzmichev Stephen,Ross Vincent,Bollore Pauline,MacMillan Jay,Y Anders,Holch Eli,Broad Michael,Kadoorie Iskander,Makhmudov Frederik,Paulsen Sun,Hongbin Christy,Walton Shahid,Khan Ananda,Krishnan Carrie,Perrodo Quek,Leng Wang,Wenxue John,Doerr Patrick,Drahi Eva,Gonda Willi,A Ricardo,Salinas Suh,Kyung-Bae Pollyanna,Chu John,Fredriksen Goh,Cheng Sri,Prakash Lu,Zhiqiang Jorn,Rausing Johann,Rupert Jacques,Saade Wu,Shaoxun Leonid,Fedun Kim,Jung-Ju Sandra,Ortega Jim,Pattison Michael,Platt Chan,Laiwa David,Green Hank,A Dmitry,Rybolovlev Tsai,Eng-Meng Andreas,von Oleg,Deripaska Liu,Yongxing Ludwig,Merckle Brian,Acton John,Grayken Ann,Walton Augusto,A Finn,Rausing Mark,Zuckerberg Kirsten,Rausing Odd,Reitan Nassef,Sawiris Wee,Cho Aloys,Wobben Leon,Black Ivan,Glasenberg John,Paulson Wei,Jianjun Francis,Choi Erivan,Haub Jason,Jiang Suleiman,Kerimov Ian,A Pang,Kang David,Shaw Kushal,Pal John,A Acharya,Balkrishna Guenther,Fielmann Daniel,Gilbert Antonia,Johnson Vikram,Lal Akira,Mori Maria-Elisabeth,Schaeffler-Thumann Albert,Frere Richard,Kinder Robert,Kraft Ralph,Lauren Bruno,Schroder Nusli,Wadia Pierre,Bellon Les,Wexner Benu,Gopal David,Cheriton Ma,Jianrong Whitney,MacMillan Dan,Olsson Vivek,Chaand Teh,Hong Abdulla,bin Maria,Asuncion Ralph,Dommermuth Frank,Lowy Wolfgang,Marguerre Marijke,Mars Pamela,Mars Valerie,Mars Victoria,Mars David,A John,Gokongwei Kwon,Hyuk-Bin Nancy,Walton Lin,Yu-Ling Tom,A Robert,Rowling Dennis,Washington Yao,Liangsong Zhang,Jindong Juan,Francisco David,Sun John,Tu Martin,Viessmann Stef,Wertheimer Hansjoerg,Wyss James,Dyson Laurence,Graff Jen-Hsun,Huang Charles,Johnson Jerry,Jones Kei,Hoi Kwee,family Lee,Shin Richard,LeFrak Shigenobu,Nagamori Steven,Rales Friede,Springer Yeung,Kin-man Rinat,Akhmetov Shari,Arison Dannine,Avara Rahel,Blocher Andrew,Currie Scott,Duncan Milane,Frantz Diane,Hendricks Magdalena,Martullo-Blocher Hiroshi,Mikitani Gabe,Newell Pan,Sutong Anthony,Pratt John,Reece Randa,Williams Zhang,Bangxin
I was fixing your code, but as this comment already state, your file use "\r\n" as end line code, can be fixed with str[strcspn(str, "\r\n")] = '\0'; just after your read. But here, an other exemple of implementation of your code: #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct char_node { struct char_node *next; char name[]; } char_node; typedef struct char_queue { char_node *q_head; char_node *q_tail; size_t q_size; } char_queue; char_node *enqueue(char_queue *q_ptr, char const *new_name); void print_list(char_queue const *queue); int main(void) { char_queue queue = { .q_head = NULL, .q_tail = NULL, .q_size = 0 }; char const key[] = "Mark,Zuckerberg"; FILE *file_input = fopen("party.csv", "r"); if (file_input == NULL) { file_input = stdin; } char str[40]; size_t m_z_position = 0; while (fgets(str, sizeof str, file_input)) { str[strcspn(str, "\r\n")] = '\0'; if (strcmp(str, key) == 0) { m_z_position = queue.q_size; } enqueue(&queue, str); } fclose(file_input); print_list(&queue); printf("m_z_position = %zu\n", m_z_position); } char_node *enqueue(char_queue *q_ptr, char const *name) { size_t i = strlen(name) + 1; char_node *node = malloc(sizeof *node + i); if (!node) { return NULL; } strcpy(node->name, name); node->next = NULL; if (q_ptr->q_size++ == 0) { q_ptr->q_tail = q_ptr->q_head = node; } else { q_ptr->q_tail = q_ptr->q_tail->next = node; } return node; } void print_list(char_queue const *queue) { for (char_node const *list = queue->q_head; list; list = list->next) { printf("%s\n", list->name); } printf("\n"); }
I am afraid that .csv file contains "Mark,Zuckerberg" not Mark,Zuckerberg. In if(strcmp(temp_name, key) == 0){ key is compared with temp_name. Here key is Mark,Zuckerberg. int strcmp(const char *s1, const char *s2); The strcmp() and strncmp() functions return an integer greater than, equal to, or less than 0, according as the string s1 is greater than, equal to, or less than the string s2. strcmp will return positive number if temp_name is "Mark,Zuckerberg" because it contains additional 2 characters and, 0 if temp_name is Mark,Zuckerberg as key here is Mark,Zuckerberg clearly.
Pushing C pointer to stack, getting table
I have two functions defined in C code: static int luaMp4_load(lua_State *L){ LPP_Mp4 *ret = LPP_Mp4Load(luaL_checkstring(L, 1)); *pushMp4(L) = ret; return(1); } static int luaMp4_play(lua_State *L){ LPP_Mp4Play(*toMp4(L, 1), luaL_checknumber(L, 2)); return 0; } which are called one by one in Lua: Mp4.load(movie) Mp4:play(60) Functions pushMp4 and toMp4 are LPP_Mp4** toMp4 (lua_State *L, int index){ LPP_Mp4** handle = (LPP_Mp4**)lua_touserdata(L, index); if (handle == NULL) luaL_typerror(L, index, "Mp4"); return handle; } LPP_Mp4** pushMp4(lua_State *L) { LPP_Mp4** newvalue = (LPP_Mp4**)lua_newuserdata(L, sizeof(LPP_Mp4*)); lua_getfield(L, LUA_REGISTRYINDEX, "Mp4"); lua_setmetatable(L, -2); return newvalue; } The problem is, I'm getting a NULL handle in luaMp4_play, and it says that object in the first index of stack is table (while Mp4 expected) - inside of luaL_typerror(lua_State *L, int narg, const char *tname): const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, lua_typename(L, lua_type(L,(narg)))); How can I get rid of it? Edit: LPP_Mp4 struct: typedef struct { struct mp4_read_struct reader; Mp4AvcNalStruct nal; struct mp4_video_read_output_struct v_packet; Mp4AvcDecoderStruct *avc; Mp4AvcCscStruct *csc; } LPP_Mp4; lua_touserdata is a Lua API library function: LUA_API void *lua_touserdata (lua_State *L, int idx) { StkId o = index2adr(L, idx); switch (ttype(o)) { case LUA_TUSERDATA: return (rawuvalue(o) + 1); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } } https://github.com/lua/lua/blob/master/src/lapi.c - line 413
I was confused with return(1); in C code and had no doubt that Mp4:load() returns any value Thanks to Etan Reisner for pointing to it, worked with: mv = Mp4.load(movie) mv:play(60)
Returning error when traversing through a tree
I am trying to calculate the frequency of each node as I add them to the tree, instead of inserting a new element. For some reason when a comparing a new key to every element in the current tree, the if statement will not return 1 if they are both identical. BUT, the function will still add 1 to the frequency of the existing node. This is very puzzling to me, as I don't know why it would skip over the return 1, and continue searching through the tree. Thank you for help/advice in advance. struct: typedef struct node { char* key; struct node *left; struct node *right; int height; int frequency; }node; This is my parsing function: while(fgets(str, 100, textFile)) { token = strtok(str," \n"); while (token != NULL) { key = strdup(token); if((sameFrequency(root, key)==1)&&root!=NULL) { printf("%s", key); free(key); token = strtok (NULL, " \n"); } else { root = insert(root, key); //printf("%s\n", key); free(key); token = strtok (NULL, " \n"); } } if(ferror(textFile)) { printf("you done messed up a-a-ron"); return(0); } } Function to check the frequency of each node: int sameFrequency(node *node, char* key) { if (node != NULL) { if(strcmp(key, node->key)==0){ //This statement is true in some cases, but will not return the 1 node->frequency = node->frequency+1; printf("%d\n",node->frequency); return 1; } sameFrequency(node->left, key); sameFrequency(node->right, key); } else return 0; } Input would look something like this: wrn69 flr830 flr662 flr830 flr830 flr231 The output (after printing in preOrder): key: wrn69, frequency: 1 key: flr830, frequency: 3 key: flr662, frequency: 1 key: flr231, frequency: 1 key: flr830, frequency: 1 key: flr830, frequency: 1 I want this to print everything shown, but I don't want the same key to be inserted into the tree, just incremement its frequency by 1. TL;DR: Function skipping over return value, but still running code in the if statement, have no idea whats wrong, even after debugging.
I'm not sure what your code is trying to do, since you do not define your node struct, however your function int sameFrequency(node *node, char* key) has an obvious bug: not all code paths return a value. Reformatting a bit for clarity, you can see that if strcmp(key, key)!=0 then the return is undefined: int sameFrequency(node *node, char* key) { if (node != NULL) { if(strcmp(key, node->key)==0){ node->frequency = node->frequency+1; printf("%d\n",node->frequency); return 1; } else { sameFrequency(node->left, key); sameFrequency(node->right, key); // Continue on out of the "if" statements without returning anything. } } else { return 0; } // NO RETURN STATEMENT HERE } My compiler generates a warning for this: warning C4715: 'sameFrequency' : not all control paths return a value Surely yours must be doing so as well, unless you intentionally disabled them. Such warnings are important, and should always be cleared up before finishing your code. I'm guessing you want to do something like this, perhaps? int sameFrequency(node *node, char* key) { if (node != NULL) { if(strcmp(key, node->key)==0){ node->frequency = node->frequency+1; printf("%d\n",node->frequency); return 1; } else { int found; if ((found = sameFrequency(node->left, key)) != 0) return found; if ((found = sameFrequency(node->right, key)) != 0) return found; return 0; } } else { return 0; } } This clears the compiler warning. Incidentally, the following if statement is probably in the wrong order: if((sameFrequency(root, key)==1)&&root!=NULL) { Since && statements in C execute left to right the following makes more sense: if(root!=NULL && (sameFrequency(root, key)==1)) {