Searchin in a stack - c

This is my code for the searching part and it's not working. Can you give me a little help on this? I'm newbie on programming and I really just suck at pointers. Thanks.
typedef struct Dictionary_Entry{
int index;
char character[100];
struct Dictionary_Entry *link;
}Dictionary_Entry;
typedef struct Dictionary{
Dictionary_Entry *top;
}Dictionary;
int check_in_dictionary(Dictionary *dictionary, char string[100], char file_char[100]){
Dictionary_Entry *runner = dictionary->top;
strcat(string, file_char);
while(runner != NULL){
if((strcmp(string, runner->character)) == 0){
break;
return runner->index;
}
}
return -1;
}

The break keyword leaves the loop, so your return runner->index line doesn't get executed. Swap the two lines (or remove break, since return will also leave the loop, in its way), and you should be fine.

Here is the corrected version with my comments starting with ////
int check_in_dictionary(Dictionary *dictionary, char string[100], char file_char[100]){
Dictionary_Entry *runner = dictionary->top;
strcat(string, file_char);
while(runner != NULL){
if((strcmp(string, runner->character)) == 0){
return runner->index; // found
//// break not neccessary here as return returns anyway
}
runner = runner->link ; //// goto next entry
}
return -1;
}
BTW strcat(string, file_char); is not necessary, you could compare directy to file_char like this strcmp(file_char, runner->character)

You need to scan the Dictionay in while loop.
something like this:
while(runner != NULL){
if((strcmp(string, runner->character)) == 0){
return runner->index;
}
runner = runner->next; /* go to next element in dictionary */
}

Related

Problem reading a stdin as file in a structured list in C

