VS2005中sprintf函数结果不正确
下面的代码:/*------------------------------------------
RANDRECT.C -- Displays Random Rectangles
(c) Charles Petzold, 1998
------------------------------------------*/
#include <windows.h>
#include <stdlib.h> // for the rand function
#include <stdio.h>
#include <time.h>
HDC hdc;
long int times;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void DrawRectangle (HWND) ;
int cxClient, cyClient ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("RandRect") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName= NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Random Rectangles"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (TRUE)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
else
DrawRectangle (hwnd) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
char strTimes = { 0 };
static time_t starTime, endTime;
switch (iMsg)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
starTime = time(NULL);
return 0;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_CLOSE:
endTime = time(NULL);
sprintf(strTimes, "用时 = %d 秒\n矩形数 = %d\n", endTime - starTime, times);
MessageBox(hwnd, strTimes, "结果", MB_OK | MB_ICONINFORMATION);
ReleaseDC (hwnd, hdc);
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
void DrawRectangle (HWND hwnd)
{
HBRUSH hBrush ;
//HDC hdc ;
RECT rect ;
if (cxClient == 0 || cyClient == 0)
return ;
SetRect (&rect, rand () % cxClient, rand () % cyClient,
rand () % cxClient, rand () % cyClient) ;
hBrush = CreateSolidBrush (
RGB (rand () % 256, rand () % 256, rand () % 256)) ;
//hdc = GetDC (hwnd) ;
FillRect (hdc, &rect, hBrush) ;
//ReleaseDC (hwnd, hdc) ;
DeleteObject (hBrush) ;
times++;
Sleep(1);
}
以上代码中 sprintf函数调用中的times, 用VS2005编译, 结果总是为0,但是用VC6编译能得以正确结果(生成的矩形数), 问题出的哪里? 在您的代码中,问题的根源在于 `sprintf` 函数用于格式化字符串时,参数类型不匹配。在C语言中,`sprintf` 函数对于 `"%d"` 需要一个 `int` 类型的参数。然而,`times` 是 `long int` 类型(通常是 64 位),而 `time_t` 类型也是平台相关的。因此,您需要确保正确使用的格式化符号以匹配这些类型。
通过确保 `sprintf` 使用正确的格式化字符串可以解决此问题:
1. 将 `sprintf` 函数的格式化字符串更改为匹配 `long int` 类型。
2. 使用 `"%ld"` 来格式化 `long int` 类型的数据。
以下是修正后的代码:
char strTimes = { 0 }; // 确保有足够空间存储结果字符串
static time_t starTime, endTime;
...
case WM_CLOSE:
endTime = time(NULL);
sprintf(strTimes, "用时 = %ld 秒\n矩形数 = %ld\n", (long)(endTime - starTime), times);
MessageBox(hwnd, strTimes, "结果", MB_OK | MB_ICONINFORMATION);
ReleaseDC (hwnd, hdc);
DestroyWindow(hwnd);
return 0;
这样调整后,`sprintf` 函数应该会正确地输出 `times` 的值。
另外,要确保字符串缓冲区 `strTimes` 的大小是足够的,以便能够存储格式化后的字符串。此处我将其设定为 100 字符长度,只是为了确保足够空间以避免缓冲区溢出问题,您可以根据实际需要调整。
如果还有其他问题,请告诉我!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 但是我把times 定义为int输出时使用 %d ,结果还是为0;
同样的把times定义为long long int, 输出时使用 %lld, 结果仍然是0;
以上情况出现在VSS2005中, VC6能得出正确结果. 七彩云南 发表于 2025-01-23 17:16
但是我把times 定义为int输出时使用 %d ,结果还是为 ...
这个问题可能与 `sprintf` 在不同编译器版本中的实现或编译器设置有关。在Visual Studio 2005中,新的C运行库可能会引入一些行为上的差异。以下是一些建议的排查和修复步骤:
1. **确保时间计算的正确性**:由于您提到 `times` 总是为0,请确保在代码中 `times` 变量实际被增量。仔细检查相关逻辑,比如在 `DrawRectangle` 中增加 `times++` 代码。
2. **字符串缓冲区问题**:确保 `strTimes` 的大小足够大,以包含格式化后的结果。此缓冲区需要能够容纳最长的字符串。设定一个合理的缓冲区大小,如:
char strTimes;
3. **调试输出**:在 `WM_CLOSE` 之前,输出或打断点检查 `times` 的值,以确保在 sprintf 之前它是正确的。例如,您可以在调试模式下通过直接输出到控制台或通过其他方法来检查 `times` 的值。
4. **调用 _set_SSE2_enable(0)**:在一些特定旧系统上,问题可能与浮点运算相关,可以尝试调用 `_set_SSE2_enable(0)`。但大多数情况下这与您的问题无关。
5. **Visual Studio 设置**:检查编译器设置,确保没有设置特定选项从而导致对 `sprintf` 行为的影响。
以下是一些调试代码的例子:
#include <stdio.h>
// 在 WM_CLOSE 之前打印 times
fprintf(stdout, "times = %d\n", times);
// 或者在调试器中设置断点查看 times 的值
如果问题仍然存在,请逐步验证每一步以找到根源。确保没有遗漏初始化或者条件竞争等潜在错误。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 使用局部静态变量
将 times 定义为局部静态变量,而不是全局变量。这样可以确保 times 的值在函数调用之间保持不变。
修改代码如下:
void DrawRectangle(HWND hwnd)
{
static long int times = 0;// 定义为局部静态变量
HBRUSH hBrush;
RECT rect;
if (cxClient == 0 || cyClient == 0)
return;
SetRect(&rect, rand() % cxClient, rand() % cyClient,
rand() % cxClient, rand() % cyClient);
hBrush = CreateSolidBrush(
RGB(rand() % 256, rand() % 256, rand() % 256));
FillRect(hdc, &rect, hBrush);
DeleteObject(hBrush);
times++;
Sleep(1);
}
然后在 WM_CLOSE 消息中,将 times 的值传递给 MessageBox:
case WM_CLOSE:
endTime = time(NULL);
sprintf(strTimes, "用时 = %d 秒\n矩形数 = %d\n", endTime - starTime, times);
MessageBox(hwnd, strTimes, "结果", MB_OK | MB_ICONINFORMATION);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
return 0; 很cool的阳 发表于 2025-1-23 17:20
怎么把DrawRectangle函数里的静态变量传给WinMain中的sprintf呢? 我用:
sprintf(strTimes, "矩形数: %d\n", times);
替换
sprintf(strTimes, "用时 = %d 秒\n矩形数 = %d\n", endTime - starTime, times);
即只传 times 一个变量给 sprintf函数时, 可以正确输出 times 的值, 但传2 个变量时times 的值总是0. 七彩云南 发表于 2025-1-23 17:40
怎么把DrawRectangle函数里的静态变量传给WinMain中的sprintf呢?
#include <windows.h>
#include <stdio.h>
// DrawRectangle 函数
int DrawRectangle() {
static int staticVar = 0; // 静态变量
return staticVar++; // 返回静态变量的值并自增
}
// WinMain 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
int value = DrawRectangle(); // 获取 DrawRectangle 函数的返回值
char buffer;
sprintf(buffer, "Static Variable Value: %d", value); // 使用返回值
MessageBox(NULL, buffer, "Message", MB_OK);
return 0;
} 真见鬼了.
把两个参数交换下位置, 先输出矩形数, 后输出时间
即把sprintf改为:
sprintf(strTimes, "矩形数 = %d \n时间 = %d 秒\n", times, endTime - starTime);
可以得到正确输出. 增加一个中间变量保存 endTime - starTime, 用于保存时间变量的值, 再把这个变量作为sprintf参数:
即:
int shijian;
shijian = endTime - starTime;
sprintf(strTimes, "时间 : %d 秒\n矩形数 : %d\n", shijian, times)
可以正确输出.
另:GCC11.4.0上没有这个问题, 可以正确执行并正确输出.
页:
[1]