Creating Multiple Instances of One Glade Window - c

I am running multiple threads and need to create a copy of the same window across each thread. Each one is display values relevant to what that thread is doing (calculating prime numbers in this case).
#include "stress.h"
//------------------------------
void windowUpdate(int *ptr) {
//------------------------------
GtkLabel *lbl_thread;
GtkLabel *lbl_total;
GtkLabel *lbl_latest;
lbl_thread = GTK_LABEL(gtk_builder_get_object(stressBuilder, "lbl_thread"));
char buffer[512];
sprintf(buffer, "%i", ptr);
gtk_label_set_text(lbl_thread, buffer);
}
//------------------------------
void windowCreate() {
//------------------------------
//This is where the window instance code will eventually live
}
//------------------------------
void prime(int *ptr) {
//------------------------------
int i = 3, count, c;
const int n = INT_MAX;
if ( n >= 1 ) {
printf("First %d prime numbers are :\n",n);
printf("2\n");
}
for ( count = 2 ; count <= n ; ) {
for ( c = 2 ; c <= i - 1 ; c++ ) {
if ( i%c == 0 )
break;
}
if ( c == i ) {
printf("Thread %i: %d\n", ptr, i);
count++;
}
i++;
}
}
//------------------------------
void debugMesg(int *ptr) {
//------------------------------
printf("A thread with ID: %i was created\n", ptr);
windowUpdate(ptr);
prime(ptr);
}
//------------------------------
void genThreads(GtkBuilder *builder, int threads) {
//------------------------------
XInitThreads();
stressBuilder = builder; //points to the builder used in main()
//------------------------------
GtkWidget *winStress;
//------------------------------
winStress = GTK_WIDGET(gtk_builder_get_object(stressBuilder, "win_thread"));
gtk_widget_queue_draw(winStress);
gtk_widget_show(winStress);
int proc[threads];
pthread_t prime[threads];
char* id;
for(int i = 0; i < threads; i++) {
id = (char) i;
proc[i] = pthread_create(&prime[i], NULL, debugMesg, (int *) id);
}
}
genThreads() is the function where the threads are created. It's also temporarily responsible for displaying the win_thread window. the windowUpdate() function needs to be able to alter the values for the instance of the window corresponding to the thread its running on.
I'm fairly new to using threads btw, in case I've made any rookie errors.
The whole program is a bit to long to post here, so here is a link to the repo in case you want to look at main() or stress.h or something.
Thanks everyone :D

Related

pthread_create, struct, c, Show next value

