wrong output in my program using hashTable - c

I've created a hash table and I'm inserting things into it but for some reason,
after I put things on the table when I go to print from the table she makes a wrong print.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
typedef struct hash Hash;
typedef struct utilizador{
char nick[6];
char nome[26];
}
struct hash{
int quantidade, table_size;
utilizador **itens;}
Hash* criateHash(int table_size){
Hash* ha= (Hash*)malloc(sizeof(Hash));
if(ha!=NULL) {
int i;
ha->table_size = table_size;
ha->itens = (utilizador **) malloc(table_size * sizeof(utilizador *));
}
if(ha->itens==NULL) {
free(ha);
return NULL;
}
ha->quantidade=0;
for(int i=0; i< ha->table_size; i++){
ha->itens[i]=NULL;
}
return ha;
}
int string_value(char *string){
int i, valor=0;
int tam= strlen(string);
for(i=0; i< tam; i++){
valor= pow(31,tam-1 )* (int) string[i]+valor;
}
return valor;
}
int hash_function(int chave, int table_size, Hash *ha){
int position=(chave%table_size);
if (ha->itens[position]==NULL)
return position;
else {
for (int j = 0; j < table_size; j++) {
position = position + j;
if(position>table_size)
return -1;
else if (ha->itens[position] == NULL) {
return position;
}
}
return -1;
}
}
int insereHash(Hash* ha, utilizador *a, int table_size){
int i, check, chave;
check=searchHash(ha, a, table_size);
if(check==-1) {
chave=string_value(a[0].nick);
i = hash_function(chave, table_size, ha);
if (i != -1) {
ha->itens[i] = a;
ha->itens[i]->activo=true;
printf("%d %d ",check, i);
printf("+ utilizador %s criado\n",ha->itens[i]->nick );
} else if (i==-1)
printf("hash não tem espaço");
}else if (check!=-1){
printf("%d", check);
printf("+ nick %s usado previamente\n", a[0].nick);
}
}
int searchHash(Hash* ha, utilizador *a, int table_size){
int chave=string_value(a[0].nick);
int position=(chave%table_size);
if(ha->itens[position]->nick!=NULL) {
if (str_compare(ha->itens[position]->nick, a[0].nick) == 0)
return position;
else {
for (int j = 0; j < table_size; j++) {
position = position + j;
if (position > table_size)
return -1;
else if(ha->itens[position]->nick==NULL)
j++;
else if (str_compare(ha->itens[position]->nick, a[0].nick) == 0) {
return position;
}
}
}
}
return -1;
}
void input(utilizador *a, char *comando, char *aux) {
fgets(aux, 35, stdin);
sscanf(aux, "%s %s %99[^\n] ", comando, &a[0].nick, &a[0].nome);
}
int str_compare( char *string1, char *string2){
for(int i=0;i<5;i++) {
if (string1[i] != string2[i]) {
return 1;
}
}return 0;
}
int table_size=23;
utilizador ar_temp[1];
char comando[2];
char aux[35];
int pos;
Hash *ha;
int main() {
ha = criateHash(table_size);
while((strcmp (comando, "X"))!=0 && (strcmp (comando, "x")!=0)) {
input(ar_temp, comando, aux);
if ((strcmp (comando, "U")==0)) {
insereHash(ha, ar_temp, table_size);
}
}
for(int g=0; g<table_size; g++){
printf("%s ",ha->itens[g]->nick);
}
return 0;
}
the input tha i use is:
U asdre ana
U qwert joa
U qwert pedro
U hjklm gomes
U ertyu ana
U hhudr humberto
U e5sxs wis
U 2kkji toba
U p07hm rojao
U zxcvb tutu
x
and my output is:
-1 19 + utilizador asdre criado
-1 22 + utilizador qwert criado
22+ nick qwert usado previamente
-1 10 + utilizador hjklm criado
-1 11 + utilizador ertyu criado
-1 20 + utilizador hhudr criado
19+ nick e5sxs usado previamente
-1 7 + utilizador 2kkji criado
-1 5 + utilizador p07hm criado
10+ nick zxcvb usado previamente
10+ nick zxcvb usado previamente
(null) (null) (null) (null) (null) zxcvb (null) zxcvb (null) (null) zxcvb zxcvb (null) (null) (null) (null) (null)
(null) (null) zxcvb zxcvb (null) zxcvb
Process finished with exit code 0
My problem is: why the other values I inserted earlier in the table are not there and how can I resolve this?
Can you help me?

