i write a code for calculator in gtk3 c the code is total numbers, in i write 1 1 1 1 the result is 3 1 i want to fix to 4 calcul result
in i write sprintf(result,"%d%s",temp,rest); the result for 1 1 1 1 is 3 1 i want to result 4 i check for sprintf(result,"%d",temp); is not correct.
the code of application :
#include<gtk/gtk.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
int calculate(int x ,int y ,char op)
{
if(op == ' ')
{
return x y;
}
return -1;
}
char *parseMath(const char *s, char *result)
{
int x;
int y;
char op;
sscanf(s, "%d%c%d", &x,&op,&y);
int offset = snprintf(NULL,0,"%d%c%d",x,op,y);
const char *rest = s offset;
int temp = calculate(x, y, op);
printf("%d\n",strlen(result));
sprintf(result,"%d%s",temp,rest);
if(rest[0]=='\0')
{
return result;
}else
{
return parseMath(result,result);
}
}
static void on_button_press(GtkWidget *widget, gpointer buffer)
{
const char *label = gtk_button_get_label(GTK_BUTTON(widget));
if(*label=='=')
{
const char *exp = gtk_entry_buffer_get_text(buffer);
char *result = malloc(sizeof(int)*8/3 2 strlen(exp));
char *ans = parseMath(exp,result);
gtk_entry_buffer_set_text(buffer,ans,-1);
assert(result!=NULL);
free(result);
}else{
guint len_buff = gtk_entry_buffer_get_length(buffer);
gtk_entry_buffer_insert_text(buffer, len_buff, label, -1);
}
}
int main(int argc, char **argv)
{
gtk_init(&argc,&argv);
GtkWidget *window;
GtkWidget *entry;
GtkWidget *button,*button2,*button3,*button4;
GtkWidget *grid;
GtkEntryBuffer *buffer;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"calculator");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
grid = gtk_grid_new();
gtk_container_add(GTK_CONTAINER(window),grid);
buffer = gtk_entry_buffer_new(NULL,-1);
entry = gtk_entry_new();
gtk_entry_set_buffer(GTK_ENTRY(entry), GTK_ENTRY_BUFFER(buffer));
gtk_grid_attach(GTK_GRID(grid), entry, 0, 0, 4, 1);
button = gtk_button_new_with_label("0");
g_signal_connect(button, "clicked", G_CALLBACK(on_button_press), buffer);
gtk_grid_attach(GTK_GRID(grid),button, 0, 1, 1, 1);
button2 = gtk_button_new_with_label(" ");
g_signal_connect(button2, "clicked", G_CALLBACK(on_button_press), buffer);
gtk_grid_attach(GTK_GRID(grid),button2, 1, 1, 1, 1);
button3 = gtk_button_new_with_label("1");
g_signal_connect(button3, "clicked", G_CALLBACK(on_button_press), buffer);
gtk_grid_attach(GTK_GRID(grid),button3, 2, 1, 1, 1);
button4 = gtk_button_new_with_label("=");
g_signal_connect(button4, "clicked", G_CALLBACK(on_button_press), buffer);
gtk_grid_attach(GTK_GRID(grid),button4, 3, 1, 1, 1);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
CodePudding user response:
First of all, if you remove all the unrelated code from your example, we get this MCVE:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int calculate(int x ,int y ,char op)
{
if(op == ' ')
{
return x y;
}
return -1;
}
char *parseMath(const char *s, char *result)
{
int x;
int y;
char op;
sscanf(s, "%d%c%d", &x,&op,&y);
int offset = snprintf(NULL,0,"%d%c%d",x,op,y);
const char *rest = s offset;
int temp = calculate(x, y, op);
printf("%zu\n",strlen(result));
sprintf(result,"%d%s",temp,rest);
if(rest[0]=='\0')
{
return result;
}else
{
return parseMath(result,result);
}
}
int main(void)
{
const char *exp = "1 1 1 1";
char *result = malloc(sizeof(int)*8/3 2 strlen(exp));
char *output = parseMath(exp, result);
printf("output: %s\n", output);
}
That's much easier for everyone to read as it does not distract with GTK stuff that is not related to your problem with formatting your text.
You should get compiler warning for this line:
printf("%d\n",strlen(result));
Function strlen returns size_t and the correct type to print such a value is %zu, not %d.
That line also contains another problem:
When you first call that function, you pass the result of malloc which points to uninitialized memory. Accessing such a block of memory causes undefined behaviour.
But these 2 issues do not cause your problem.
When you run your program in a debugger (which you clearly should do!) you will see that the first call to parseMath will create the correct content for sprintf(result,"%d%s",temp,rest);: "2 1 1". And rest will point to " 1 1" as expected
But then things go wrong. When you call this function recursively you will notice that rest changes from " 1" to "" after you call sprintf(result,"%d%s",temp,rest); to create your string.
If you look at the manpage for 'sprintf' you will find that
C99 and POSIX.1-2001 specify that the results are undefined if a call to sprintf(), snprintf(), vsprintf(), or vsnprintf() would cause copying to take place between objects that overlap (e.g., if the target string array and one of the supplied input arguments refer to the same buffer). See NOTES.
And other than with your first call to parseMath you provide the same buffer twice when you call it recursively: return parseMath(result,result);
The terminating 0 byte of your calculated result "3 1" overwrites the ' ' of rest and you decide you have completed your task.
To fix that problem you need to create a copy of that buffer instead of just pointing into s.
Finally I stumbled over that weird expression:
char *result = malloc(sizeof(int)*8/3 2 strlen(exp));
Where did you get that formula? You are removing 2 numbers 1 operator and replace them with 1 number. The result cannot be longer than the initial input. Just use strlen(exp) 1 to allocate your memory.
Together with the other fixes we get this corrected version:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int calculate(int x ,int y ,char op)
{
if(op == ' ')
{
return x y;
}
return -1;
}
char *parseMath(const char *s, char *result)
{
int x;
int y;
char op;
sscanf(s, "%d%c%d", &x,&op,&y);
int offset = snprintf(NULL,0,"%d%c%d",x,op,y);
char *rest = strdup(s offset);
int temp = calculate(x, y, op);
printf("%zu\n",strlen(result));
int done = rest[0]=='\0';
sprintf(result,"%d%s",temp,rest);
free(rest);
if(done)
{
return result;
}else
{
return parseMath(result,result);
}
}
int main(void)
{
const char *exp = "1 1 1 1";
char *result = malloc(strlen(exp) 1);
*result = 0;
char *output = parseMath(exp, result);
printf("output: %s\n", output);
}
