我在gtk3c中写了一个计算器的代码,代码是总数,在我写1+1+1+1的时候,结果是3+1,我想要修正为4 [英] 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

查看:10
本文介绍了我在gtk3c中写了一个计算器的代码,代码是总数,在我写1+1+1+1的时候,结果是3+1,我想要修正为4的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在gtk3c中写了一个计算器代码,代码是总数,在我写1+1+1+1时,结果是3+1,我想要修正为4 calcul result

在我编写的Sprintf(Result,%d%s";,temp,rest)中;1+1+1+1的结果是3+1我想结果4 我检查Sprintf(Result,%d";,Temp);是否不正确。

应用代码:

#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
",strlen(result));
    sprintf(result,"%d%s",temp,rest);

    if(rest[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;
}

推荐答案

首先,如果从您的示例中删除所有不相关的代码,我们将获得以下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
",strlen(result));
    sprintf(result,"%d%s",temp,rest);

    if(rest[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
", output);
}

这对每个人来说都更容易阅读,因为它不会因为与您的文本格式问题无关的GTK内容而分心。

您应该收到以下行的编译器警告:

printf("%d
",strlen(result));

函数strlen返回size_t,打印这样的值的正确类型是%zu,而不是%d

该行还包含另一个问题: 当您第一次调用该函数时,将传递malloc的结果,该结果指向未初始化的内存。访问这样的内存块会导致未定义的行为。

但这两个问题不会导致您的问题。

当您在调试器中运行程序时(显然您应该这样做!)您将看到,第一次调用parseMath将为sprintf(result,"%d%s",temp,rest);"2+1+1"创建正确的内容。和rest将按预期指向"+1+1"

但随后事情就出了问题。当您以递归方式调用此函数时,您会注意到在调用sprintf(result,"%d%s",temp,rest);创建字符串后,rest"+1"更改为""

如果您查看manpage for 'sprintf',您会发现

   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.

与第一次调用parseMath不同,您在递归调用return parseMath(result,result);时提供了两次相同的缓冲区:return parseMath(result,result);

计算结果的终止0字节"3+1"覆盖rest'+',您决定已完成任务。

要解决该问题,您需要创建该缓冲区的副本,而不是只指向s

最后我无意中发现了那个奇怪的表达:

char *result = malloc(sizeof(int)*8/3+2+strlen(exp));

你从哪里得到这个配方的?您正在删除2个数字+1个运算符,并将其替换为1个数字。结果不能长于初始输入。只需使用strlen(exp) + 1即可分配内存。

与其他修复程序一起,我们得到了此更正版本:

#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
",strlen(result));
    int done = rest[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
", output);
}

这篇关于我在gtk3c中写了一个计算器的代码,代码是总数,在我写1+1+1+1的时候,结果是3+1,我想要修正为4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