I created a transfer list. Agents will make the transfers. There is a separate transfer list for each club.
When I want to suppress the list for club A (Agent1 thread function); It switches to the second agent value without suppressing the first agent value.
Do you have a problem with the point?
struct Club
{
int budget;
}A,B,C,D,E;
struct Player
{
int id;
int Pbudget;
int AgentID;
char position[15];
char club[1];
}players[22];
struct Agent
{
int forward ;
int midfielder;
int defender;
int goalkeeper;
}Agent[3];
void *club(void *data){
if(data == "A"){
int listA[2];
listA[0] = 0; //CLub A -> 0;
for(int i=0; i<5; i++){
listA[1] = players[alist[i]].id; // PLayer Id
if(players[alist[i]].AgentID == 0){
sem_wait(&Club[0]);
printf("Agent00 %d\n",players[alist[i]].id );
printf("Agent0 %d\n",listA[1] );
pthread_create(&agentA[0], NULL, Agent1 ,&listA);
}
}
// Agent1 thread
void *Agent1(void *num){
int clubName = *((int *)num + 0); // Club A -> 0, Club B -> 1, Club C -> 2 ...
int pID = *((int *)num ); // Player Id
if(clubName == 0){
printf("Club A negotiates with Agent- %d for a %s player\n", players[pID].AgentID, players[pID].position);
printf("Agent0- %d \n", pID);
sem_post(&Club[0]);
}

How to solve the dining philosophers problem with only mutexes?

I wrote this program to solve the dining philosophers problem using Dijkstra's algorithm, notice that I'm using an array of booleans (data->locked) instead of an array of binary semaphores.
I'm not sure if this solution is valid (hence the SO question).
Will access to the data->locked array in both test and take_forks functions cause data races? if so is it even possible to solve this problem using Dijkstra's algorithm with only mutexes?
I'm only allowed to use mutexes, no semaphores, no condition variables (it's an assignment).
Example of usage:
./a.out 4 1000 1000
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#define NOT_HUNGRY 1
#define HUNGRY 2
#define EATING 3
#define RIGHT ((i + 1) % data->n)
#define LEFT ((i + data->n - 1) % data->n)
typedef struct s_data
{
int n;
int t_sleep;
int t_eat;
int *state;
bool *locked;
pthread_mutex_t *state_mutex;
} t_data;
typedef struct s_arg
{
t_data *data;
int i;
} t_arg;
int ft_min(int a, int b)
{
if (a < b)
return (a);
return (b);
}
int ft_max(int a, int b)
{
if (a > b)
return (a);
return (b);
}
// if the LEFT and RIGHT threads are not eating
// and thread number i is hungry, change its state to EATING
// and signal to the while loop in `take_forks` to stop blocking.
// if a thread has a state of HUNGRY then it's guaranteed
// to be out of the critical section of `take_forks`.
void test(int i, t_data *data)
{
if (
data->state[i] == HUNGRY
&& data->state[LEFT] != EATING
&& data->state[RIGHT] != EATING
)
{
data->state[i] = EATING;
data->locked[i] = false;
}
}
// set the state of the thread number i to HUNGRY
// and block until the LEFT and RIGHT threads are not EATING
// in which case they will call `test` from `put_forks`
// which will result in breaking the while loop
void take_forks(int i, t_data *data)
{
pthread_mutex_lock(data->state_mutex);
data->locked[i] = true;
data->state[i] = HUNGRY;
test(i, data);
pthread_mutex_unlock(data->state_mutex);
while (data->locked[i]);
}
// set the state of the thread number i to NOT_HUNGRY
// then signal to the LEFT and RIGHT threads
// so they can start eating when their neighbors are not eating
void put_forks(int i, t_data *data)
{
pthread_mutex_lock(data->state_mutex);
data->state[i] = NOT_HUNGRY;
test(LEFT, data);
test(RIGHT, data);
pthread_mutex_unlock(data->state_mutex);
}
void *philosopher(void *_arg)
{
t_arg *arg = _arg;
while (true)
{
printf("%d is thinking\n", arg->i);
take_forks(arg->i, arg->data);
printf("%d is eating\n", arg->i);
usleep(arg->data->t_eat * 1000);
put_forks(arg->i, arg->data);
printf("%d is sleeping\n", arg->i);
usleep(arg->data->t_sleep * 1000);
}
return (NULL);
}
void data_init(t_data *data, pthread_mutex_t *state_mutex, char **argv)
{
int i = 0;
data->n = atoi(argv[1]);
data->t_eat = atoi(argv[2]);
data->t_sleep = atoi(argv[3]);
pthread_mutex_init(state_mutex, NULL);
data->state_mutex = state_mutex;
data->state = malloc(data->n * sizeof(int));
data->locked = malloc(data->n * sizeof(bool));
while (i < data->n)
{
data->state[i] = NOT_HUNGRY;
data->locked[i] = true;
i++;
}
}
int main(int argc, char **argv)
{
pthread_mutex_t state_mutex;
t_data data;
t_arg *args;
pthread_t *threads;
int i;
if (argc != 4)
{
fputs("Error\nInvalid argument count\n", stderr);
return (1);
}
data_init(&data, &state_mutex, argv);
args = malloc(data.n * sizeof(t_arg));
i = 0;
while (i < data.n)
{
args[i].data = &data;
args[i].i = i;
i++;
}
threads = malloc(data.n * sizeof(pthread_t));
i = 0;
while (i < data.n)
{
pthread_create(threads + i, NULL, philosopher, args + i);
i++;
}
i = 0;
while (i < data.n)
pthread_join(threads[i++], NULL);
}
Your spin loop while (data->locked[i]); is a data race; you don't hold the lock while reading it data->locked[i], and so another thread could take the lock and write to that same variable while you are reading it. In fact, you rely on that happening. But this is undefined behavior.
Immediate practical consequences are that the compiler can delete the test (since in the absence of a data race, data->locked[i] could not change between iterations), or delete the loop altogether (since it's now an infinite loop, and nontrivial infinite loops are UB). Of course other undesired outcomes are also possible.
So you have to hold the mutex while testing the flag. If it's false, you should then hold the mutex until you set it true and do your other work; otherwise there is a race where another thread could get it first. If it's true, then drop the mutex, wait a little while, take it again, and retry.
(How long is a "little while", and what work you choose to do in between, are probably things you should test. Depending on what kind of fairness algorithms your pthread implementation uses, you might run into situations where take_forks succeeds in retaking the lock even if put_forks is also waiting to lock it.)
Of course, in a "real" program, you wouldn't do it this way in the first place; you'd use a condition variable.

How to control pthreads with multiple mutexes and conditions?

In the code below I wrote a program to perform add/remove operations on an int array using multithreading. The condition is that multiple threads cannot make operations on the same cell, but parallel operations can be made on different cells.
I thought in order to implement such conditions I'd need to use multiple mutexes and condition variables, to be exact, as many as there're cells in the array. The initial value of all cells of my array is 10 and threads increment/decrement this value by 3.
The code below seems to work (the cell values of the array after all threads finished working is as expected) but I don't understand a few things:
I first spawn adder threads which sleep for a second. In addition each thread has printf statement which is triggered if a thread waits. Remove threads don't sleep so I expect remove threads to invoke their printf statements because they must wait a second at least before adder threads finish their work. But remover threads never call printf.
My second concern: as I mentioned I first spawn adder threads so I expect the cells value go from 10 to 13. Then if remover thread acquires lock the value can go from 13 to 10 OR if adder thread acquires the lock then the cell value will go from 13 to 16. But I don't see the behavior in printf statements inside threads. For example one of the printf sequences I had: add thread id and cell id 1: cell value 10->13, then remove thread id and cell id 1: cell value 10->7 then add thread id and cell id 1: cell value 10->13. This doesn't make sense. I made sure that the threads all point to the same array.
Bottom line I'd like to know whether my solution is correct and if yes why is the behavior I described occurring. If my solution is incorrect I'd appreciate example of correct solution or at least general direction.
This is the code (all the logic is in AdderThread, RemoveThread):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define ARR_LEN 5
#define THREADS_NUM 5
#define INIT_VAL 10
#define ADD_VAL 3
#define REMOVE_VAL 3
#define ADDER_LOOPS 2
typedef struct helper_t {
int threadId;
int * arr;
int * stateArr; //0 if free, 1 if busy
} helper_t;
enum STATE {FREE, BUSY};
enum ERRORS {MUTEX, COND, CREATE, JOIN, LOCK, UNLOCK, WAIT, BROADCAST};
pthread_mutex_t mutexArr[THREADS_NUM];
pthread_cond_t condArr[THREADS_NUM];
void errorHandler(int errorId) {
switch (errorId) {
case MUTEX:
printf("mutex error\n");
break;
case COND:
printf("cond error\n");
break;
case CREATE:
printf("create error\n");
break;
case JOIN:
printf("join error\n");
break;
case LOCK:
printf("lock error\n");
break;
case UNLOCK:
printf("unlock error\n");
break;
case WAIT:
printf("wait error\n");
break;
case BROADCAST:
printf("broadcast error\n");
break;
default:
printf("default switch\n");
break;
}
}
void mallocError() {
printf("malloc error\nExiting app\n");
exit(EXIT_FAILURE);
}
void initMutexesAndConds(pthread_mutex_t * mutexArr, pthread_cond_t * condArr) {
int i;
for(i = 0; i < THREADS_NUM; i++) {
pthread_mutex_init(&mutexArr[i], NULL);
pthread_cond_init(&condArr[i], NULL);
}
}
helper_t * initStructs(int * arr, int * stateArr) {
int i;
helper_t * helpers = (helper_t *) malloc(sizeof(helper_t) * THREADS_NUM);
if(!helpers) {
mallocError();
} else {
for(i = 0; i < THREADS_NUM; i++) {
helpers[i].threadId = i;
helpers[i].arr = arr;
helpers[i].stateArr = stateArr;
}
}
return helpers;
}
void printArr(int * arr, int len) {
int i;
for(i = 0; i < len; i++) {
printf("%d, ", arr[i]);
}
printf("\n");
}
void * AdderThread(void * arg) {
int i;
helper_t * h = (helper_t *) arg;
int id = h->threadId;
for(i = 0; i < ADDER_LOOPS; i++) {
pthread_mutex_t * mutex = &mutexArr[id];
pthread_cond_t * cond = &condArr[id];
if(pthread_mutex_lock(mutex)) {
errorHandler(LOCK);
}
while(h->stateArr[id] == BUSY) {
printf("adder id %d waiting...\n", id);
if(pthread_cond_wait(cond, mutex)) {
errorHandler(WAIT);
}
}
h->stateArr[id] = BUSY;
sleep(1);
h->arr[id] = h->arr[id] + ADD_VAL;
printf("add thread id and cell id %d: cell value %d->%d\n", id, h->arr[id]-ADD_VAL, h->arr[id]);
h->stateArr[id] = FREE;
if(pthread_cond_broadcast(cond)) {
errorHandler(BROADCAST);
}
if(pthread_mutex_unlock(mutex)) {
errorHandler(UNLOCK);
}
}
pthread_exit(NULL);
}
void * RemoveThread(void * arg) {
helper_t * h = (helper_t *) arg;
int id = h->threadId;
pthread_mutex_t * mutex = &mutexArr[id];
pthread_cond_t * cond = &condArr[id];
if(pthread_mutex_lock(mutex)) {
errorHandler(LOCK);
}
while(h->stateArr[id] == BUSY) {
printf("remover id %d waiting...\n", id);
if(pthread_cond_wait(cond, mutex)) {
errorHandler(WAIT);
}
}
h->stateArr[id] = BUSY;
h->arr[id] = h->arr[id] - REMOVE_VAL;
printf("remove thread id and cell id %d: cell value %d->%d\n", id, h->arr[id], h->arr[id]-ADD_VAL);
h->stateArr[id] = FREE;
if(pthread_cond_broadcast(cond)) {
errorHandler(BROADCAST);
}
if(pthread_mutex_unlock(mutex)) {
errorHandler(UNLOCK);
}
pthread_exit(NULL);
}
int main() {
int i;
helper_t * adderHelpers;
helper_t * removeHelpers;
pthread_t adders[THREADS_NUM];
pthread_t removers[THREADS_NUM];
int * arr = (int *) malloc(sizeof(int) * ARR_LEN);
int * stateArr = (int *) malloc(sizeof(int) * ARR_LEN);
if(!arr || !stateArr) {
mallocError();
}
for(i = 0; i < ARR_LEN; i++) {
arr[i] = INIT_VAL;
stateArr[i] = FREE;
}
initMutexesAndConds(mutexArr, condArr);
adderHelpers = initStructs(arr, stateArr);
removeHelpers = initStructs(arr, stateArr);
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&adders[i], NULL, AdderThread, &adderHelpers[i]);
pthread_create(&removers[i], NULL, RemoveThread, &removeHelpers[i]);
}
for(i = 0; i < THREADS_NUM; i++) {
pthread_join(adders[i], NULL);
pthread_join(removers[i], NULL);
}
printf("the results are:\n");
printArr(arr, THREADS_NUM);
printf("DONE.\n");
return 0;
}
1) This code sequence in Addr:
h->stateArr[id] = BUSY;
sleep(1);
h->arr[id] = h->arr[id] + ADD_VAL;
printf("add thread id and cell id %d: cell value %d->%d\n", id, h->arr[id]-ADD_VAL, h->arr[id]);
h->stateArr[id] = FREE;
Is execute with the mutex locked; thus Remove would never get a chance to see the state as anything but FREE.
2) There is no guarantee that mutex ownership alternates (afaik), but at the very least, to properly co-ordinate threads you should never rely upon such an implementation detail. It is the difference between working and “happens to work”, which usually leads to “used to work”....
If you put the sleep() between the mutex unlock and mutex lock, you might have a better case, but as it is, it just unlocks it then locks it again, so the system is well within its rights to just let it continue executing.
[ I ran out of space in comments ... ]:
Yes, the condition variables are doing nothing for you here. The idea of a condition variable is to be able to be notified when a significant event, such as a state change, has occurred on some shared objection.
For example, a reservoir might have a single condition variable for the water level. Multiplexed onto that might be many conditions: level < 1m; level > 5m; level > 10m. To keep the systems independent (thus working), the bit that updates the level might just:
pthread_mutex_lock(&levellock);
level = x;
pthread_cond_broadcast(&newlevel);
pthread_mutex_unlock(&levellock);
The actors implementing the conditions would do something like:
pthread_mutex_lock(&levellock);
while (1) {
if (level is my conditions) {
pthread_mutex_unlock(&levellock);
alert the media
pthread_mutex_lock(&levellock);
}
pthread_cond_wait(&newlevel, &levellock);
}
Thus I can add many “condition monitors” without breaking the level setting code, or the overall system. Many is finite, but by releasing the mutex while I alert the media, I avoid having my water monitoring system rely on the alarm handling.
If you are familiar with “publish/subscribe”, you might find this familiar. This is fundamentally the same model, just the PS hides a pile of details.

