我在 gtk3 c 中寫了一個計算器代碼,代碼是總數,在我寫 1 1 1 1 結果是 3 1 我想修復 4 計算 結果
在我寫 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\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;
}
uj5u.com熱心網友回復:
首先,如果您從示例中洗掉所有不相關的代碼,我們會得到這個 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);
}
這對每個人來說都更容易閱讀,因為它不會分散與您的文本格式問題無關的 GTK 內容。
您應該收到此行的編譯器警告:
printf("%d\n",strlen(result));
函式strlen回傳size_t并且列印這樣一個值的正確型別是%zu,不是%d。
該行還包含另一個問題:當您第一次呼叫該函式時,您將其結果傳遞malloc給未初始化的記憶體。訪問這樣的記憶體塊會導致未定義的行為。
但是這兩個問題不會導致您的問題。
當您在除錯器中運行程式時(您顯然應該這樣做!),您將看到第一次呼叫parseMath將為sprintf(result,"%d%s",temp,rest);:創建正確的內容"2 1 1"。并且會按預期rest指向" 1 1"
但后來事情出錯了。當您遞回呼叫此函式時,您會注意到在呼叫創建字串后rest從" 1"變為。""sprintf(result,"%d%s",temp,rest);
如果您查看“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);
計算結果的終止 0 位元組將"3 1"覆寫' 'of 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\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);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/418555.html
標籤:
