string BUG in c project for school - c

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;
}

Related

My problem with the size of the number in the My_Mastermind minigame

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
}

Why strcmp does not return 0?

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;
}

Why gdb showed /stdlib/strtol_l.c: No such file or directory? Do I missing something to install?

I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0, loc=0x7ffff7fb04a0 <_nl_global_locale>)
at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: No such file or directory.
I tried reinstalling gdb to get it working again, but I failed. It still shows the same error message. I later found the problem myself and marked it in the code below. I'm just curious why something like this sometimes happens when I try to debug some string functions? Like strdup, strtok, strtol, etc.. Am I missing something to install? I hope I can solve this problem completely.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char buff[255];
#define NUM_BUCKETS 32
typedef struct Customer {
char* email;
char* name;
int shoesize;
char* food;
struct Customer* next;
} Customer ;
unsigned long hash(char *str) {
unsigned long hash = 0;
int c;
while (*str != '\0') {
c = *str;
hash = ((hash << 5) + hash) + (unsigned char)c;
str++;
}
return hash;
}
Customer *add_friend_to_list(char *email, char *name, int shoesize, char *food, Customer *bucket) {
Customer* customer;
customer = malloc(sizeof(Customer));
customer->name = strdup(name);
customer->food = strdup(food);
customer->shoesize = shoesize;
customer->email = strdup(email);
customer->next = bucket;
return customer;
}
void add_consumer_to_hashtable(char *name, char *food, char *email, int shoesize, Customer **buckets, size_t num_buckets) {
size_t which_bucket = hash(name) % num_buckets;
buckets[which_bucket] = add_friend_to_list(email, name, shoesize, food, buckets[which_bucket]);
}
int main() {
Customer* buckets[NUM_BUCKETS] = {NULL};
int ittime = 0;
FILE *fp = NULL;
fp = fopen("customers.tsv", "r");
while (true) {
fgets(buff, 255, fp);
if (feof(fp)) {
break;
}
ittime++;
}
fclose(fp);
fp = NULL;
char *email = (char *)malloc(5 * sizeof(char));
char *name = (char *)malloc(5 * sizeof(char));
int shoesize;
char *food = (char *)malloc(5 * sizeof(char));
const char s[2] = "\t";
fp = fopen("customers.tsv", "r");
for (int i = 0; i < ittime + 1; i++) { //This line cause the Segmentation Fault
fgets(buff, 255, fp);
char *token;
token = strtok(buff, s);
email = token;
token = strtok(NULL, s);
name = token;
token = strtok(NULL, s);
shoesize = atoi(token);
token = strtok(NULL, s);
food = token;
add_consumer_to_hashtable(name, food, email, shoesize, buckets, NUM_BUCKETS);
}
fclose(fp);
while (true) {
char *cmd = (char *)malloc(5 * sizeof(char));
printf("command: ");
scanf("%s", cmd);
if (strcmp(cmd, "add") == 0) {
char *email1 = (char *)malloc(5 * sizeof(char));
char *name1 = (char *)malloc(5 * sizeof(char));
int shoesize1;
char *food1 = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", email1);
printf("name? ");
scanf(" %[^\n]", name1);
printf("shoe size? ");
scanf("%d", &shoesize1);
printf("favorite food? ");
scanf("%s", food1);
add_consumer_to_hashtable(name1, food1, email1, shoesize1, buckets, NUM_BUCKETS);
free(name1);
free(food1);
free(email1);
} else if (strcmp(cmd, "lookup") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "delete") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
free(cus->email);
free(cus->food);
free(cus->name);
free(cus);
cus->shoesize = EOF;
cus = NULL;
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "list") == 0) {
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
if (cus->next != NULL) {
cus = cus->next;
printf("\n");
} else {
break;
}
}
}
} else if (strcmp(cmd, "quit") == 0) {
break;
} else if (strcmp(cmd, "save") == 0) {
fp = fopen("customers.tsv", "w");
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
fprintf(fp, "%s\t%s\t%d\t%s", cus->email, cus->name, cus->shoesize, cus->food);
if (cus->next != NULL) {
cus = cus->next;
fprintf(fp, "\n");
} else {
break;
}
}
}
fclose(fp);
} else {
printf("unknown command\n");
}
}
for (int i = 0; i < 32; i++) {
Customer *tmp;
Customer *cus = buckets[i];
if (cus == NULL) {
continue;
}
if (cus->next != NULL) {
tmp = cus;
cus = cus->next;
} else {
break;
}
while ((tmp != NULL)) {
if (tmp->shoesize != EOF) {
free(tmp->email);
free(tmp->food);
free(tmp->name);
free(tmp);
}
cus->shoesize = EOF;
cus = NULL;
}
if (tmp != NULL) {
free(tmp);
}
if (cus != NULL) {
free(cus);
}
}
return 0;
}
I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
The error message means:
crash happened inside GLIBC strtol_l_internal() function
GDB can't show you the source of that function because libc6-src (or similar) package is not installed.
Now, looking at the source for strtol_l_internal() is not going to be helpful -- the root cause of the problem is that you called it with incorrect parameter.
You should read man strtol and verify that you satisfied its preconditions.
It looks like you called strtol(NULL, NULL, ...), which is not a valid thing to do. You could use (gdb) up command to find out where the wrong call came from, and fix the caller.

program creates a file, but won't write to it

I'm very novice at C but I'm trying to learn. I'm trying right now to make a program read from a csv file and take only it's integers from it, and write those out to a seperate .txt file. I'm not seeing why it will create a file, but why it won't write anything to it. Here's the code. in the methods 'getTokensFromLineforOutput' and 'writeOutput' is where I try to do my writing, everything else works fine, and if you were to take away those two methods and run it as just a program reading from a csv file it operates as intended. But writing is where I'm running into. IDK if i'm able to attach a document so for reference here's the csv file I made from notepad:
3,1, joe
45,0, sandy
5,1, mary
12,0, eugene
11,0, alex
#include <stdio.h>
#include <stdbool.h>
#define NAMESIZE 30
#define ARRAYSIZE 100
#define ROWLENGTH 300
#define TOKENLENGTH 10
typedef struct {
int nWeeks;
bool isCensored;
char identifier[NAMESIZE];
}SurvivalPatientData;
bool giveMeALine(FILE * source, char * dest)
{
bool status = false;
char * where = dest;
char ch;
int ch_ctr = 0;
while(((ch = getc(source)) != EOF) && (ch != '\n') && (ch != '\r'))
{
*where = ch;
where++;
ch_ctr++;
status = true;
}
for (int i=ch_ctr; i<ROWLENGTH && status ;i++)
{
*where= '\0'; /*null*/
where++;
}
printf("giveMeALine returning status = %d\n",status);
return status;
}
bool getTokensFromLineforOutput(char *theLine, SurvivalPatientData *sdp) {
bool status = false;
FILE * file = fopen("C:/Users/Default/Desktop/CCSU/CCSU SPRING 18/CS_3//output.txt", "w");
char * inTheLine = theLine;
char theToken[TOKENLENGTH];
char * inToken = theToken;
char ch = '\0';
for (int i = 0; i<TOKENLENGTH; i++)
{
theToken[i]='\0'; /*null char*/
}
int value = 0;
while((ch=*inTheLine)!=',')
{
value *= 10;
value += ch - '0';
inTheLine++;
}
sdp->nWeeks=value;
fprintf(file, "%d\n",sdp->nWeeks);
inTheLine++;
for (int i = 0; i<TOKENLENGTH; i++)
{
theToken[i]='\0'; /*null char*/
}
inToken = theToken;
inTheLine++;
while((ch=*inTheLine)!=',')
{
*inToken = ch;
inToken++;
inTheLine++;
}
inToken--;
if (*inToken == '0')
{
sdp->isCensored=false;
}
else
{
sdp->isCensored= true;
}
fprintf(file, "%d\n",sdp->isCensored);
inTheLine++;
for (int i = 0; i<TOKENLENGTH; i++)
{
theToken[i]='\0'; /*null char*/
}
inToken = sdp->identifier;
while((ch=*inTheLine)!=',' && ch!= EOF)
{
*inToken = ch;
inToken++;
inTheLine++;
}
status=true;
return status;
}
bool getTokensFromLine(char * theLine,
SurvivalPatientData * sdp);
bool getTokensFromLine(char *theLine, SurvivalPatientData *sdp) {
bool status = false;
char * inTheLine = theLine;
char theToken[TOKENLENGTH];
char * inToken = theToken;
char ch = '\0';
for (int i = 0; i<TOKENLENGTH; i++)
{
theToken[i]='\0'; /*null char*/
}
int value = 0;
while((ch=*inTheLine)!=',')
{
value *= 10;
value += ch - '0';
inTheLine++;
}
sdp->nWeeks=value;
printf("Weeks is %d\n",sdp->nWeeks);
inTheLine++;
for (int i = 0; i<TOKENLENGTH; i++)
{
theToken[i]='\0'; /*null char*/
}
inToken = theToken;
inTheLine++;
while((ch=*inTheLine)!=',')
{
*inToken = ch;
inToken++;
inTheLine++;
}
inToken--;
if (*inToken == '0')
{
sdp->isCensored=false;
}
else
{
sdp->isCensored= true;
}
printf("isCensored is %d\n",sdp->isCensored);
inTheLine++;
for (int i = 0; i<TOKENLENGTH; i++)
{
theToken[i]='\0'; /*null char*/
}
inToken = sdp->identifier;
while((ch=*inTheLine)!=',' && ch!= EOF)
{
*inToken = ch;
inToken++;
inTheLine++;
}
printf("The identifier is %s\n",sdp->identifier);
status=true;
return status;
}
bool writeOutput(FILE * source, SurvivalPatientData * gotIt){
bool status = false;
bool write = false;
for (int j = 0; j<ARRAYSIZE; j++){
for (int i = 0; i<NAMESIZE; i++){
(gotIt[j].identifier)[i]='\x20';
}
gotIt[j].nWeeks = 0;
gotIt[j].isCensored = false;
}
int nrows = 0;
int row = 0;
char readALine[ROWLENGTH];
bool lines2Read = true;
bool gotTokens = false;
while (lines2Read){
bool gotALine = giveMeALine(source, readALine);
if(!gotALine){
lines2Read = false;
} else {
gotTokens = getTokensFromLineforOutput(readALine, &(gotIt[row]));
if(gotTokens){
status = true;
row++;
nrows++;
}
}
}
return status;
}
bool getInputFancy(FILE * source, SurvivalPatientData * gotIt){
bool status = false;
for (int j = 0; j<ARRAYSIZE; j++){
for (int i = 0; i<NAMESIZE; i++){
(gotIt[j].identifier)[i]='\x20';
}
gotIt[j].nWeeks = 0;
gotIt[j].isCensored = false;
}
int nrows = 0;
int row = 0;
char readALine[ROWLENGTH];
bool lines2Read = true;
bool gotTokens = false;
while (lines2Read){
bool gotALine = giveMeALine(source, readALine);
if(!gotALine){
lines2Read = false;
} else {
puts(readALine);
gotTokens = getTokensFromLine(readALine, &(gotIt[row]));
if(gotTokens){
printf("found %d row\n", row);
status = true;
row++;
nrows++;
}
}
}
printf("found %d rows\n", nrows);
return status;
}
int main() {
printf("Hello, World!\n");
bool readIt = false;
bool write = false;
SurvivalPatientData gotIt[ARRAYSIZE];
FILE * whereInputIs = fopen("C:/Users/Default/Desktop/CCSU/CCSU SPRING 18/CS_3//retake.csv", "r");
FILE * whereOutputIs = fopen("C:/Users/Default/Desktop/CCSU/CCSU SPRING 18/CS_3//output.txt", "w");
if (whereInputIs == NULL){
perror("can't open file source/doesn't exist");
}
puts("Found the file");
readIt = getInputFancy(whereInputIs, gotIt);
write = writeOutput(whereOutputIs, gotIt);
if (!readIt)
{
perror("could not read that file");
}
puts("!!!read the file!!!");
if (fclose ( whereInputIs) != 0) {
perror("trouble trying to close");
}
puts("!!!closed the file!!!");
return 0;
}
(If I could comment this I would)
Try putting parentheses around your de referencing * and variable..
(ch = (*inThLine))