C how to run a loop in the background

I am making a "Clicker-Game". It's my first real game that I'm doing alongside school. I got all of the game code complete but I want to have a loop in the background that adds geldps(money per second) after every second.
I tried threads but I don't really understand it and we won't learn that until next year, so I´m asking, if anyone can either tell me a better way to make a loop in the background that runs independent from the main program, and can just add geldps to geld every second. Thanks.
PS: I am sorry for the German variables. Ask me if you don't know what sth means or anything, and it´s probably not very well organised and everything.
#include <stdio.h>
int geldps=0,geld=0;
int main()
{
int stand=0, oil=0, Mine=0, Bank=0,standzahl=100, Minezahl=500, Bankzahl=1000, oilzahl=10000, Werkzeug=0, Werkzeugzahl=10;
char input, input2;
float faktor;
do
{
system("cls");
faktor=1+Werkzeug/10;
printf("%c%c%c%c%c%c%c%c%c%c%c\n",201,205,205,205,205,205,205,205,205,205,187);
printf(" %d$\n",geld);
printf("%c%c%c%c%c%c%c%c%c%c%c\n",200,205,205,205,205,205,205,205,205,205,188);
printf(" Space to get money\n U to go to Upgrades\n Escape to leave");
input=getch();
if(input==32)
{
geld=geld+faktor;
continue;
}
if(input == 117 || input == 85)
{
system("cls");
do
{
system("cls");
printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\n 1 - Lemon Stands(%d)(%d$)\n 2 - Mines(%d)(%d$)\n 3 - Banks(%d)(%d$)\n 4 - Oil Refinerys(%d)(%d$)\nBackspace to go back", Werkzeug, Werkzeugzahl, stand, standzahl, Mine, Minezahl, Bank, Bankzahl, oil, oilzahl);
input2=getch();
if(input2== 48)
{
if(geld<Werkzeugzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Werkzeugzahl,geld);
system("pause");
continue;
}
geld=geld-Werkzeugzahl;
Werkzeug++;
Werkzeugzahl=Werkzeugzahl+Werkzeugzahl/10;
}
if(input2== 49)
{
if(geld<standzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",standzahl,geld);
system("pause");
continue;
}
geld=geld-standzahl;
stand++;
standzahl=standzahl+standzahl/10;
}
if(input2== 50)
{
if(geld<Minezahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Minezahl,geld);
system("pause");
continue;
}
geld=geld-Minezahl;
Mine++;
Minezahl=Minezahl+Minezahl/10;
geldps=geldps+1;
}
if(input2== 51)
{
if(geld<Bankzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Bankzahl,geld);
system("pause");
continue;
}
geld=geld-Bankzahl;
Bank++;
Bankzahl=Bankzahl+Bankzahl/10;
geldps=geldps+10;
}
if(input2== 52)
{
if(geld<oilzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",oilzahl,geld);
system("pause");
continue;
}
geld=geld-oilzahl;
oil++;
oilzahl=oilzahl+oilzahl/10;
geldps=geldps+100;
}
}
while(input2!=8);
}
}
while(input!=27);
return 0;
}
update: I was procrastinating and cleaned and improved your code. At the end of this answer.
If all you need is for a number to be consistently incremented based on time, add a function that updates a value based on time.
Here's an example showing not only how to do that but also how to compartmentalize your code into functions and how to use better code formatting and variable names.
#include <stdio.h> // printf()
#include <time.h> // time()
#include <stdlib.h> // random()
#include <unistd.h> // sleep()
int updateValue(int lastValue, int amountPerSecond) {
static time_t lastTime = -1;
time_t currentTime = time(NULL);
int newValue = lastValue;
if (lastTime != -1) {
newValue += amountPerSecond * (currentTime - lastTime);
}
lastTime = currentTime;
return newValue;
}
void seedRandom() {
// Don't use this in production code.
srandom(time(NULL));
}
int sleepRandomly() {
const int SLEEP_RANGE_IN_SECS = 5;
// sleep( 0..5 seconds )
int timeToSleep = random() % (SLEEP_RANGE_IN_SECS + 1);
sleep(timeToSleep);
return timeToSleep;
}
int main() {
const int AMOUNT_PER_SECOND = 5;
int value = 0;
// How many times to run the loop
int numCycles = 5;
seedRandom();
// Initialize the updateValue() start time
value = updateValue(value, AMOUNT_PER_SECOND);
while (numCycles--) {
int amountSlept = sleepRandomly();
int newValue = updateValue(value, AMOUNT_PER_SECOND);
printf("Slept %d seconds.", amountSlept);
printf("Value updated: %10d + (%d secs * %4d amount/secs) = %10d\n",
value, amountSlept, AMOUNT_PER_SECOND, newValue);
value = newValue;
}
return 0;
}
Cleaned up version of your code, and then I just kept improving it.
#include <stdio.h> // printf()
#include <string.h> // strlen()
#include <stdarg.h> // vsnprintf()
#include <unistd.h> // STDIN_FILENO
#include <sys/time.h> // gettimeofday()
#include <time.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
// TODO: convert the menus to tables:
// key - desc count cost effect
// TODO: add all income sources in a list so it's easy to add more
// without changing code
// TODO: the current pricing is off
// TODO: convert to C++ so we can use classes
// TODO: only use one menu, it's nicer to use
// one global value so we can ensure that we restore
// stdin's terminal settings
struct termios g_oldStdinTermios;
int g_keepGoing = 1;
typedef struct {
int count;
int zahl;
int zahlIncrement;
int geldPerSecondIncrement;
} IncomeSource;
typedef struct {
char lastMessage[100];
// try to avoid global variables, pass them instead
// one variable per line
int geld;
int geldPerSecond;
int geldPerClick;
IncomeSource werkzeug;
IncomeSource stand;
// Use consistent capitalization: sound be "mine"
IncomeSource mine;
IncomeSource bank;
IncomeSource oil;
} Values;
void setLastMessage(Values *values, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
(void) vsnprintf(values->lastMessage, sizeof(values->lastMessage), fmt, ap);
va_end(ap);
}
void clearLastMessage(Values *values) {
// clear lastMessage after valid choice
values->lastMessage[0] = '\0';
}
void initializeValues(Values *values) {
clearLastMessage(values);
// use spaces around assignment and operators
values->geldPerSecond = 0;
values->geld = 10000;
// count, cost, cost increment (1/n), geldPerSecond increment
values->werkzeug = (IncomeSource){0, 10, 10, 0};
// BUG: number of stands doesn't increase geld per second
// or geld per click
values->stand = (IncomeSource){0, 100, 10, 0};
values->mine = (IncomeSource){0, 500, 10, 1};
values->bank = (IncomeSource){0, 1000, 10, 10};
values->oil = (IncomeSource){0, 10000, 10, 100};
values->geldPerClick = 1 + values->werkzeug.count / 10;
}
void clearScreen() {
// use ANSI escape sequences
const char *ANSI_MOVE_TO_1_1 = "\x1B[1;1H";
const char *ANSI_CLEAR_SCREEN = "\x1B[2J";
printf("%s%s", ANSI_CLEAR_SCREEN, ANSI_MOVE_TO_1_1);
}
char upcase(char c) {
if (c < 'a' || c > 'z') {
return c;
}
return 'A' + (c - 'a');
}
void setNonBlockingBufferingStdinTermios() {
struct termios new_;
tcgetattr(STDIN_FILENO, &g_oldStdinTermios);
new_ = g_oldStdinTermios;
new_.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &new_);
}
void restoreStdinTermios() {
tcsetattr(STDIN_FILENO, TCSANOW, &g_oldStdinTermios);
}
long getElapsedTimeInMs(struct timeval *start) {
struct timeval now;
gettimeofday(&now, NULL);
// in microseconds
long elapsed = ((now.tv_sec - start->tv_sec) * 1000000
+ now.tv_usec - start->tv_usec);
return elapsed / 1000;
}
char getCharacter() {
struct timeval start;
gettimeofday(&start, NULL);
char input = -1;
while (read(STDIN_FILENO, &input, 1) == -1
&& errno == EAGAIN
&& getElapsedTimeInMs(&start) < 500) {
}
return upcase(input);
}
void updateGeld(Values *values) {
static time_t lastTime = -1;
time_t currentTime = time(NULL);
if (lastTime != -1) {
values->geld += values->geldPerSecond * (currentTime - lastTime);
}
lastTime = currentTime;
}
void printHeader(Values *values) {
const char *UPPER_LEFT = "\u2554";
const char *UPPER_RIGHT = "\u2557";
const char *LOWER_LEFT = "\u255a";
const char *LOWER_RIGHT = "\u255d";
const char *HORIZONTAL = "\u2550";
const char *VERTICAL = "\u2551";
updateGeld(values);
// Automatically expand the box as the size
// of geld grows.
const int BORDER_WIDTH = 3;
char geldStr[20];
snprintf(geldStr, sizeof(geldStr), "$ %d", values->geld);
// Move code used more than once into its own function
clearScreen();
printf("%s", UPPER_LEFT);
for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
printf("%s", HORIZONTAL);
}
printf("%s\n", UPPER_RIGHT);
// use spaces around commas
printf("%s %s %s %s\n",
VERTICAL, geldStr, VERTICAL, values->lastMessage);
printf("%s", LOWER_LEFT);
for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
printf("%s", HORIZONTAL);
}
printf("%s\n", LOWER_RIGHT);
}
void upgrade(Values *values, IncomeSource *source) {
if (values->geld < source->zahl) {
setLastMessage(values, "Not enough money(%d/%d$)",
source->zahl, values->geld);
return;
}
clearLastMessage(values);
values->geld -= source->zahl;
source->count++;
source->zahl += source->zahl / source->zahlIncrement;
values->geldPerSecond += source->geldPerSecondIncrement;
}
char getUpgradeInput(Values *values) {
clearScreen();
printHeader(values);
printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\t\t+%d/click\n",
values->werkzeug.count, values->werkzeug.zahl, values->geldPerClick);
printf(" 1 - Lemon Stands(%d)(%d$)\t\t\t+%d/sec\n",
values->stand.count, values->stand.zahl,
values->stand.count * values->stand.geldPerSecondIncrement);
printf(" 2 - Mines(%d)(%d$)\t\t\t\t+%d/sec\n",
values->mine.count, values->mine.zahl,
values->mine.count * values->mine.geldPerSecondIncrement);
printf(" 3 - Banks(%d)(%d$)\t\t\t\t+%d/sec\n",
values->bank.count, values->bank.zahl,
values->bank.count * values->bank.geldPerSecondIncrement);
printf(" 4 - Oil Refinerys(%d)(%d$)\t\t\t+%d/sec\n",
values->oil.count, values->oil.zahl,
values->oil.count * values->oil.geldPerSecondIncrement);
printf(" Q - Back to main menu\n");
printf("> ");
fflush(stdout);
return getCharacter();
}
void upgradeLoop(Values *values) {
char input = ' ';
while (input != 'Q' && g_keepGoing) {
input = getUpgradeInput(values);
switch (input) {
case '0':
upgrade(values, &values->werkzeug);
values->geldPerClick = 1 + values->werkzeug.count / 10;
break;
case '1':
upgrade(values, &values->stand);
break;
case '2':
upgrade(values, &values->mine);
break;
case '3':
upgrade(values, &values->bank);
break;
case '4':
upgrade(values, &values->oil);
break;
case 'Q':
break;
default:
break;
}
}
}
char getMainInput(Values *values) {
printHeader(values);
// make this easier to read in the code...
printf(" _ - [Space] get money\n");
printf(" U - Upgrades\n");
printf(" Q - Quit\n");
printf("> ");
fflush(stdout);
return getCharacter();
}
void mainLoop(Values *values) {
char input = ' ';
// while..do is easier to read and understand than do..while
while (input != 'Q' && g_keepGoing) {
// Encapsulate code in functions to make your program's logic
// easier to follow
input = getMainInput(values);
// Use a switch statement here and use character values
// rather than integers
switch (input) {
case ' ':
values->geld += values->geldPerClick;
clearLastMessage(values);
break;
case 'U':
upgradeLoop(values);
clearLastMessage(values);
case 'Q':
break;
default:
break;
}
};
}
void sigintHandler(int signal) {
printf("SIGINT received, cleaning up.\n");
restoreStdinTermios();
g_keepGoing = 0;
}
int main() {
Values values;
initializeValues(&values);
setNonBlockingBufferingStdinTermios();
signal(SIGINT, sigintHandler);
mainLoop(&values);
restoreStdinTermios();
return 0;
}

Process exited with return value 255, w/pointers to structures

I have some functions that should allow me to manage a structure which was allocated dynamically. The allocation of the memory and the input of data in those is no real problem, though my program stops when it reaches a certain line of code: (No warning or problems detected)
if(codeV == p_vendite[ctrl_j].p_venditore[ctrl_i].codVenditore)
This line is in the function called VenditeProdotto(Vendite *p_vendite).
Here's the important part of the code (defining structures)
typedef struct _Venditore {
int codVenditore;
int codProdotto;
int qty;
} Venditore;
typedef struct _Vendite{
int mmGG;
Venditore *p_venditore;
} Vendite;
void AggiungiVendita (Vendite *p_vendite);
void VenditeProdotto(Vendite *p_vendite);
void VenditeVenditore(Vendite *p_vendite);
...
Here's main():
int main() {
int check, i, count, flag, choice;
Vendite *p_Vendite;
...
...
p_Vendite = (Vendite*) calloc(numVenditori,sizeof(Vendite));
...
...
p_Vendite->p_venditore = (Venditore*)calloc(numVenditori,sizeof(Venditore));
/*menu*/
flag = TRUE;
do{
choice = menu();
switch (choice) {
case 1 : AggiungiVendita(p_Vendite); break;
...
case 3 : VenditeProdotto(p_Vendite); break;
case 4 : VenditeVenditore(p_Vendite); break;
...
}
} while (flag == TRUE);
return 0;
}
And here are the functions:
void AggiungiVendita (Vendite *p_vendite) {
int flag, check, answer;
i = 0;
do{
/*input of struct - codVenditore,codProdotto,qty*/
...
check = scanf("%d", &(p_vendite[j].p_venditore[i].codVenditore));
...
/*input*/
check = scanf("%d", &(p_vendite[j].p_venditore[i].codProdotto) );
...
/*controllo sull'input*/
check = scanf("%d", &(p_vendite[j].p_venditore[i].qty) );
...
...
//asking to redo or quit
} while(flag == TRUE && i < numVenditori);
return;
}
int menu() {
//just a standard menu, no problem here
...
return choice;
}
void VenditeProdotto(Vendite *p_vendite) {
int check = 0, codeP = 0, ctrl_i = 0, ctrl_j = 0; //ctrl_i,ctrl_j are increasing variables and I use them to search among the structures
...//input, continues after
Where I find the debug error: (line 3 after this)
for(ctrl_j = 0; ctrl_j < numVendite; ctrl_j++) {
for(ctrl_i = 0; ctrl_i < numVenditori; ctrl_i++) {
if (codeP == p_vendite[ctrl_j].p_venditore[ctrl_i].codProdotto)
printf("\nSeller %d, quantity sold: %d in day %d", p_vendite[ctrl_j].p_venditore[ctrl_i].codVenditore, p_vendite[ctrl_j].p_venditore[ctrl_i].qty, ctrl_j+1);
else
continue;
}
}
return;
}
Basically I don't know if it's really legit to use the first line of code that I've talked about, with . instead of ->, but if I try to change the syntax I get detected errors. Any ideas?
At first I thought about something like (p_vendite+ctrl_j)->(p_venditore+ctrl_i)->codProdotto, since it's a pointer but it doesn't seem working.
There are a couple of obvious bugs:
Allocation of Vendite
You're allocating numVenditori elements for p_Vendite, but later on you are iterating numVendite times over the same pointer:
p_Vendite = (Vendite*) calloc(numVenditori,sizeof(Vendite));
...
for(ctrl_j = 0; ctrl_j < numVendite; ctrl_j++) {
for(ctrl_i = 0; ctrl_i < numVenditori; ctrl_i++) {
if (codeP == p_vendite[ctrl_j].p_venditore[ctrl_i].codProdotto)
The allocation should read:
p_Vendite = (Vendite*) calloc(numVendite,sizeof(Vendite));
or as I would prefer it:
p_Vendite = calloc (numVendite, sizeof *p_Vendite);
Allocation of Venditore
p_Vendite->p_venditore = (Venditore*)calloc(numVenditori,sizeof(Venditore));
You're only allocating the p_venditore element for one of your Vendite structs. You need to allocate all of them in a loop:
for (int j = 0; j < numVendite; j++) {
p_Vendite[j].p_venditore = (Venditore*)calloc(numVenditori,sizeof(Venditore));
// And check for allocation errors
}

Resources