while loop to build up a list not ending - c

I'm trying to figure out why my code isn't working but i haven't managed so far. The code should analyse a string and build up a list containing all which letters from the english alphabet (contained in alf) are contained in that string (*s) and how many times:
` char c, *s, alf[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
the string is then acquired from a file and i've got no problem until there, i've managed to print it out correctly on the prompt so that's working. Anyway here's what i did(int variables d and num will be used later):
FILE *f=fopen("prova.txt","r");
int d,l=0,num;
while(feof(f)==0){
l++;
fscanf(f,"%c",&c);
}
s=malloc(sizeof(l*sizeof(char)));
rewind(f);
l=0;
while(feof(f)==0){
fscanf(f,"%c",s+l);
l++;
}
//"stringa acquisita" stands for "acquired string"
printf("\nstringa acquisita:%s",s);
And the string gets printed out correctly, excepting from the fact that it gets one charachter more than it should. Any advices in that direction are also welcome.
So i got to building the list. Here's what I did:
typedef struct Nodo{char car; int rip; struct Nodo* next;} Nodo;
typedef Nodo* lista;
lista head = NULL, el, temp;
for(l=0;l<26;l++){
num=0;
for(d=0;d<strlen(s);d++){
if(s[d]==alf[l]){
num++;
}
}
if(num!=0){
el = malloc(sizeof(Nodo));
if(el==NULL){
perror("error malloc\n");
exit(1);
}
el->car=alf[l];
el->rip=num;
if(head==NULL){
head=el;
el->next=NULL;
//this printf doesn't print anything on the prompt
printf("\n%c\n%d", head->car,head->rip);
}
else{
temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=el;
el->next=NULL;
}
}
//this printf prints only one time
printf("CHECKIT\n");
}
And here my code crashes. As i specified in the comments, I put two printf to get to see what's going on. The first one doesn't give anything printed on the prompt, about the second one i get one "CHECKIT" printed out and then everything crashes. Can anyone tell me what I'm missing here?
Thank you a lot.
/EDIT/
There was one sizeof more than it should have been:`
s=malloc(sizeof(l*sizeof(char)));` `
Corrected that with
s=malloc(l*sizeof(char));
everything works correctly.
Thanks everyone.

Related

C - Linked List Segmentation Fault During Display

Edit 2: I realized that I did not have a "Not found" result for any query not in the database. Changes have been made to introduce this feature. Here is the current test and test output:
Input:
3
sam
99912222
tom
11122222
harry
12299933
sam
edward
harry
Output:
Not found
=0
Not found
=0
Not found
=0
Not found
=0
sam
=99912222
Not found
=0
Not found
=0
Not found
[Infinite loop continues]
Edit: I have changed a few things in the while loop in display(). I am now getting an infinite loop printing "=0" except for the third or fourth cycle through the search. Hmmm...
By the way, thanks for the reminder of testing strings with ==. Seems like a no-brainer now.
I have done some searching and have yet to be able to understand where I have gone wrong with my code. I am working on a challenge which will result in a simple phone-book program. It will take input of a number (the number of entries to be added) then the names and associated phone numbers (no dashes or periods). After the entries have been added then the user can search for entries by name and have the number displayed in the format "name=number".
The code throws a segmentation fault with the while loop in the display() function. I assume that I am attempting to print something assigned as NULL, but I cannot figure out where I have gone wrong. Any help would be very appreciated.
Lastly, the challenge calls for me to read queries until EOF; however, this confuses me since I am to accept user input from stdin. What does EOF look like with stdin, just a register return (\n)?
(PS: This is my first attempt at linked lists, so any pointers would be greatly appreciated.)
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
void add_entry(void);
void display(void);
struct phonebook {
char name[50];
int number;
struct phonebook *next;
};
struct phonebook *firstp, *currentp, *newp;
char tempname[50];
int main() {
int N;
firstp = NULL;
scanf("%d", &N);
for (int i = 0; i < N; i++) {
add_entry();
}
display();
return 0;
}
void add_entry(void) {
newp = (struct phonebook*)malloc(sizeof(struct phonebook));
if (firstp == NULL) firstp = currentp = newp;
else {
currentp = firstp;
while (currentp->next != NULL)
currentp = currentp->next;
currentp->next = newp;
currentp = newp;
}
fgets(currentp->name, 50, stdin);
scanf("%d", &currentp->number);
currentp->next = NULL;
}
void display(void) {
while (strcmp(tempname, "\n") != 0) {
currentp = firstp;
fgets(tempname, 50, stdin);
while (strcmp(currentp->name, tempname) != 0) {
if (currentp->next == NULL) {
printf("Not found\n");
break;
}
currentp = currentp->next;
}
printf("%s=%d\n", currentp->name, currentp->number);
}
}
Your problem is that you never find the entry you're looking for. The expression currentp->name != tempname will always be true, since those are always unequal. In C, this equality test will not compile into a character-by-character comparison, but into a comparison of pointers to currentp->name and tempname. Since those are never at the same addresses, they will never be equal.
Try !strcmp(currentp->name, tempname) instead.
The reason you crash, then, is because you reach the end of the list, so that currentp will be NULL after your loop, and then you try to print NULL->name and NULL->number, actually causing the crash.
Also, on another note, you may want to start using local variables instead of using global variables for everything.
Not sure if this solves the problem, but you can't directly compare strings with != in C. You need to use if( strcmp( string1, string2 ) == 0 ) to check.
fgets doesn't take EOF (= -1) like getchar does, but it does include '\n' and pad the rest with NULL (= 0) so checking for EOF is not really helpful, but yes you can stop after \n or NULL.

Frequency of each word of text file. Error while allocating memory?

Good evening everyone!
I have started messing around with strings and pointers in C.
I want to write a programm that reads a text file, then calculating the frequency of each word and printing it.
My variables are:
FILE *fp;
char *words[N] //N defined 100
int i=0, y=0;
int *freq;
int freq_count=0;;
int word_number=0;
The code part:
for(i=0;i<word_counter;i++){
while(y<word_counter){
if(strcmp(words[i],words[y]==0){
freq1++;
} y++;
}
if(i==0){
freq=(int*)malloc(sizeof(int));
strcpy(freq, freq1); freq1=0;
}
else{
freq=(int*)realloc(freq, (i+1)*sizeof(int));
strcpy(freq, freq1); freq1=0;
}
y=0;
}
I get several errors running this...What is wrong?
Take into consideration that in words[N] i have put each word of the text by itself in each cell.
Thank you all in advance.
Maybe another array is not what you want, but still better than using realloc and condition in loop.
int freq[N];
for(i=0;i<word_counter;i++){
freq1 = 0;
for(y=0;y<word_counter;y++){
if(strcmp(words[i],words[y]==0)
freq1++;
}
freq[i] = freq1;
}

Last element value appears in first and last position when printing linked list

Happy New Year.
This question arises from a project to program a game called Laby-chiffres in C. To see the game look in the third batch of games on this link: http://www.rci-jeux.com/jeux/labychiffres/laby.swf .
Context:
I am using a linked list to store the path taken by a player through a grid of numbers. The player's aim is to find a path from the departure point to the arrival point, with a given length and given total of the numbers in the path. There is a switch statement for a menu and then one to accept the direction the player wants to move in. This works as I have code that shows that the 'passage' of the player to each number is recorded correctly
Problem:
When I try to print the path (which is a requirement of the assignment - and useful for the player to see) I print the path in the correct order, except that the last element, i.e. where the player most recently moved to, is shown at the start and the end of the list.
Example: Player makes moves through positions with values as follows. Starting with the departure point value 5 -> 8 -> 4-> 1. What is printed at each stage is:
5->
8->8->
4->8->4->
1->8->4->1->
What I have tried
I have looked at several other linked list questions, but none I have seen have the same issue that I have.
I have tried changing lots of things, but to be honest now more experimentally than anything. For example, changing the empiler function to add elements at the wrong end prints the path in the wrong order (as expected) but still prints the most recently reached number twice, just both at the start of the path rather than one at the start and one at the end.
Relevant functions
The lecturer has said explicitly that the printing needs to reverse the order so these are the printing functions:
void affiche_chemin (PLATEAU jeu, PILE pile){
afficher_pile_inverse(&jeu , jeu.chemin.P_sommet);
printf("\n");
}
void afficher_pile_inverse(PLATEAU *P_jeu, ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse(P_jeu,P_cur->P_suivant);
printf("%d->",lire_valeur_a(P_jeu,&P_cur->valeur));
}
}
lire_valeur_a reads the value in the grid, which is part of the PLATEAU structure given below and read in from a text file. This appears to work so I am not including it to try to keep the question length down.
The function to add elements is :
ELEMENT* empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
P_elt_ajoute ->P_suivant = P_liste->P_sommet;
P_liste->P_sommet = P_elt_ajoute;
return P_elt_ajoute;
}
Given the lecturers comments about needing to reverse the order to print correctly I think I am adding elements at the right end of the list.
These functions initialise the path, and allocate a new ELEMENT, and are just given for reference as used in the next extract.
void initialiser_pile(PILE *P_pile){
P_pile->P_sommet = NULL;
}
ELEMENT *nouvel_element (POSITION nouvelle_valeur){
ELEMENT *P_elt;
P_elt =(ELEMENT*) malloc(sizeof(ELEMENT));
if(P_elt ) { /* NULL equivalent to false like 0 */
P_elt->valeur = nouvelle_valeur;
P_elt->P_suivant = NULL;
}
return P_elt;
}
This code sets up the path for the first time when the text file for the game is read, so it is the first time empiler is used to add an element to a path. (This extract is from a long function using fscanf multiple times to read the game text file, and seems to work correctly.)
ELEMENT *P_sommet = nouvel_element(PLAT->dep);
if (P_sommet == NULL){
printf("Erreur d'allocation\n");
return 0;
}
initialiser_pile(&PLAT->chemin);
empiler (&PLAT->chemin,P_sommet);
PLAT->longcur = 1;
PLAT->sumcur=PLAT->grille[PLAT->dep.indl][PLAT->dep.indc];
The following function is used for adding elements during the game.
int choix_indep_jeu_update(PLATEAU *jeu, POSITION *new_pos, int pas, int dir){
ELEMENT *new = nouvel_element(*new_pos);//1 Make new element
if (new == NULL) return 0;
empiler( &jeu->chemin, new );//should add new element
jeu->longcur++;
jeu->sumcur = jeu->sumcur + lire_valeur_a(jeu, new_pos);
affiche_grille(*jeu);
affiche_chemin(*jeu,jeu->chemin);
return 1;
}
Data Structures
typedef struct position_st{
int indl;//indice of ligne
int indc;//indice of colonne
}POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
}PILE;
typedef struct plat_st{
//########## GAME FILE INFORMATION
int nl; //number of lines in grid
int nc; //number of columns in grid
POSITION dep; //position du depart: dep.indl and dep.indc
POSITION arr; //position d'arrive: arr.indl and arr.indc
int longdem; //length demanded
int sumdem; //total demanded
int ** grille; //Playing grid
//#######INFO re GAME IN PROGRESS ########
int longcur; //longueur courant
int sumcur; //totale courant
PILE chemin; //The path
}PLATEAU;
I simplified your code and it seems to be working, assuming that you want empiler() to insert elements into the front of the list, so they end up in reverse order. I added afficher_pile_inverse1() so that the last value doesn't have a "->" after it. So the error is in creating the list or there's an issue with the grid function which you did not show.
#include <stdio.h>
#include <stdlib.h>
typedef int POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
}PILE;
void empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
P_elt_ajoute ->P_suivant = P_liste->P_sommet;
P_liste->P_sommet = P_elt_ajoute;
}
void afficher_pile_inverse1(ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse1(P_cur->P_suivant);
printf("%d->",P_cur->valeur);
}
}
void afficher_pile_inverse(ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse1(P_cur->P_suivant);
printf("%d",P_cur->valeur);
}
}
void affiche_chemin (PILE pile){
afficher_pile_inverse(pile.P_sommet);
printf("\n");
}
int main(void){
ELEMENT ae[4] = {{0,NULL},{1,NULL},{2,NULL},{3,NULL}};
PILE P_liste = {NULL};
size_t i;
for(i = 0; i < 4; i++)
empiler(&P_liste, &ae[i]);
affiche_chemin(P_liste);
return 0;
}

C: lists, structures: error: structure has no member

English is not my motherlanguage, I'm sorry for any grammar mistakes in the description or in the code, I translated it in order to share it here with you.
Hello, I'm writing a little program in C and I need some help, I'm stuck with one error I can't fix, I searched here on forums and anywhere else, but nothing I found helped me. The other functions in the program work just fine.
This function reads a list of words and categories from txt file, puts it into a structure, makes a list. The user types what word he wants to delete from file, so function searches if it's there and deletes if it is.
I'm not the best with lists so there's probably a really basic, stupid problem here, any help please?
void REMOVE_WORD (int howmanylines)
{
FILE *fp;
if ((fp=fopen("words.txt", "r+w"))==NULL)
{printf("Error while opening the file!\n");
exit(1);}
else
{
typedef struct base
{
struct base *next;
char word[25];
char category[15];
} list_els;
struct base tab[howmanylines];
int i=0;
while (!feof(fp))
{
fscanf(fp, "%s", &tab[i].word);
fscanf(fp, "%s", &tab[i].category);
i++;
}
fclose(fp);
list_els *head;
list_els *el=(list_els*)malloc(sizeof(list_els));
list_els *ind=head;
while (ind->next)
{
ind=ind->next;
ind->next=el;
}
printf("What word do you want to remove?\n\n");
char word_remove[25];
scanf("%s", &word_remove);
if (strcmp(ind->next->word, word_remove)==0)
{
printf("Found:\n Word: | Category:\n %s | %s\n", ind->next->word, ind->next->category);
printf("Are you sure you want to remove?\n1)Yes\n 2)No\n\n");
int removing;
if (removing==1)
{
list_els *removed=ind->next;
ind->next=removed->next;
free(removed);
}
else if (removing==2) {printf("Removing cancelled.\n\n");}
else {printf("Wrong operation number!");}
}
else printf("Word not available in the base!\n\n");
}
}
It shows me an error 'struct base' has no member named 'word' in the line where I use the strcmp.
In this snippet
list_els *head;
list_els *el=(list_els*)malloc(sizeof(list_els));
list_els *ind=head;
while (ind->next)
{
ind=ind->next;
ind->next=el;
}
You are not initialising ind to any valid value. You probably meant to write ind = el instead of head. Also, don't cast malloc().

insert values into a binary search tree in C?

I have a .h file that contains my struct and I must NOT edit this file:
struct KnightTree
{
int key;
int level;
int balance; //will be used in AVL only, and be ignored in other cases.
KnightTree* pLeftChild;
KnightTree* pRightChild;
};
And a .cpp file that I write my code here, I've written a code to insert 2 values (key and level) into the BST:
void BSTinsert(KnightTree* tree, int k, int lvl)
{
KnightTree* newnode;
if (tree == NULL)
{
newnode->key=k;
newnode->level=lvl;
newnode->pLeftChild=NULL;
newnode->pRightChild=NULL;
tree = newnode;
}
else
{
if (tree->key > k)
BSTinsert(tree->pLeftChild,k,lvl);
else if (tree->key <= k)
BSTinsert(tree->pRightChild,k,lvl);
}
}
But when I run it, the console "thinks" itself for about 3 seconds and error pop-up said "exe has stop working" so I have to close the program. I think's simple but I'm kinda confused now... I'm using Visual C++ 6.0 (I have to use this old version...)
Thank you guys!
You have at least 2 major problems:
You do not allocate memory for your newnode, so by addressing it you just create memory corruption.
You do not attach your newly created node to the tree, assigning tree = newnode doesn't create the necessary link to the tree.
Proceed from fixing these 2 issues.
And one more thing: have you tried to actually debug it before posting the question here?

Resources