Cannot understand why program crashes after a couple iterations of while loop?

I am writing the following program to parse the text file (attached) but it keeps crashing after couple of iterations of while loop or it seems that the buffer storing file contents is corrupted somehow?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char * pick_question(char *, char, int);
char * print_answer(char *, char, int);
int no_of_questions(char*, char);
void clear();
int debug = 0;
int main(int argc, char* argv[])
{
system("cmd /c chcp 1252");
// system("cmd /c chcp 65001");
if (argc < 2)
{
perror("Please enter a filename!\n");
exit(0);
}
if (argc > 2)
{
debug = atoi(argv[2]);
}
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
if (!file)
{
perror("Unable to read file!\n");
exit(0);
}
else
{
if (debug == 1)
{
printf("File opened successfully\n");
}
}
static char *buffer;
int fileSz;
fseek(file, 0, SEEK_END);
fileSz = ftell(file);
fseek(file, 0, SEEK_SET);
buffer = (char*) malloc((fileSz + 1) * sizeof(char));
if (!buffer)
{
perror("Unable to allocate buffer!");
exit(0);
}
fread(buffer, sizeof(char), fileSz, file);
while (1)
{
time_t t;
srand((unsigned) time(&t));
int sub = rand() % 5 + 1;
char del;
switch (sub)
{
case 1:
del = 'A';
break;
case 2:
del = 'B';
break;
case 3:
del = 'C';
break;
case 4:
del = 'D';
break;
case 5:
del = 'E';
}
int nrOfQues = no_of_questions(buffer, del);
if (nrOfQues == 0)
{
perror("main(): no_of_questions() returned 0. Unsupported text structure in file or incorrect file encoding!");
fclose(file);
exit(0);
}
int qNo = rand() % nrOfQues + 1;
char *ques = pick_question(buffer, del, qNo);
if (ques)
{
printf("\n\n");
puts(ques);
printf("\n\n");
}
else
{
perror("main(): pick_question() returned NULL. Unsupported text structure in file!");
fclose(file);
exit(0);
}
printf("\n\n");
printf("Do you want to see the answer(y/n)?");
char ans, repeat;
scanf("%c", &ans);
if ( ans == 'Y' || ans == 'y')
{
char *ans = print_answer(buffer, del, qNo);
if (ans)
{
printf("\n\n");
puts(ans);
printf("\n\n");
}
else
{
printf("\n\n");
perror("main(): print_answer() returned NULL. Unsupported text structure in file!");
fclose(file);
exit(0);
}
}
printf("Do you want to try more questions (y/n)?");
clear();
scanf("%c", &repeat);
if (repeat == 'N' || repeat == 'n')
{
break;
}
clear();
}
printf("\n\n");
printf("******** Thank you for using TULE Master! ********");
printf("\n\n");
fclose(file);
return 0;
}
char * pick_question(char * buffer, char sub, int qNo)
{
char tmpBuff[20];
char tmpBuff2[20];
const char * searchStr = "FRÅGA";
const char * searchStr2 = "A 1 SVAR:";
const char * searchStr3 = "*****************************************";
char *pStr, *currPos, *nStr, *tmpStr, *tmpStr2;
currPos = buffer;
int count = snprintf(tmpBuff, 20, "FRÅGA %c %d", sub, qNo);
if (count >= 0 || count < 20)
{
if (debug)
{
printf("tmpBuff is %s\n", tmpBuff);
}
currPos = strstr(currPos, tmpBuff);
if (currPos)
{
pStr = currPos;
nStr = currPos + 1;
nStr = strstr(nStr, searchStr);
if (!nStr)
{
nStr = currPos;
nStr = strstr(nStr, searchStr2);
if (!nStr)
{
printf("pick_qestion(): nStr is NULL. Unsupported "
"text structure");
return NULL;
}
}
// Check if it is a scenario based question
count = snprintf(tmpBuff2, 20, "FRÅGA %c %d", sub, qNo-1);
if (count >= 0 || count < 20)
{
tmpStr = strstr(buffer, tmpBuff2);
tmpStr2 = strstr(tmpStr, searchStr3);
if (tmpStr < tmpStr2 && tmpStr2 < pStr)
{
pStr = tmpStr2;
}
}
int qLen = nStr - pStr;
char *ques = malloc(sizeof(char) * (qLen+1));
snprintf(ques,qLen,"%s", pStr);
return ques;
}
else
{
printf("pick_qestion(): string \"FRÅGA\" not found in file!");
return NULL;
}
}
printf("pick_qestion(): snprintf was not successful!");
return NULL;
}
char * print_answer(char * buffer, char sub, int qNo)
{
char tmpBuff[20];
char *pStr, *currPos, *nStr;
int count = snprintf(tmpBuff, 20, "%c %d SVAR:", sub, qNo);
if (count >= 0 || count < 20)
{
currPos = strstr(buffer, tmpBuff);
if (!currPos)
{
printf("print_answer(): string \"SVAR\" not found in file!");
}
pStr = currPos;
nStr = currPos + 1;
char tmpBuff2[20];
int count = snprintf(tmpBuff2, 20, "%c %d SVAR:", sub, qNo+1);
if (count < 0 || count >= 20)
{
printf("print_answer(): snprint was not successful!");
return NULL;
}
nStr = strstr(nStr, tmpBuff2);
if (!nStr)
{
nStr = buffer + strlen(buffer);
}
int ansLen = nStr - pStr;
char *ans = malloc(sizeof(char) * (ansLen+1));
snprintf(ans, ansLen, "%s", pStr);
return ans;
}
printf("print_answer(): snprint was not successful!");
return NULL;
}
int no_of_questions(char *buffer, char sub)
{
char tmpBuff[20];
char *currPos, *pStr;
int count = snprintf(tmpBuff, 20, "FRÅGA %c", sub);
if (count >= 0 || count < 20)
{
if (debug)
{
printf("tmpBuff is %s\n", tmpBuff);
}
currPos = strstr(buffer, tmpBuff);
while (currPos != NULL)
{
pStr = currPos;
currPos = currPos + 1;
currPos = strstr(currPos, tmpBuff);
}
if (pStr != buffer)
{
pStr += 9;
char tmpBuff2[20];
memcpy(tmpBuff2, pStr, 2);
if (debug)
{
printf("No. of questions for %c DEL is are %d\n", sub,
atoi(tmpBuff2));
}
return atoi(tmpBuff2);
}
return 0;
}
return 0;
}
void clear()
{
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
}
This is the file that is given as input to the program:
Link

Resources