Basicaly what i want is to read a file in these case im using the stdin as my file FILE *f=stdin;
the files contains something like these
2019 - Frog and Mouse
1982 - Water and gelly
3025 - Sugar
...
I want to be able to read and print the names and the total number of characters of the names
so far i have created a structure and a list
typedef struct struct_data_uc{
int *uc_number;
char *uc_name;
} S_data_uc;
typedef struct List_uc_data{
S_data_uc uc_data;
struct List_uc_data *next;
} L_uc_data;
L_uc_data* UC_add(L_uc_data *list, L_uc_data data_uc){
L_uc_data *new;
new=(L_uc_data*)malloc(sizeof(L_uc_data));
if(new!=NULL){
(*new)=data_uc;
new->next=list;
return new;
}
return list;
}
then i created the functions to read the list and show the results and also ree the list
void UC_free(L_uc_data *list){
L_uc_data *aux;
while(list!=NULL){
aux=list->next;
free(list);
list=aux;
}
}
void UC_read(L_uc_data *data_uc, FILE *fin, FILE *fout){
char str[MAXSTR];
if(fout!=NULL)
fscanf(fin,"%d - %c",&data_uc->uc_data.uc_number,&data_uc->uc_data.uc_name);
void UC_Show(L_uc_data *data_uc, FILE *fout, int prompt){
if(prompt==0){
fprintf(fout,"%d - %c\n",
data_uc->uc_data.uc_number,
data_uc->uc_data.uc_name);
}else{
fprintf(fout,"%d - %c\n",
data_uc->uc_data.uc_number,
data_uc->uc_data.uc_name);
}
}
than my main
int main(){
FILE *f=stdin;
L_uc_data *list=NULL, *i, data_uc;
UC_read(&data_uc, stdin, stdout);
list=UC_add(list,data_uc);
for(i=list;i!=NULL;i=i->next)
UC_Show(i,f,0);
return 0;
}
but the program wont seems to work, any help?
There are quite a few errors in your code. I've tried to fix without modifying the original code too much. See the comments for details.
typedef struct struct_data_uc{
int uc_number; // Changed from int *
char *uc_name;
} S_data_uc;
typedef struct List_uc_data{
S_data_uc uc_data;
struct List_uc_data *next;
} L_uc_data;
// Allocate a new L_uc_data and insert into list
L_uc_data* UC_add(L_uc_data *list, int number, const char *name)
{
L_uc_data *new = malloc(sizeof(L_uc_data));
if (new != NULL) {
new->uc_data.uc_number = number;
// Need strdup here to alloc mem and copy
new->uc_data.uc_name = strdup(name);
new->next = list;
return new;
}
return list;
}
// Free the entire list
void UC_free(L_uc_data *list)
{
while (list) {
L_uc_data *aux = list->next;
// Free the mem from strdup
free(list->uc_data.uc_name);
free(list);
list = aux;
}
}
// Reads the entire file and returns a new list
L_uc_data * UC_read(FILE *f)
{
char line[MAXSTR];
L_uc_data *the_list = NULL;
// Using fgets to get the entire line, then sscanf to parse
while (fgets(line, MAXSTR, f)) {
int number;
char name[MAXSTR];
// Remember to check the return from sscanf
if (2 == sscanf(line, "%d - %[^\n]", &number, name)) {
// Add to list
the_list = UC_add(the_list, number, name);
}
}
return the_list;
}
// Print the entire list
void UC_show(L_uc_data *list, FILE *fout)
{
while (list) {
fprintf(fout, "%d - %s\n", list->uc_data.uc_number, list->uc_data.uc_name);
list = list->next;
}
}
int main()
{
L_uc_data *list = UC_read(stdin);
UC_show(list, stdout);
UC_free(list);
return 0;
}
You're making (at least) 2 mistakes. First, you are passing stdin as the argument to UC_Show, where an attempt is made to write to it. 2nd, you are not checking the value returned by printf, which is almost certainly going to indicate an error and set errno to EBADF to tell you exactly what the error is. You cannot write to stdin.

How to access recursive structure with pointers

I am getting a really strange error in my C program and therefore I need your help guys! So I have a recursive structure called path, where sometimes I store the address of the "parent" path in the structure field mother:
typedef struct path{
struct path* mother;
struct path** children;
int length;
uint8_t* inf;
} path;
So in my example I just generate one path like this:
int child_num=2;
int bytes=10;
path* my_path=malloc(sizeof(path));
if (path==NULL) throw error...
my_path->inf=malloc(sizeof(uint8_t)*bytes);
memset(my_path->inf, 4, bytes);
my_path->children=malloc(sizeof(path*)*child_num);
for(int i=0; i<child_num; i++){
my_path->children[i]->mother=my_path;
my_path->children[i]->inf=malloc(sizeof(uint8_t)*bytes);
memset(my_path->children[i]->inf, 5, bytes);
}
So now since I stored the link to the parent structure, I want to use another helping pointer to get access to its information:
path* my_pointer=my_path->children[0]->mother; //this is just for the example
So i checked the addresses and everything seems to be alright, but if I know use the pointer in another method, pointing to the field "inf", it works if I use the variable "path" so:
method(path->inf, bytes);
it is fine, but as soon as I do:
method(my_pointer->inf, bytes);
the method crashes at the marked line:
void method(uint8_t* element, int bytes) {
if (element==NULL) ... //<=== here it crashes
//do something
}
I really dont get what I am doing wrong, I printed the addresses and everything seems to be good, even if I access a certain byte over the variable "my_pointer", so like
my_pointer->inf[1]
it returns me the corresponding value, but in the separate method it doesnt work.
Like the comments indicate we can't exactly answer your question with the information provided, but we can point you in the right direction.
First, I noticed in your examples that you're using path as a variable name to a typedef'd path structure. You need to either be more verbose with your variable names or actually copy paste some code to make sure that we can look at the actual problem, because it could simply be an issue with naming.
All in all I think it would do you a world of good to employ a bit of code hygiene. Organize some of the functions you use for data structure overhead at file scope:
static int path_alloc(path* p);
static int path_alloc_kids(path* p, int num);
static int path_alloc(path* p) {
if(p == NULL) { return -1; }
p = (path*)malloc(sizeof(path));
if(p == NULL) { return -2; }
return 0;
}
static int path_alloc_kids(path* p, int num) {
if(p == NULL || num <= 0) { return -1; }
if(!path_alloc(p)) { /* Easier to read and understand, no error handling here to muddle things up */
/* You don't actually need a path**, do you? Think of char *argv[] a.k.a. char **argv, is that what you're actually going for? */
p->children = (path*)malloc(sizeof(path) * num);
if(p->children == NULL) { return -2; }
p->length = num;
} else { return -1; } /* Simple */
return 0;
}
This makes it a LOT easier to understand your code, which is the main issue with pointers. Add in some methods to free the allocated children and roots and you're set to use this path structure in a relatively abstracted way. You may want to consider using a path and a path_node in a linked-list fashion, that way you only allocate what you need.
struct spath_node; /* So it knows of itself */
typedef struct spath_node {
struct spath_node *parent;
struct spath_node *next;
uint8_t *data;
int data_size;
} path_node;
Then allocate by passing in a data size and parent, a NULL parent could mean it's a root node.
static int path_alloc_node(path_node *parent, int data_size, uint8_t *data);
This makes for relatively slow insert/traversal, but easier to understand where you went wrong.
EDIT: To be clear, this is how we would add children to the linked-list example:
static int path_alloc_node(path_node *parent, int data_size, uint8_t *data) {
path_node *tmp;
if(parent == NULL || data_size <= 0) { return -1; }
if(parent->next != NULL) { return -3; }
tmp = (path_node*)malloc(sizeof(path_node));
if(tmp == NULL) { return -2; }
else parent->next = tmp;
if(data == NULL) { /* Assume the caller is requesting a new data block of the given size */
data = (uint8_t*)malloc((size_t)data_size);
if(data == NULL) { return -2; }
}
parent->next->data = data;
parent->next->data_size = data_size;
parent->next->next = NULL;
parent->next->parent = parent;
return 0;
}

Searching node in list both works and does not work

This might be a bad question but I'm completly lost. I have this code:
struct nodoTemas* search_in_list(char * val, struct nodoTemas **prev,struct nodoTemas *head/*, struct nodoTemas *curr*/)
{
struct nodoTemas *ptr = head;
struct nodoTemas *tmp = NULL;
bool found = false;
printf("\n Searching the list for value [%s] \n",val);
while(ptr != NULL)
{
if(ptr->nombreTema == val)
{
found = true;
break;
}
else
{
tmp = ptr;
ptr = ptr->next;
}
}
if(true == found)
{
if(prev)
*prev = tmp;
return ptr;
}
else
{
return NULL;//si no ha encontrado nada devuelve NULL
}
}
And I test it, in a specific file to test it, like this:
char * var="tema1";
char * var2="tema2";
head=add_to_list(var,true,head,curr);
curr=head;
curr=add_to_list(var2,true,head,curr);
struct nodoTemas* nodoBuscado;
char *temaABuscar="tema4";
nodoBuscado=search_in_list(temaABuscar, NULL,head);
if(nodoBuscado!=NULL)
printf("VALOR DEL NODO %s\n",nodoBuscado->nombreTema);
And it works perfectly fine no matter what I do. If I look for something that exists it prints it and so on. Now on my main file I get the char * my server gets the char * from a message. I thought this failed so I tried several things, this being one of them:
printf("MATCH %d \n" , strcmp(temaRecibido,head->nombreTema));
And I get a 0 as a result. So the strings are the same. But the search fails, in this other file. I've printed it, I've checked for their strlen sizes, and it all matches.
So I believe I'm looking at the wrong side but I cannot understand why code that is working in one place does not work in other. Should I look for the mistake somewhere else? Also, if I do strlen of a string WITH null and one without null, are they the same size? man says it excludes the terminating byte but I am unsure about this.
I'm sorry if the post is lacking I wasn't sure how to properly present it.
You cannot compare strings like
if(ptr->nombreTema == val)
You should use strcmp
if(strcmp(ptr->nombreTema, val) == 0)
im not sure if you can compare strings in C that way...
if you search for the string "tema1" instead a pointer to "tema1" what is the result?
also, check this http://www.wikihow.com/Compare-Two-Strings-in-C-Programming.

C, Code:Block, yet another sigsegv, lists

Good Day everyone,
Got this exercize from my prof webspace. I have this kind of text file:
Simon Phillips 30
Neil Peart 45
Vinnie Colaiuta 50
I want to store this into a list so here is my code:
struct listplot {
char name[25];
char sur[25];
int age;
struct listplot *next;
};
typedef struct listplot EL;
EL *list;
int filescan(EL *current)
{
FILE *in;
int count=0;
in=fopen("persone.txt", "r");
if (ferror(in))
{
printf("File Error\n");
return count;
}
do
{
current=malloc(sizeof(EL));
fscanf(in,"%s%s%d", current->name, current->sur, &current->age);
current->next=NULL;
if (!feof(in)) count=count+filescan(current->next);
}
while (!feof(in));
return count;
}
In main i have:
int count=filescan(list);
This code won't work.
In debug it seems that the 'do' loop goes infinite, but eventually the program crashes with segmentation fault.
Can anybody help me with this?
Thank you a lot.
Many improvents to make it more robust:
Initialize this element properly:
EL* list_header = NULL; /* Points to first element */
Increase level of indirection here:
int filescan(EL** current)
{
In the main function you have to pass the address of the list_header:
count = filescan(&list_header)
Move this section into a single function whose only concern is to open the file.
FILE *in;
int count=0;
in=fopen("persone.txt", "r");
if (ferror(in))
{
printf("File Error\n");
return count;
}
And return 0 if in is NULL or in error.
do
{
First do the scan and check if it fills 3 parameters by
EL els = {0}; /* element for scanning */
if (fscanf(in,"%s%s%d", els.name, els.sur, &els.age) == 3)
{
Move this in to a function that creates/fills/copies a new EL for a successfully filled els
current->next = create_duplicate_EL_for(els);
/* the duplicator should malloc and fill, and set next to NULL */
current=malloc(sizeof(EL));
// some strcpys //
current->next=NULL;
Apparently you want count so increase it.
And for looping, set
current = current->next;
Complete your scanf branch with an else if we don't find exactly 3 elements:
else
{
/* debug/error log code here */
}
}
while (!feof(in));
return count;

strcmp always producing the same result

I have a LinkedList implementation which holds structs which contain words and a few other pieces of information. In the LinkedList I have a function which checks to see if a word is
already contained in one of the structs in the list. Problem is, this returns 0 every single time. Any idea why this is?
This compiles completely fine and every single aspect of this function works besides the if(strcmp(ll->value->word, word)) statement.
EDIT: Sorry, forgot to add in the !
int llContains(LinkedList* ll, char* word){
LinkedList* nn= ll;
if(nn != NULL){
for(int i=0; nn != NULL; i++){
if(!strcmp(ll->value->word, word)){
return i;
}
nn = nn->next;
}
} else {
return -1;
}
}
The code has undefined behaviour as there is a path through the function that does not have an explicit return: if the return within the for is not executed.
Note that strcmp() returns 0 when strings equal so the if within the for will be "true" if the strings do not match. This means if the first entry in the list does not equal then 0 will be returned.
Change to:
int llContains(LinkedList* ll, char* word){
LinkedList* nn= ll;
if(nn != NULL){
for(int i=0; nn != NULL; i++){
if(strcmp(ll->value->word, word) == 0){
return i;
}
nn = nn->next;
}
}
/* ALWAYS return a value. */
return -1;
}
Add some debug info before "return i"
int llContains(LinkedList* ll, char* word){
LinkedList* nn= ll;
if(nn != NULL){
for(int i=0; nn != NULL; i++){
if(strcmp(ll->value->word, word)){
printf("Linked->word : %s, word : %s\n",ll->value->word, word);
return i;
}
nn = nn->next;
}
} else {
return -1;
}
}
Try this, and let's see what you have

Resources