Your hash table stores pointers to instances of "struct utilizador". However, every time you call insereHash, you are passing the same ar_temp instance, which you are overwriting on every call to input.
That's why you print the same string multiple times at the end - the entries are in the right place, but you overwrote the data.
You want:
ha->itens: [.| |.|.| ]
| | |
| | +-> {"asdre","ana"}
| +---> {"qwert","joa"}
+-------> {"zxcvb","tutu"}
You have:
ha->itens: [.| |.|.| ]
| | |
+---+-+-> {"zxcvb","tutu"} <-- ar_temp

Related

Selection sort not working as expected (C language)

I have to sort an array of structs with selection sort, after I read them from a file.txt.
My algorithm is not working as expected, but it always avoid to sort them and it print the struct in decreasing order.
Example of file.txt :
P0 "ANTONIO" 2000 4
P1 "BARTOLOMEO" 1995 6
P2 "CARLO" 2020 1
P3 "DEMETRIO" 1960 2
P4 "ETTORE" 1920 3
P5 "FRANCESCO" 1950 5
Input: 2 5 3 1 6 4
Output: 4 6 1 3 5 2
What am I doing wrong?
Code below:
#include <stdio.h>
#include <stdlib.h>
#define N 7
struct persona
{
char codice[10];
char nome[30];
int anno[10];
int reddito[10];
};
int main()
{
FILE* fp;
fp = fopen("Testo.txt", "r");
struct persona* persona = malloc(sizeof(struct persona) * N);
int i = 0;
int j = 0;
if (fp != NULL)
{
while (i < N-1)
{
fscanf(fp, "%s %s %s %s",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
i++;
}
}
else
{
perror("Errore");
}
fclose(fp);
for(i=0; i<N-2; i++)
{
int min = persona[i].reddito;
for(j=i+1; j<N-1; j++)
{
if(persona[j].reddito < persona[i].reddito)
{
min = persona[j].reddito;
}
persona[N] = persona[j];
persona[j] = persona[i];
persona[i] = persona[N];
}
}
for(i=0; i<N-1;i++)
{
printf("%s\t %s\t %s\t %s\n",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
}
}
You have 6 lines in the file, but you have defined N as 7. It should be updated to 6.
while (i < N-1)
You are reading the first N-2, that is, 5 lines from the file. The 6th line is not being read. Same goes for other loops in the code using N.
int anno[10];
int reddito[10];
You do not need integer array to read the numeric fields in file, an integer should suffice.
As mentioned by #WhozCraig in the comments, the selection sort algorithm is incorrect. Here's the updated code for reference:
#include <stdio.h>
#include <stdlib.h>
#define N 6
typedef struct persona
{
char codice[10];
char nome[30];
int anno;
int reddito;
} PERSONA;
int main()
{
FILE *fp;
if ((fp = fopen("file.txt", "r")) == NULL)
{
perror("\nFile not found");
exit(1);
}
PERSONA *persona = malloc(sizeof(struct persona) * N);
int i = 0, j;
while (i < N)
{ if (fscanf(fp, "%s %s %d %d", persona[i].codice, persona[i].nome, &persona[i].anno, &persona[i].reddito) == EOF) {
break;
}
i++;
}
fclose(fp);
PERSONA temp;
/* selection sort */
for (i = 0; i < N - 1; i++)
{
int jMin = persona[i].reddito;
for (j = i + 1; j < N; j++)
{
if (persona[j].reddito < persona[jMin].reddito)
{
jMin = j;
}
}
if (jMin != i)
{
temp = persona[i];
persona[i] = persona[jMin];
persona[jMin] = temp;
}
}
for (i = 0; i < N; i++)
{
printf("\n%s\t %s\t %d\t %d", persona[i].codice, persona[i].nome, persona[i].anno, persona[i].reddito);
}
}
Further improvements:
You could also calculate the number of lines in the file in the code instead of relying on a hardcoded value N.
The statement to check sets only the min only if this statement is true
if(persona[j].reddito < persona[i].reddito)
try using the qsort function
int cmpfunc (const void * a, const void * b) {
struct persona *p1 = (struct persona *)a;
struct persona *p2 = (struct persona *)b;
if(p1->reddito < p2->reddito) return -1;
if(p1->reddito > p2->reddito) return 1;
return 0;
}
and instead of the for loop, use
qsort(persona, N, sizeof(struct persona), cmpfunc);

how to sort names in c by array

I want to know how to sort name by array.
I have a ploblem about sorting and print it. I have no idea because I'm beginner for C programing. please advice me (sorry for my english) thank you.
code that i have
#include<stdio.h>
#include<string.h>
#include <ctype.h>
int main(){
int i = 0;
char choose[10];
struct Student{
char name[61];
char surname[61];
char sex[10];
char age[3];
char id[12];
float gpa;
}student[20];
for(i=0;i<20;i++){
scanf("%s %s %s %s %s %f",student[i].name, student[i].surname, student[i].sex,student[i].age,student[i].id,student[i].gpa);
}
for(int i =0;i<20;i++){
//sort
}
}
When a task is about sorting arrays, qsort is - in most cases - your friend.
All you need to do is to provide a compare function that tells whether one element is less, equal or larger than another element. Then qsort handles the rest.
Example:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student{
char name[61];
char surname[61];
char sex[10];
char age[3];
char id[12];
float gpa;
};
void printData(struct Student* s, int n)
{
for (int i=0; i<n; ++i)
{
printf("%s %s %s %s %s %f\n",
s[i].sex, s[i].name, s[i].surname, s[i].age, s[i].id, s[i].gpa);
}
}
// Compare function for qsort
int cmp(const void *p1, const void *p2)
{
struct Student* pa = (struct Student*)p1;
struct Student* pb = (struct Student*)p2;
return strcmp(pa->name, pb->name);
}
int main(void)
{
struct Student data[3] = {
{"bbb", "bbbb", "Mr", "42", "idx", 42.0},
{"ccc", "cccc", "Ms", "42", "idy", 43.0},
{"aaa", "aaaa", "Mr", "42", "idz", 44.0}
};
printf("Before sorting:\n");
printData(data, 3);
qsort(data, 3, sizeof data[0], cmp);
printf("After sorting:\n");
printData(data, 3);
return 0;
}
Output:
Before sorting:
Mr bbb bbbb 42 idx 42.000000
Ms ccc cccc 42 idy 43.000000
Mr aaa aaaa 42 idz 44.000000
After sorting:
Mr aaa aaaa 42 idz 44.000000
Mr bbb bbbb 42 idx 42.000000
Ms ccc cccc 42 idy 43.000000
#include <stdio.h>
#include <string.h>
void main()
{
char name[10][8], tname[10][8], temp[8];
int i, j, n;
printf("Enter the value of n \n");
scanf("%d", &n);
printf("Enter %d names n \n", n);
for (i = 0; i < n; i++)
{
scanf("%s", name[i]);
strcpy(tname[i], name[i]);
}
for (i = 0; i < n - 1 ; i++)
{
for (j = i + 1; j < n; j++)
{
if (strcmp(name[i], name[j]) > 0)
{
strcpy(temp, name[i]);
strcpy(name[i], name[j]);
strcpy(name[j], temp);
}
}
}
printf("\n----------------------------------------\n");
printf("Input NamestSorted names\n");
printf("------------------------------------------\n");
for (i = 0; i < n; i++)
{
printf("%s\t\t%s\n", tname[i], name[i]);
}
printf("------------------------------------------\n");
}

Parenthesis balance program crashing(c)

Good afternoon, i am trying to do a program that checks whether if a expression has its parentheses balanced or not but because of some problem that i can't quite find out the program is crashing, could somebody help me find a way so that the program works?
In
a * b - (2 + c)
Out
Correct
or
In
)3+b * (2-c)(
Out
Incorrect
The program should check only for parantheses and i am supposed to implement linear lists on the code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SUCESSO 1 //Succes
#define FALHA -1 //Failure
#define CELULA_INVALIDA 0 //Invalid key
#define TAMANHO_MAXIMO 1000 //Max size
typedef struct{
char exp[1000];
unsigned int chave; //key
}celula; //node
typedef struct{
celula celulas[TAMANHO_MAXIMO]; //vector of nodes
unsigned int tamanho; //size of the list
}fila; //list
int criarFilaVazia(fila * ent){ //create an empty list
ent->tamanho = 0;
return(SUCESSO);
}
int insFinal(fila * ent, celula node){ //put a node on the end of the list
unsigned int i;
celula aux;
if(ent->tamanho == TAMANHO_MAXIMO){
return(FALHA);
}
else{
ent->celulas[ent->tamanho] = node;
ent->tamanho++;
return(SUCESSO);
}
}
void mostrarCelula(celula ent){ //show node
printf("%s \n", ent.exp);
}
void mostrarFila(fila ent){ //show entire list
unsigned int i;
if(ent.tamanho == 0){
printf("Fila vazia");
}
else{
printf("A fila possui %u element \n", ent.tamanho);
for(i=0; (i < ent.tamanho); i++){
printf("Elemento %u \n \n", (i+1));
mostrarCelula(ent.celulas[i]);
}
}
}
int main(){
int i, j;
fila exp;
celula aux;
scanf("%s", &aux.exp);
getchar();
aux.chave = 0;
insFinal(&exp, aux);
for(i = 0; i < strlen(exp.celulas[0].exp); i++){//checks all the array
if(exp.celulas[0].exp[i] == '('){//if there is an opening
for(j = i; j < strlen(exp.celulas[0].exp); j++){
if(exp.celulas[0].exp[j] == ')'){//should be and ending
exp.celulas[0].exp[i] = 0;//removes if balanced
exp.celulas[0].exp[j] = 0;
}
}
}
}
//checks for remaining parentheses and prints the output
for(i = 0; i < strlen(exp.celulas[0].exp); i++){
if(exp.celulas[0].exp[i] == '(' || exp.celulas[0].exp[i] == ')'){
printf("Incorreta"); //incorrect
}
else{
printf("Correta"); //correct
}
}
return 0;
}
[enter image description here][1]
Error message: https://i.stack.imgur.com/aeSn5.png
it says ex06 stopped working
Your program is crashing inside insFinal because the ent parameter passed in from main has uninitialized data. Hence, undefined behavior. Ammend these two lines at the beginning of main:
fila exp;
celula aux;
With this:
fila exp = {0};
celula aux = {0};
That will zero-init both.
The thing I don't get is what all these data structures are used for. Nor do I understand the double-nested for loop for checking the balance. Checking for a balanced set of parentheses in an expression should be as simple as this:
int areParenthesesBalanced(const char* str)
{
int balance = 0;
int len = str ? strlen(str) : 0;
for (int i = 0; i < len; i++)
{
if (str[i] == '(')
{
balance++;
}
else if (str[i] == ')')
{
balance--;
if (balance < 0)
{
return 0;
}
}
}
return (balance == 0) ? 1 : 0;
}
int main() {
char str[1000];
scanf("%s", str);
if (areParenthesesBalanced(str))
{
printf("Incorreta\n");
}
else
{
printf("Correta\n");
}
return 0;
}

I have problems to compile a method with a multidimensional array

I need to display a board who have this structure
only with O - | chars
Have this error
main.c:17:29: error: expected primary-expression before ‘]’ token
desplegar_tablero(&tablero[][],fil,col);
(still not complete the algorithm but i'm working in it)
int main(int argc, char **argv){
if (argc != 3){
fprintf(stderr, "Ejecutar como ./prog N_filas N_columnas.\n");
exit(EXIT_FAILURE);
}
int fil = 2*(atoi(argv[1]))-1;
int col = 2*(atoi(argv[2]))-1;
char tablero[fil][col];
desplegar_tablero(&tablero[][],fil,col);
}
void desplegar_tablero(char tab[][], int f, int c){
for (int i = 1; i<= f; ++f){
for (int j = 1; j <=c; ++c){
//Si fila es impar
if (i%2 == 1){
//Columna Impar
if (j%2 == 1){
// ASCII 79 = O
tab[i][j]= 79;
printf(" %u ",&tab[i][j]);
}
//Columna par
else{
// ASCII 196 = -
tab[i][j] = 196;
printf(" %u ",&tab[i][j]);
}
}
// Si fila par
else{
//Columna impar
if (j%2==1){
// ASCII 179 = |
tab[i][j]= 179;
printf(" %u ",&tab[i][j]);
}
//Columna par
else{
// ASCII 32 = espacio
tab[i][j] = 32;
printf(" %u ",&tab[i][j]);
}
}
printf("\n");
}
}
}

C - Function is not counting the correct amount of given character

as said on the title, my function is not calculating the correct amount os characters in a given string.
The function is this one:
void contar(char **texto, int *quantidade, int N)
{
int i, j, aux;
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!='\0';j++)
{
aux = (int) texto[i][j];
/* If upper case */
if(64 < aux && aux < 91)
{
aux = aux - 65;
quantidade[aux]++;
}
/* If lower case */
else if(96 < aux && aux < 123)
{
aux = aux - 71;
quantidade[aux]++;
}
}
}
for(i=0;i<52;i++)
{
printf("\n i-%d %d\n", i, quantidade[i]);
}
}
My objective is: take the character, check his number according to the ASCII table. If the number represents an Upper Case Character, I subtract it by 65 and use it as the index of my vector and increment the vector in that position. If it is a Lower Case Character, I subtract it by 71, because the last Upper Case Character is Z, which corresponds to 90. And the 'a' corresponds 97. So 90 - 65 = 25 and 97 - 65 = 32, as I dont wanna leave this gap in the vector, I do 97 - 65 - 6.
What is happening is that, for certain characters, the function is counting 1 character less.
For example, on the text below, the function counts only 5 'A', when there is actually 6.
Duvidas Frequentes E um grau do ensino superior obtido em cursos de
Graduacao, ministrados pela Universidade, destinados a alunos que
tenham concluido o ensino medio ou equivalente. A Unicamp oferece
cursos de Graduacao em diferentes areas do conhecimento. A estrutura
de ensino e pesquisa da Unicamp esta, em sua maior parte, no campus de
Barao Geraldo, em Campinas. Em Piracicaba funciona a Faculdade de
Odontologia de Piracicaba (FOP); em Limeira, a Faculdade de Tecnologia
(FT) e Faculdade de Ciencias Aplicadas (FCA); em Paulinia, o Centro de
Pesquisas Quimicas, Biologicas e Agricolas (CPQBA); em Sumare, o
Hospital Estadual; e, em Hortolandia, o Hospital Mario Covas.
The rest of the code is the following one:
#include <stdio.h>
#include <stdlib.h>
void encriptar(char **texto, int **ascii, int *quantidade, int *prioridade, int N);
void matriz_ascii(char **texto, int **ascii, int N);
void ordenar(int *quantidade, int *prioridade);
void contar(char **texto, int *quantidade, int N);
int checarMaior(int *quantidade, int i);
void troca(int **ascii, int *prioridade, int N);
int main()
{
int N, i, j, quantidade[52], prioridade[26], **ascii;
char **texto;
for(i=0;i<52;i++)
{
quantidade[i] = 0;
}
for(i=0;i<26;i++)
{
prioridade[i] = 0;
}
scanf("%d", &N);
setbuf(stdin, 0);
texto = malloc(N * sizeof(char *));
ascii = malloc(N * sizeof(char *));
for(i=0;i<N;i++)
{
texto[i] = malloc(501 * sizeof(char));
ascii[i] = malloc(501 * sizeof(char));
}
for(i=0;i<N;i++)
{
fgets(texto[i], 501, stdin);
}
encriptar(texto, ascii, quantidade, prioridade, N);
for(i=0;i<N;i++)
{
for(j=0;texto[i][j];j++)
{
texto[i][j] = (char) ascii[i][j];
}
}
printf("\n");
for(i=0;i<N;i++)
{
printf("%s", texto[i]);
}
printf("\n");
for(i=0;i<26;i++)
{
printf("%d ", prioridade[i]);
}
printf("\n");
return 0;
}
void encriptar(char **texto, int **ascii, int *quantidade, int *prioridade, int N)
{
matriz_ascii(texto, ascii, N);
contar(texto, quantidade, N);
ordenar(quantidade, prioridade);
troca(ascii, prioridade, N);
}
void matriz_ascii(char **texto, int **ascii, int N)
{
int i, j;
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!='\0';j++)
{
ascii[i][j] = (int) texto[i][j];
}
}
}
void contar(char **texto, int *quantidade, int N)
{
int i, j, aux;
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!=0;j++)
{
/*aux = (int) texto[i][j];
printf("%d ", aux); */
/* Se for maiusculo */
if(65 <= texto[i][j] && texto[i][j] <= 90)
{
aux = texto[i][j] - 65;
quantidade[aux]++;
}
/* Se for minusculo */
else if(97 <= texto[i][j] && texto[i][j] <= 122)
{
aux = texto[i][j] - 71;
quantidade[aux]++;
}
}
printf("\n");
}
/*for(i=0;i<52;i++)
{
printf("\n i-%d %d\n", i, quantidade[i]);
}*/
}
void ordenar(int *quantidade, int *prioridade)
{
int i, i_maior;
for(i=0;i<26;i++)
{
quantidade[i] += quantidade[i+26];
}
for(i=0;i<26;i++)
{
i_maior = checarMaior(quantidade, 0);
quantidade[i_maior] = -1;
prioridade[i] = i_maior;
}
}
int checarMaior(int *quantidade, int i)
{
int i_maior = i, maior = quantidade[i];
for(i=i+1;i<26;i++)
{
if(quantidade[i] > maior)
{
maior = quantidade[i];
i_maior = i;
}
else if(quantidade[i] == maior)
{
if(i < i_maior)
{
i_maior = i;
}
}
}
return i_maior;
}
void troca(int **ascii, int *prioridade, int N)
{
int i, j, i_aux, i_num, aux, valor = -1;
for(i=0;i<N;i++)
{
for(j=0;ascii[i][j];j++)
{
aux = ascii[i][j];
/* Se for maiusculo */
if(64 < aux && aux < 91)
{
aux = aux - 65;
valor = 1;
}
/* Se for minusculo */
else if(96 < aux && aux < 123)
{
aux = aux - 97;
valor = 0;
}
else
{
valor = -1;
}
if(valor != -1)
{
for(i_aux=0;i_aux<26;i_aux++)
{
if(prioridade[i_aux] == aux)
{
i_num = i_aux;
}
}
if(i_num % 2 == 0)
aux = prioridade[i_num+1];
else
aux = prioridade[i_num-1];
if(valor == 1)
ascii[i][j] = aux + 65;
else if(valor == 0)
ascii[i][j] = aux +97;
}
}
}
}
Any ideas of what I am doing wrong?
Thanks in advance!
The quantidade function seems OK. But this loop in matriz_ascii has a problem:
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!='\0';j++)
{
ascii[i][j] = (int) texto[i][j];
}
}
This does not copy the null-terminator. But later on, in troca you have a loop that runs until ascii[i][j] == 0;. That loops will run off the end of the copied values until they happen to come across a 0 in other memory, which is bad.
As you point out in comments, you malloc the wrong amount of space also (on two different lines). You could have avoided that by using this idiom:
texto = malloc(N * sizeof *texto);
ascii = malloc(N * sizeof *ascii);
for(i=0;i<N;i++)
{
texto[i] = calloc(501, sizeof *texto[i]);
ascii[i] = calloc(501, sizeof *ascii[i]);
}
The reason I use calloc is so that if your fgets lines fail (e.g. due to end of input) then your array contains blank strings, which your code handles correctly. Without that, a short input file would cause your code to operate on uninitialized memory.
Other things you can do to make your code more readable and robust:
replace magic numbers like 65 with 'A',
replace loops that set things to 0 with initialization to = { 0 };, or calloc
Check that malloc does not return NULL.
Also you should make more of an effort to debug before posting on here. If something is not working, then change your code to add extra debugging output (or use a debugger) until you find out exactly which little piece is causing the program to go from good to bad. Also you can try valgrind.

Resources