I have a small program to handle a list of rabbits (name, district, participation count) stored in an array of pointers (Rabbit** iterator). I'd like to implement the following methods: add, delete and modify a rabbit, list all the rabbits or list by district.
When I compare for example the name of the rabbits in the list with strcmp() it doesn't return 0 when the names are equal. How can I solve this problem?
The Rabbit struct:
typedef struct Rabbit {
char* name;
char* district;
unsigned part_count;
} Rabbit;
The delete method:
bool delete_rabbit(char* delete_name)
{
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL && strcmp(iterator[i]->name, delete_name) == 0) {
free(iterator[i]);
iterator[i] = NULL;
count--;
return true;
}
}
return false;
}
The list by district method:
void list_by_district(char* district)
{
unsigned counter = 0;
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL && strcmp(iterator[i]->district, district) == 0) {
counter++;
printf("\n%u. Rabbit:\n", counter);
printf("Name: %s\nDistrict: %s\nParticipation count: %u\n", iterator[i]->name, iterator[i]->district, iterator[i]->part_count);
}
}
}
The modify method is similar to the delete method except it only changes the values.
The corresponding code snippets from main:
Rabbit** iterator;
unsigned size = 10, count = 0;
int main()
{
iterator = (Rabbit**)malloc(sizeof(Rabbit*) * 10);
...
do {
...
switch (input) {
case 'a':
if (count == size) iterator = allocate_more_memory();
...
iterator[count++] = add_rabbit(new_name, new_district, new_part_count);
break;
case 'd':
if (size == count + 6) iterator = allocate_less_memory();
do {
printf("Enter name to be deleted: ");
scanf("%[^\n]", delete_name);
getchar();
if (strlen(delete_name) >= 30) printf("Name only has 30 or less characters!\n");
} while (strlen(delete_name) >= 30);
if (!delete_rabbit(delete_name)) printf("\nThere's no rabbit in the list with this name.\n");
break;
...
}
} while (input != 'x');
...
free(iterator);
return 0;
}
EDIT:
The add method:
Rabbit* add_rabbit(char* new_name, char* new_district, unsigned new_part_count)
{
Rabbit* new_rabbit = (Rabbit*)malloc(sizeof(Rabbit));
if (new_rabbit) {
new_rabbit->name = (char*)malloc((strlen(new_name) + 1) * sizeof(char));
new_rabbit->district = (char*)malloc((strlen(new_district) + 1) * sizeof(char));
strcpy(new_rabbit->name, new_name);
strcpy(new_rabbit->district, district);
new_rabbit->part_count = new_part_count;
}
return new_rabbit;
}
The allocate less memory method:
Rabbit** allocate_less_memory()
{
Rabbit** new_iterator = (Rabbit**)malloc(sizeof(Rabbit*) * (size - 5));
if (new_iterator) {
unsigned counter = 0;
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL) {
new_iterator[counter++] = iterator[i];
}
}
size -= 5;
free(iterator);
return new_iterator;
}
return NULL;
}
Related
can you help me with the size of the digits, for example, when I enter 01234, then everything works as it should, but it shouldn’t, the limit of digits should be within four.When I enter some four-digit number, everything works as it should work. But when some five-digit, six-digit or even more, then everything works as if it should be, but it should not work like that. And when I enter numbers that are less than four-digit, for example 123 , then it gives an error and it's good. But when I enter numbers that are more than four digits, it does not give an error and works as if it should be so.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct s_mastermind {
int my_attempt;
char* my_code;
} my_mastermind;
my_mastermind* settings_function(my_mastermind* mastermind, int argc, char** argv);
int checking_for_correctness_num(char* _string);
int wrong_input(int progress,char* num_code);
my_mastermind* my_function();
int check_function(char* string);
char* input_function();
int mis_placed_pieces(char* bit, char* num_code);
int well_placed_pieces(char* bit, char* num_code);
int code_checker(char* bit, char* num_code);
char* size_of_function(char* strye);
char* my_strcpy(char* num1, char* num2) {
for(int i = 0; num2[i] != 0; i++) {
num1[i] = num2[i];
}
return num1;
}
int my_strlen(char* num1) {
return (*num1) ? my_strlen(++num1) + 1 : 0;
}
my_mastermind* my_function() {
my_mastermind* num = malloc(sizeof(my_mastermind));
num->my_code = malloc(5);
num->my_code[4] = '\0';
my_strcpy(num->my_code, "");
num->my_attempt = 10;
return num;
}
my_mastermind* settings_function(my_mastermind* mastermind, int argc, char** argv) {
char* bit;
for(int i = 0; i < argc;) {
if (my_strlen(argv[i]) == 2 && argv[i][0] == '-') {
if(argv[i][1] == 'c') {
char* num_code = argv[i + 1];
if(wrong_input(argc,num_code) != 0) {
break;
}
my_strcpy(mastermind->my_code, num_code);
}else if(argv[i][1] == 't') {
if(checking_for_correctness_num(argv[i + 1]) == 0) {
mastermind->my_attempt = check_function(argv[i + 1]);
}
} else {
printf("WRONG FLAG RESTART THE GAME!!!\n");
}
}
i += 1;
}
return mastermind;
}
int wrong_input(int progress,char* num_code) {
// if(my_strlen(num_code) != 4) {
// printf("Code bigger than 4\n");
// }
if(checking_for_correctness_num(num_code) == 1) {
printf("Wrong input!\n> ");
fflush(stdout);
char* code = input_function();
char* variable = size_of_function(code);
free(code);
int results = 1;
if(wrong_input(progress,variable) == 0) {
results = code_checker(num_code, variable);
}
free(variable);
return results;
}
return 0;
}
int checking_for_correctness_num(char* _string) {
for(int i = 0; _string[i] != '\0'; i++) {
if(!(_string[i] >= '0' && _string[i] <= '9')) {
return 1;
}
}
return 0;
}
int check_function(char* string) {
int check_num = 0;
for(int i = 0; string[i] != '\0'; i++) {
check_num = check_num * 10 + (string[i] - '0');
}
return check_num;
}
char* input_function() {
char* getting = malloc(101);
getting[100] = '\0';
read(0, getting, 100);
fflush(stdout);
return getting;
}
int game_progress(int progress, char* bit) {
printf("Round: %d\n> ", progress);
fflush(stdout);
char* code = input_function();
char* variable = size_of_function(code);
free(code);
int results = 1;
if(wrong_input(progress,variable) == 0) {
results = code_checker(bit, variable);
}
free(variable);
return results;
}
void game_action(my_mastermind* mastermind) {
int current_try = 0;
for (;current_try < mastermind->my_attempt;) {
int results = game_progress(current_try, mastermind->my_code);
current_try += 1;
if(results == 0) {
printf("Congratz! You did it!\n");
break;
}
}
}
int code_checker(char* bit, char* num_code) {
int good_w = well_placed_pieces(bit, num_code);
int not_good_m = mis_placed_pieces(bit, num_code);
if(good_w == 3 || good_w == 2 || good_w == 1 || not_good_m == 3 || not_good_m == 2 || not_good_m == 1){
printf("Well placed pieces: %d\nMisplaced pieces: %d\n---\n", good_w,not_good_m);
}
if(good_w == 4) {
return 0;
} else {
return 1;
}
}
int well_placed_pieces(char* bit, char* num_code) {
int number = 0;
for(int i = 0; i < 4; i++) {
if (bit[i] == num_code[i]) {
number += 1;
}
}
return number;
}
int mis_placed_pieces(char* bit, char* num_code) {
int number = 0;
int i = 0;
int j = 0;
while(i < 4) {
i++;
if (bit[i] == num_code[i]) {
number += 1;
}
}
return number;
}
char* size_of_function(char* strye) {
char* new_string = malloc(5);
new_string[4] = '\0';
for(int i = 0; i < 4;i++){
new_string[i] = strye[i];
}
return new_string;
}
int main(int argc, char** argv) {
printf("Will you find the secret code?\n---\n");
my_mastermind* mastermind = my_function();
settings_function(mastermind, argc, argv);
game_action(mastermind);
free(mastermind);
return 0;
}
The problem is that you size_of_function assumes the input string is exactly 4 character long, not counting the '\0'. You should either check if the input string and return a error via a NULL pointer, or fully copy the string and check later.
Returning a NULL pointer require the least modification. You can do it by checking the input string size first :
char* size_of_function(char* strye) {
if(my_strlen(strye) != 4)
return NULL;
char* new_string = malloc(5);
new_string[4] = '\0';
for(int i = 0; i < 4;i++){
new_string[i] = strye[i];
}
if (strye[4] == '\r' || strye[4] == '\n' || strye[4] == '\0')
return new_string;
free(new_string);
return NULL;
}
Then, in wrong_input(), check if num_code is NULL :
int wrong_input(int progress,char* num_code) {
if(num_code == NULL || checking_for_correctness_num(num_code) == 1) {
printf("Wrong input!\n> ");
fflush(stdout);
char* code = input_function();
char* variable = size_of_function(code);
free(code);
int results = 1;
if(wrong_input(progress,variable) == 0) {
results = code_checker(num_code, variable);
}
free(variable);
return results;
}
return 0;
}
It is critical to check if num_code is NULL before calling checking_for_correctness_num(). In C the || operator evaluates the left operand first and skip the second operand evaluation if the first one is true. This way we can ensure that we never pass a NULL pointer to checking_for_correctness_num().
wrong_input() is called recursively and allocates memory without freeing it before calling itself. This can eat up memory fast and is generality considered to be bad practice.
Also, you've implemented my_strlen() as a recursive function, which isn't necessary. Using a loop is better :
int my_strlen(char* num1) {
int index = 0;
while(num1[index++]); //Note that 'index' is post-incremented
return index - 1; //Subtract one to account for the last post increment
}
Here's the task: "Develop a program for the formation and processing of hash tables, built on the principle of open addressing (private hashing). Practical evaluation of hash tables for the set structure, including the data key N-bit digital code (N >= 10). Explore two probing methods: linear and quadratic. Analyze and calculate the results obtained, first of all, the occurrence of collisons and the search time data for different indicators table coverage ratios"
???For some reason I can't do the last one. I can't count collisions and their output in any way, and calculate the search time. Suggest ideas for the algorithm, plz???
Here`s code:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 20
typedef struct inform {
char* key, * name;
} INFO;
typedef struct hash_table {
int count, size;
INFO** array;
}HTAB;
INFO* New_Item(char* key, char* name)
{
INFO* result = (INFO*)malloc(sizeof(INFO));
result->key = key;
result->name = name;
return result;
}
void free_item(INFO* item)
{
if (item != NULL)
free(item);
}
HTAB* NewHTAB(int size)
{
HTAB* result = (HTAB*)malloc(sizeof(HTAB));
result->count = 0;
result->size = size;
result->array = (INFO**)malloc(sizeof(INFO*) * size);
memset(result->array, NULL, sizeof(INFO*) * size);
return result;
}
void free_hash_table(HTAB* table)
{
if (table != NULL) {
for (int i = 0; i < table->size; i++) {
INFO* item = table->array[i];
if (item != NULL) free_item(item);
}
free(table->array);
free(table);
}
}
int ht_hasItem(HTAB* table, int idx)
{
return table->array[idx] != NULL;
}
int ht_IsFull(HTAB* table)
{
return table->count == table->size;
}
int Hash_Code(int key, int size)
{
return key % size;
}
int Insert(HTAB* table, char* keycpy, char* namecpy)
{
int result = 0;
char* key = _strdup(keycpy);
char* name = _strdup(namecpy);
if (ht_IsFull(table)) printf("Hash table is FULL!!!");
else {
INFO* item = New_Item(key, name);
int idx = Hash_Code(atoi(key), table->size);
//int h = 1;
while (ht_hasItem(table, idx)) {
idx = Hash_Code(idx + 1, table->size);
}
//idx = Hash_Code(idx + (h*h), table->size);
//h++;
table->array[idx] = item;
table->count++;
}
return result;
free(key);
free(name);
}
void Display(HTAB* table)
{
printf("-------------------------------------------------\n");
for (int i = 0; i < table->size; i++) {
if (ht_hasItem(table, i)) {
INFO* item = table->array[i];
printf(" %d\t| %s\t| %s \t|\n", i, item->key, item->name);
printf("-------------------------------------------------\n");
}
else {
printf(" %d\t| ---\t| \t---\t\t|\n", i);
printf("-------------------------------------------------\n");
};
}
printf("\n");
}
int Search(HTAB* table, char* key)
{
int result = -1;
int idx = Hash_Code(atoi(key), table->size);
// int h = 1;
while (ht_hasItem(table, idx)) {
if (strcmp(table->array[idx]->key, key) == 0) {
result = idx;
break;
}
else idx = Hash_Code(idx + 1, table->size);
//idx = Hash_Code(idx + (h*h), table->size);
//h++;
}
return result;
}
INFO* Remove(HTAB* table, char* key)
{
INFO* result = NULL;
int idx = Search(table, key);
if (idx != -1) {
result = table->array[idx];
table->array[idx] = NULL;
table->count--;
}
return result;
}
int main() {
int itemIdx = 0;
INFO* item = NULL;
HTAB* table = NewHTAB(30);
char name[LEN], key[LEN];
int choice = 0, c;
system("chcp 1251");
FILE* ftxt;
if (!(ftxt = fopen("RGR_2_AP.txt", "r"))) {
puts("\n File not found...\n");
return 0;
}
while (fscanf(ftxt, "%s%s", name, key) == 2)
Insert(table, key, name);
printf("\n Іndex\t| Кey\t| \t NAME\t\t|\n");
Display(table);
do {
printf("MENU-: \n1.Insert new item"
"\n2.Search item"
"\n3.Delet item"
"\n\n Please choose one point-:");
scanf_s("%d", &choice);
switch (choice) {
case 1:
printf("\nEnter name: ");
rewind(stdin);
gets_s(name);
printf("\nВведіть ключ: ");
gets_s(key);
while (strlen(key) < 10) {
printf("\nWrong key");
printf("\nTry again: ");
gets_s(key);
}
Insert(table, key, name);
printf("\n");
Display(table);
break;
case 2:
printf("\nEnter key: ");
rewind(stdin);
gets_s(key);
while (strlen(key) < 10) {
printf("\nWrong key");
printf("\nTry again: ");
gets_s(key);
}
itemIdx = Search(table, key);
if (itemIdx != -1) {
item = table->array[itemIdx];
printf("Item found: (%d, %s, %s)\n", itemIdx, item->key, item->name);
}
else printf("Item not found\n");
break;
case 3:
printf("\nEnter key: ");
rewind(stdin);
gets_s(key);
while (strlen(key) < 10) {
printf("\nWrong key");
printf("\nTry again: ");
gets_s(key);
}
Remove(table, key);
Display(table);
break;
default:
printf("Wrong Input\n");
}
printf("\n Do you want continue(enter 1 if yes)?-:\t");
scanf_s("%d", &c);
} while (c == 1);
free_hash_table(table);
printf("End...\n");
return 0;
}
You could add variables which count collisions in the Insert and Search methods, as well as the run time. You may need to return a list in that case, with the first element being the index, second being the # of collisions, and third being the run time.
Use the chrono library to time your functions.
I´m facing really weird issue with my headtail application. When I try to read from file data.txt using Powershell (command: Get-Content data.txt | .\Headtail.exe head 10) I always get proper and expected output. However if I change input from data.txt to fail.txt I won´t get any output from output function (called vypis()).
Does anyone have an idead what is going on here?
GOOD CASE: Output from command (this output is suppose to be same using fail.txt as an input (meaning that content of the given input should be printed)) Get-Content data.txt | .\Headtail.exe head 10 in PowerShell:
aaaaaaaaaaaaaaaaaaaaaaaaaaaa.
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.
ccccccccccccccccccccc.
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.
ffffffffffffffffffffffffffffffffffffffffffffffffffff.
ggggggggggggggggggggggggggggggggg.
hhhhh.
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj.
WRONG CASE: Output from command Get-Content fail.txt | .\Headtail.exe head 10 in PowerShell:
/*NOTHING */
Code for my headtail function is following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int const size = 15;
int last_changed = 0;
typedef struct {
char **field;
int *columns;
int rows;
} TMatrix;
void set_size(TMatrix* matrix) {
for (int i = 0; i < matrix->rows; i++) matrix->columns[i] = size;
}
TMatrix* allocate() {
TMatrix* matrix = malloc(sizeof(TMatrix));
if (!matrix) return NULL;
matrix->field = malloc(size * sizeof(char*));
if (!matrix->field) return NULL;
matrix->rows = size;
matrix->columns = malloc(size * sizeof(int));
if (!matrix->field) return NULL;
set_size(matrix);
for (int i = 0; i < matrix->rows; i++) {
matrix->field[i] = malloc(size * sizeof(char));
if (!matrix->field[i]) return NULL;
}
return matrix;
}
void release(TMatrix* matrix) {
for(int i = 0; i < matrix->rows; i++) free(matrix->field[i]);
free(matrix->field);
free(matrix->columns);
free(matrix);
}
bool add_rows(TMatrix* matrix) {
matrix->rows += 10;
char** rebuf = realloc(matrix->field, matrix->rows * sizeof(char*));
if (!rebuf) {
free(rebuf);
return false;
}
matrix->field = rebuf;
int* rebufl = realloc(matrix->columns, matrix->rows * sizeof(int));
if (!rebufl) {
free(rebufl);
return false;
}
matrix->columns = rebufl;
for (int i = 1; i <= 10; i++) {
char* rebuh = realloc(matrix->field[matrix->rows - i], size * sizeof(char));
if (!rebuh) {
free(rebuh);
return false;
}
matrix->field[matrix->rows - i] = rebuh;
matrix->columns[matrix->rows - i] = size;
}
return true;
}
bool add_column(TMatrix* matrix, int row) {
matrix->columns[row] += 15;
char* rebuf = realloc(matrix->field[row], matrix->columns[row] * sizeof(char));
if (!rebuf) {
free(rebuf);
return false;
}
matrix->field[row] = rebuf;
return true;
}
TMatrix* load(FILE* in) {
char c;
int actual_row = 0, actual_column = 0;
TMatrix* matrix;
if (!(matrix = allocate())) return NULL;
while ((fscanf(in, "%c", &c)) != EOF) {
matrix->field[actual_row][actual_column] = c;
if (c != '\n') {
actual_column += 1;
if (((matrix->columns[actual_row]) - 1) == actual_column) {
if (!add_column(matrix, actual_row)) return NULL;
}
}
else if (c == '\n') {
actual_column +=1;
if (((matrix->columns[actual_row]) - 1) == actual_column) {
if (!add_column(matrix, actual_row)) return NULL;
}
matrix->field[actual_row][actual_column] = '\0';
actual_column = 0;
actual_row += 1;
last_changed += 1;
if (((matrix->rows) - 1) == actual_row) {
if (!add_rows(matrix)) return NULL;
}
}
}
return matrix;
}
bool output(FILE* out, TMatrix *matrix, double num_of_output_lines, char method[]) {
if (!matrix) return false;
if (num_of_output_lines <= 0) return false;
if (matrix->rows <= 0) return false;
if (num_of_output_lines > last_changed) return false;
if (strcmp("head", method) == 0) {
for (int i = 0; i < num_of_output_lines; i++) {
for (int j = 0; j < matrix->columns[i]; j++) {
if (matrix->field[i][j] != '\0') fprintf(out, "%c", matrix->field[i][j]);
else break;
}
}
}
else if (strcmp("tail", method) == 0) {
for (int a = (last_changed-1); a >= (last_changed - num_of_output_lines); a--) {
for (int b = 0; b < matrix->columns[a]; b++) {
if (matrix->field[a][b] != '\0') fprintf(out, "%c", matrix->field[a][b]);
else break;
}
}
}
else return false;
return true;
}
void Help() {
fprintf(stdout, "-------------------------------------------------------------------------------------\n");
fprintf(stdout, "* Help function - nothing important *\n");
fprintf(stdout, "-------------------------------------------------------------------------------------\n");
}
int main(int argc, char *argv[])
{
if (argc < 3 || argc > 4) {
printf("!Valid count of arguments entered! \n");
return -1;
}
if (strcmp("-h", argv[1]) == 0) Help();
double num_of_output_lines = atoi(argv[argc - 1]);
TMatrix* matrix = load(stdin);
if (!matrix) {
printf("!Error while loading! \n");
return -1;
}
if (!output(stdout, matrix, num_of_output_lines, argv[argc - 2])) {
printf("!Error while printing! \n");
return -1;
}
release(matrix);
return 0;
}
And content of data.txt (works fine, just an example input):
aaaaaaaaaaaaaaaaaaaaaaaaaaaa.
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.
ccccccccccccccccccccc.
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.
ffffffffffffffffffffffffffffffffffffffffffffffffffff.
ggggggggggggggggggggggggggggggggg.
hhhhh.
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj.
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk.
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm.
nnnnnnnnnnnnnnnnnnnnnnnnn.
ooooooooooo.
ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq.
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr.
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss.
ttttttttttttttttttttt.
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.
vvvvvvvvvvvvvvvvvvvvvvvvvvv.
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.
zzzzzzzzzzzzzzzzzzzzzz.
And finally content of fail.txt (didn´t get any output, the difference is just in length of some rows):
aaaaa.
bbbbbbb.
cccc.
ddddddd.
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.
ffffffffffffffffffffffffffffffffffffffffffffffffffff.
ggggggggggggggggggggggggggggggggg.
hhhhh.
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj.
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk.
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm.
nnnnnnnnnnnnnnnnnnnnnnnnn.
ooooooooooo.
ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq.
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr.
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss.
ttttttttttttttttttttt.
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.
vvvvvvvvvvvvvvvvvvvvvvvvvvv.
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.
zzzzzzzzzzzzzzzzzzzzzz.
I need to program a small airport management system for a school project and I have a terrible bug in my code.
As soon as I initialize the airportManager with more than one airport, all the IATA codes in the airports array get the name of the last airport that was input.
I have tried debugging it a lot of time but without any success. Everything is fine until I print the IATA code or use it. I will be glad for any help.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define TEMP_STR_LEN 255
#define IATA_SIZE 3
// Airport struct:
struct Airport
{
char name[TEMP_STR_LEN];
char country[TEMP_STR_LEN];
char iata[IATA_SIZE];
} typedef airport;
// Airport functions:
int compareAirports(airport const *airport1, airport const *airport2)
{
if (strcmp(airport1->iata, airport2->iata) != 0)
return 0;
else
return 1;
}
int compareIataCode(airport *airport1, char const *iata)
{
if (strcmp(airport1->iata, iata) != 0)
return 0;
else
return 1;
}
void NameArrange(char *name)
{
char tmpString[255];
tmpString[0] = '\0';
char *token = strtok(name, " ");
int i, place = 0, strTotalLen = 0, lastTokenLen = 0;
while (token != NULL)
{
place++;
if (strlen(token) % 2 == 0)
{
for (i = 0; i < strlen(token) - 1; i++)
{
if (token[i] >= 'a' && token[i] <= 'z')
{
token[i] -= 32; // by ascii table
}
if ((token[i + 1] >= 'A' && token[i + 1] <= 'Z'))
token[i + 1] += 32; // by ascii table
i++;
}
}
else if (token[0] >= 'a' && token[0] <= 'z')
token[0] -= 32;
if (place != 1)
strcat(tmpString, " ");
strncat(tmpString, token, strlen(token));
strTotalLen += strlen(token);
lastTokenLen = strlen(token);
token = strtok(NULL, " ");
}
strTotalLen += (place - 1) * 2;
if (lastTokenLen % 2 != 0)
tmpString[strTotalLen - lastTokenLen] += 32;
strcpy(name, tmpString);
}
// ***Airport manager struct***
struct AirportManager
{
int airportsCount;
airport *airportArr;
} typedef airportMan;
// airportManager functions
void addAirport(airportMan *airportManager, airport *airportToAdd)
{
airportManager->airportArr = (airport *) realloc(airportManager->airportArr, (airportManager->airportsCount + 1) * (sizeof(airport)));
strcpy(airportManager->airportArr[airportManager->airportsCount].name, airportToAdd->name);
strcpy(airportManager->airportArr[airportManager->airportsCount].country, airportToAdd->country);
strcpy(airportManager->airportArr[airportManager->airportsCount].iata, airportToAdd->iata);
airportManager->airportsCount++;
printf(" BUG!!! %s\n", airportManager->airportArr[0].iata);
}
bool airportFind(airportMan *airportManager, char *iataCode)
{
int i;
printf("%s", airportManager->airportArr[0].iata );
char airportIata[IATA_SIZE];
char airportIata2[IATA_SIZE];
strcpy(airportIata, iataCode);
strcpy(airportIata2, airportManager->airportArr[0].iata);
if (strcmp(airportIata, airportIata2) == 0)
return true;
// for (i = 1; i < airportManager->airportsCount; i++) {
// printf("%s",airportManager->airportArr[0].iata );
// return true;
// }
puts("Airport not found");
return false;
}
bool checkDuplicatedIata(const airportMan *airportManger, const char *iata)
{
// checks if there is already airport with the same iata code as the input
int i;
for (i = 0; i < airportManger->airportsCount; i++)
{
if (compareIataCode(&(airportManger->airportArr[i]), iata))
{
puts("This IATA code is already exists, please try again");
return true;
}
}
return false;
}
bool checkIataSize(const char *iata)
{
if (strlen(iata) != IATA_SIZE)
{
puts("The IATA code must be 3 letters");
return false;
}
return true;
}
bool checkIataLetters(const char *iata)
{
// checks if all the letters in a given iata code are all capital
int i;
for (i = 0; i < strlen(iata); i++)
{
if (iata[i] >= 'a' && iata[i] <= 'z')
{
puts("The IATA code must be in capital letters");
return false;
}
}
return true;
}
bool checkIataOk(const char *iata, const airportMan *airportManager)
{
if (checkDuplicatedIata(airportManager, iata) == false
&& checkIataSize(iata) && checkIataLetters(iata))
return true;
else
return false;
}
airport *initAirport(airportMan *airportManager)
{
// asks the user to input an airport
airport *iniAirport;
iniAirport = (airport *) malloc(sizeof(airport));
char tmpStr[TEMP_STR_LEN];
char *ptr;
bool iataOk = false;
printf("please enter airport details (press enter to confirm):\nName:");
fflush(stdin);
fgets(tmpStr, 255, stdin);
if ((ptr = strchr(tmpStr, '\n')) != NULL)
*ptr = '\0';
strcpy(iniAirport->name, tmpStr);
NameArrange(iniAirport->name);
printf("Country:");
fgets(iniAirport->country, 255, stdin);
if ((ptr = strchr(iniAirport->country, '\n')) != NULL)
*ptr = '\0';
while (!iataOk)
{
printf("IATA code:");
fgets(iniAirport->iata, TEMP_STR_LEN, stdin);
fflush(stdin);
if ((ptr = strchr(iniAirport->iata, '\n')) != NULL)
*ptr = '\0';
iataOk = checkIataOk(iniAirport->iata, airportManager);
}
return iniAirport;
}
airportMan *initAirportManager()
{
airportMan *airportManager = (airportMan *) malloc(sizeof(airportMan));
if (airportManager == NULL)
return NULL;
airportManager->airportsCount = 0;
int airportsCount = 0, i = 0;
puts("Please enter how much airports you want to add");
scanf("%d", &airportsCount);
getchar();
for (i = 0; i < airportsCount; i++)
{
airport *airport = initAirport(airportManager);
addAirport(airportManager, airport);
}
return airportManager;
}
// ****Struct date*******
struct Date
{
int day;
int month;
int year;
} typedef date_t;
bool checkDateFormat(char *dateString)
{
char tmpString[TEMP_STR_LEN] = "";
strcpy(tmpString, dateString);
char *token = strtok(tmpString, "/");
if (strlen(token) == 2)
{
token = strtok(NULL, "/");
if (strlen(token) == 2)
{
token = strtok(NULL, "/");
if (strlen(token) == 4)
return true;
puts("Please enter the date in the correct format");
return false;
}
puts("Please enter the date in the correct format");
return false;
}
puts("Please enter the date in the correct format");
return false;
}
bool checkDate(date_t *date)
{
int daysArr[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (date->month > 0 && date->month <= 12)
{
if (date->day > 0 && date->day <= daysArr[date->month - 1])
{
if (date->year >= 2020)
return true;
puts("Invalid year, please try again");
return false;
}
puts("Invalid day, please try again");
return false;
}
puts("Invalid month, please try again");
return false;
}
date_t *initDate()
{
date_t *date;
char tmpDateString[TEMP_STR_LEN];
char *ptr;
bool checkFormat = false;
bool checkValid = false;
date = (date_t *) malloc(sizeof(date_t));
while ((!checkFormat) || (!checkValid))
{
puts("Please enter date in the following format: dd/mm/yyyy ");
fgets(tmpDateString, TEMP_STR_LEN, stdin);
if ((ptr = strchr(tmpDateString, '\n')) != NULL)
*ptr = '\0';
checkFormat = checkDateFormat(tmpDateString);
char *token = strtok(tmpDateString, "/");
date->day = atoi(token);
token = strtok(NULL, "/");
date->month = atoi(token);
token = strtok(NULL, "/");
date->year = atoi(token);
checkValid = checkDate(date);
}
return date;
}
// ***Flight struct***
struct Flight
{
char departureAirport[TEMP_STR_LEN];
char arrivalAirport[TEMP_STR_LEN];
int takeofTime;
date_t *date;
} typedef flight_f;
// ***flight functions
bool checkTakeOffTime(const flight_f *flight)
{
if ((flight->takeofTime >= 0 && flight->takeofTime <= 23))
return true;
puts("Invalid time");
return false;
}
bool compareFlightIata(const char *srcIata, const char *destIata)
{
return strcmp(srcIata, destIata) == 0;
}
bool compareFlightPath(const char *srcIata, const char *destIata)
{
if (compareFlightIata(srcIata, destIata))
{
puts("Flight must have different destination and source airports ");
return false;
}
return true;
}
flight_f *initFlight(airportMan *airportManager)
{
flight_f *flight;
char *ptr;
bool checkIata = false;
bool takeoffCheck = false;
bool airportExists = false;
flight = (flight_f *) malloc(sizeof(flight_f));
puts("Please enter flight details ");
while (!checkIata || !airportExists)
{
puts("\nSrc airport:");
fgets(flight->departureAirport, TEMP_STR_LEN, stdin);
if ((ptr = strchr(flight->departureAirport, '\n')) != NULL)
*ptr = '\0';
checkIata = (checkIataSize(flight->departureAirport)
&& checkIataLetters(flight->departureAirport));
if (checkIata)
airportExists = airportFind(airportManager, flight->departureAirport);
}
checkIata = false;
airportExists = false;
while (!checkIata || !airportExists)
{
puts("\nDec airport:");
fgets(flight->arrivalAirport, TEMP_STR_LEN, stdin);
if ((ptr = strchr(flight->arrivalAirport, '\n')) != NULL)
*ptr = '\0';
checkIata = (checkIataSize(flight->arrivalAirport)
&& checkIataLetters(flight->arrivalAirport)
&& compareFlightPath(flight->departureAirport,
flight->arrivalAirport));
if (checkIata)
airportExists = airportFind(airportManager, flight->arrivalAirport);
}
while (!takeoffCheck)
{
puts("\nTakeoff time: ");
scanf("%d", &flight->takeofTime);
getchar();
takeoffCheck = checkTakeOffTime(flight);
}
flight->date = initDate();
return flight;
}
bool checkFlightPath(flight_f flight, char const *departureFrom,
char const *arrivingTo)
{
if (strcmp(flight.departureAirport, departureFrom) == 0
&& strcmp(flight.arrivalAirport, arrivingTo) == 0)
return true;
else
return false;
}
int flightPathFind(flight_f **flightsArr, char const *departureFrom,
char const *arrivingTo, int size)
{
int count = 0;
int i;
for (i = 0; i < size; i++)
{
if (checkFlightPath((*flightsArr)[i], departureFrom, arrivingTo))
{
count++;
}
}
return count;
}
// Struct airline
struct Airline
{
char name[TEMP_STR_LEN];
int filghtsCount;
flight_f **flightsArr;
} typedef airline_a;
void addFlightToAirline(airline_a *airline, airportMan *airportManager)
{
airline->flightsArr = (flight_f **) realloc(airline->flightsArr,
(airline->filghtsCount + 1) * sizeof(flight_f *));
flight_f *flightToAdd = initFlight(airportManager);
airline->flightsArr[airline->filghtsCount] = flightToAdd;
airline->filghtsCount++;
}
void airlineFlightsCount(airline_a *airline, char const *departureFrom,
char const *arrivingTo)
{
int i;
int count = 0;
for (i = 0; i < airline->filghtsCount; i++)
{
if (checkFlightPath(*(airline->flightsArr[i]), departureFrom, arrivingTo))
count++;
}
printf("%s airline has %d flights in that path\n", airline->name, count);
}
airline_a *initAirline()
{
airline_a *airline;
airline = (airline_a *)malloc(sizeof(airline_a));
if (airline == NULL)
return NULL;
char *ptr;
puts("Please enter airline name:");
fgets(airline->name, TEMP_STR_LEN, stdin);
if ((ptr = strchr(airline->name, '\n')) != NULL)
*ptr = '\0';
airline->filghtsCount = 0;
airline->flightsArr = NULL;
return airline;
}
int main()
{
airportMan *airportManager = initAirportManager();
return 0;
}
I have to scan this file which partly contains
SNOL
INTO num IS 8
INTO res IS 9
and the output of the code below is
Program starts...
Set value of num to 0
Set value of res to 8
input msg
which is wrong because num should be 8 and res should be 9
why is it num scanning 0 instead of 8?
and why doesn't the code work anymore if I assign number to num and number to res?
num = number;
//Tokenizer functions//
bool isLowerCase(const char *object)
{
int i;
int len = strlen(object);
for(i = 0; i < len; i++) {
if(object[i] >= 'a' && object[i] <= 'z') {
return true;
}
}
return false;
}
//function to check if character is Float.
bool objectFloat(const char* object) {
//check if 1st character is a digit, if not then return false,
otherwise
return true.
if(!isdigit(object[0]))
return false;
// Check if the 2nd character to the last are digits or periods.
// If not, return false otherwisereturn true
int periods = 0; //initialize how many periods in the object to zero
int i;
//if character is a period then increment periods.
for(i = 1; i < strlen(object); i++) {
if(object[i] == '.') {
periods++;
}
//return false if character is not a digit
else if(!isdigit(object[i])) {
return false;
}
}
// return true if there is only one period.
return periods == 1;
}
//function to check if character is a keyobject.
bool isKeyobject(const char* object) {
char keyobjects[11][11] = { "SNOL", "LONS", "INTO", "IS", "MULT", "BEG",
"PRINT", "ADD", "SUB", "DIV", "MOD" };
int i;
for(i = 0; i < 11; i++) {
// Check if object is equal to keyobjects at index i
// If yes, return true
if(isLowerCase(object))
return false;
if(strcmp(object, keyobjects[i]) == 0) {
return true;
}
}
//object is not equal to any of the keyobjects so return false
return false;
}
//Function to check if every character is an integer
// If not, return false otherwise return true
bool objectInt(const char* object) {
int i;
for(i = 0; i < strlen(object); i++) {
if(!isdigit(object[i])) return false;
}
return true;
}
bool objectIsVariable(const char* object) {
// Check if alphanumeric character & lower case
// If not, return false
int i;
for(i = 0; i < strlen(object); i++) {
if(!isalnum(object[i]) && !isLowerCase(object)) return false;
}
return true;
}
int main() {
FILE *s_path = fopen("test.snol", "r");
int number = 0;
int num, res;
if(isKeyobject(object) && strcmp(object, IsitSNOL) == 0) {
printf("Program starts...\n");
}
else if(isKeyobject(object) && strcmp(object, IsitINTO) == 0) {
printf("Set value of ");
}
if(objectInt(object)) {
number = atoi(object);
}
else if(objectFloat(object)) {
number = atof(object);
}
if(objectIsVariable(object) && strcmp(object, IsitNum) == 0) {
//if float
printf("num to %d\n", number);
num == number;
}
else if(objectIsVariable(object) && strcmp(object, IsitRes) == 0) {
//if float
printf("res to %d\n", number);
res == number;
}
else if(isKeyobject(object) && strcmp(object, IsitBEG) == 0) {
printf("input msg\n");
scanf("%s", msg);
fscanf(s_path, " %s", &object);
printf("INPUT(%s): %s\n", object, msg);
}
}
} // END MAIN -----------------------------------//
The problem seem to be that you read the number after the variable name but you do the print before.
So your sequence is:
Keyobject INTO
objectIsVariable num // Now you print the value
objectInt // Now you read the value
You need to postpone the printing until you have actually read the value.
This is not a very elegant solution, but you can try like:
int flag = 0;
if(objectInt(object)) {
number = atoi(object);
if (flag == 1)
{
num = number;
printf("num to %d\n", number);
}
else if (flag == 2)
{
res = number;
printf("res to %d\n", number);
}
else
{
printf("Illegal flag\n");
}
flag = 0;
}
if(objectIsVariable(object) && strcmp(object, IsitNum) == 0) {
flag = 1;
}
else if(objectIsVariable(object) && strcmp(object, IsitRes) == 0) {
flag = 2;
}