关于fwprintf(fp,L"%s\n",str_chs)的UNICODE问题

本文介绍了在Windows系统下,使用_wfopen()和fwprintf()函数将含有中文的字符串缓存写入指定路径文本文件时,需在调用fwprintf()前设置_wsetlocale(0,Lchs)以避免生成乱码或问号字符串。通过示例代码演示了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

from:

http://my.oschina.net/u/923534/blog/308477

在windows系统下将一个含有中文的字符串缓存写入指定路径下的文本文件中,假如采用_wfopen(),fwprintf()方式写入,务必在调用fwprintf()之前加上_wsetlocale(0, L"chs");这句,否则系统不支持,写出来的文本文件会是乱码或者问号字串。

 

示例代码如下:

 

FILE* fp = _wfopen(L"Data.txt",L"a+"); if(fp == NULL)
{
    return  false;
}
_wsetlocale(0,L"chs");//务必加上否则生成的文本是问号字符串 fwprintf(fp,L"%s\n",L"中文字符串写入文本"); fclose(fp);
 char  strline[1024] = {0}; fscanf(fp, "%[^\n]%*c", strline);//fscanf跨过空格读取整行的代码。格式化中使用了正则匹配

#include <windows.h> #include <stdio.h> #include <stdint.h> #include <mmsystem.h> #include <string.h> #include <stdlib.h> #include <time.h> #pragma comment(lib, "winmm.lib") #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib") #define UNICODE #define _UNICODE #define LOG_FILE L"vehicle_log.txt" // ------------------ 全局变量定义 ------------------ uint16_t current_vehicle_speed = 0; // 当前速度(km/h) uint8_t can_data[8] = {0}; // CAN 数据帧 uint64_t total_distance_mm = 0; // 累计行驶距离(mm) uint32_t last_update_time = 0; // 上次更新状态的时间戳(ms) const uint32_t delta_T = 20; // 目标刷新间隔(ms) const uint32_t can_update_period = 100; // CAN 信号更新间隔(ms) LARGE_INTEGER frequency, start_counter; // 高精度计时器 int is_paused = 0; // 暂停状态 // ------------------ 函数声明 ------------------ void ClearLogFile(const wchar_t* log_file); void WriteLog(uint32_t current_time, uint16_t speed); void GenerateCANMessage(uint16_t speed_msg, uint8_t frame[8]); uint16_t ReadCANMessage(uint8_t frame[8]); void UpdateVehicleState(uint32_t current_time); LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // ------------------ 清空日志文件 ------------------ void ClearLogFile(const wchar_t* log_file) { FILE* file = _wfopen(log_file, L"w"); total_distance_mm = 0; if (file) { fwprintf(file, L"Log initialized. Vehicle Logger started.\n"); fclose(file); } else { MessageBoxW(NULL, L"无法创建日志文件: vehicle_log.txt", L"错误", MB_ICONERROR); } } // ------------------ 写入日志 ------------------ void WriteLog(uint32_t current_time, uint16_t speed) { FILE* file = _wfopen(LOG_FILE, L"a"); if (!file) { MessageBoxW(NULL, L"日志文件写入失败: vehicle_log.txt", L"错误", MB_ICONERROR); return; } SYSTEMTIME st; GetLocalTime(&st); fwprintf(file, L"%02d:%02d:%02d.%03d - Speed: %d km/h, Total Distance: %llu mm\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, speed, total_distance_mm); fclose(file); } // ------------------ 生成 CAN 消息 ------------------ void GenerateCANMessage(uint16_t speed_msg, uint8_t frame[8]) { memset(frame, 0, 8); uint16_t mask = (1 << 13) - 1; uint16_t encoded_speed = speed_msg & mask; for (int i = 0; i < 13; i++) { uint16_t bit_pos = 16 + i; uint8_t byte_pos = bit_pos / 8; uint8_t bit_in_byte = 7 - (bit_pos % 8); if (encoded_speed & (1 << i)) { frame[byte_pos] |= (1 << bit_in_byte); } } } // ------------------ 读取 CAN 消息 ------------------ uint16_t ReadCANMessage(uint8_t frame[8]) { uint16_t speed = 0; for (int i = 0; i < 13; i++) { uint16_t bit_pos = 16 + i; uint8_t byte_pos = bit_pos / 8; uint8_t bit_in_byte = 7 - (bit_pos % 8); if (frame[byte_pos] & (1 << bit_in_byte)) { speed |= (1 << i); } } return speed; } // ------------------ 更新车辆状态 ------------------ void UpdateVehicleState(uint32_t current_time) { static uint32_t last_can_update_time = 0; static uint32_t last_log_time = 0; static int first_cycle_done = 0; if (is_paused) return; // 计算实际经过的时间(ms) uint32_t elapsed_ms = (last_update_time == 0) ? delta_T : (current_time - last_update_time); last_update_time = current_time; if (!first_cycle_done) { current_vehicle_speed = ReadCANMessage(can_data); WriteLog(current_time, current_vehicle_speed); first_cycle_done = 1; return; } // 更新CAN信号 if ((current_time - last_can_update_time) >= can_update_period) { uint16_t random_speed = rand() % 150; GenerateCANMessage(random_speed, can_data); current_vehicle_speed = random_speed; last_can_update_time = current_time; } // 正确的距离计算公式 total_distance_mm += (uint64_t)((double)current_vehicle_speed * elapsed_ms / 3.6); // 记录日志(每20ms) if ((current_time - last_log_time) >= delta_T) { WriteLog(current_time, current_vehicle_speed); last_log_time = current_time; } } // ------------------ 窗口处理函数 ------------------ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static uint32_t last_display_update_time = 0; switch (uMsg) { case WM_CREATE: { ClearLogFile(LOG_FILE); // 创建控件 CreateWindowW(L"BUTTON", L"Pause", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 20, 20, 120, 40, hwnd, (HMENU)1, NULL, NULL); CreateWindowW(L"STATIC", L"当前速度: 0 km/h\n总距离: 0 mm", WS_VISIBLE | WS_CHILD | SS_LEFT, 20, 80, 350, 100, hwnd, (HMENU)2, NULL, NULL); QueryPerformanceFrequency(&frequency); QueryPerformanceCounter(&start_counter); GenerateCANMessage(0, can_data); srand((unsigned int)time(NULL)); // 初始化随机数生成器 // 初始显示 wchar_t buffer[256]; swprintf(buffer, 256, L"当前速度: %d km/h\n总距离: %llu mm", current_vehicle_speed, total_distance_mm); SetWindowTextW(GetDlgItem(hwnd, 2), buffer); break; } case WM_COMMAND: { if (LOWORD(wParam) == 1) { is_paused = !is_paused; SetWindowTextW(GetDlgItem(hwnd, 1), is_paused ? L"Resume" : L"Pause"); } break; } case WM_USER + 1: { LARGE_INTEGER current_counter; QueryPerformanceCounter(&current_counter); // 计算自程序启动以来的毫秒数 uint32_t elapsed_ms = (uint32_t)((current_counter.QuadPart - start_counter.QuadPart) * 1000 / frequency.QuadPart); UpdateVehicleState(elapsed_ms); // 更新显示(每100ms) if (elapsed_ms - last_display_update_time >= 100) { wchar_t buffer[256]; swprintf(buffer, 256, L"当前速度: %d km/h\n总距离: %llu mm", current_vehicle_speed, total_distance_mm); SetWindowTextW(GetDlgItem(hwnd, 2), buffer); last_display_update_time = elapsed_ms; } PostMessageW(hwnd, WM_USER + 1, 0, 0); break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcW(hwnd, uMsg, wParam, lParam); } return 0; } // ------------------ 主程序 ------------------ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { // 确保正确注册窗口类 WNDCLASSW wc = {0}; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = L"VehicleLogger"; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.hCursor = LoadCursor(NULL, IDC_ARROW); if (!RegisterClassW(&wc)) { MessageBoxW(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR); return 0; } HWND hwnd = CreateWindowW( wc.lpszClassName, L"CAN信号记录器", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 600, 400, NULL, NULL, hInstance, NULL ); if (!hwnd) { MessageBoxW(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); PostMessageW(hwnd, WM_USER + 1, 0, 0); MSG msg; while (GetMessageW(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return (int)msg.wParam; } 累计距离计算逻辑有点问题
最新发布
08-08
### C语言读写TXT文件中的中文字符 在C语言中,处理包含中文字符的文本文件需要特别关注字符编码问题。通常情况下,UTF-8是最常用的多字节字符集之一。 当使用`fopen()`函数来打开文件时,在Windows系统中需要注意路径字符串中的反斜杠`\`会被解释为转义字符[^1]。因此建议使用双反斜杠`\\`或正斜杠`/`作为目录分隔符。 对于读取和写入带有特定编码(如UTF-8)的文本文件,可以采用以下方法: #### 写入带BOM头的UTF-8编码文件 为了确保其他程序能够识别该文件是以UTF-8格式保存的,可以在文件开头添加一个特殊的标记——Byte Order Mark (BOM),即三个字节序列EF BB BF。 ```c #include <stdio.h> int main() { char utf8_bom[] = {0xEF, 0xBB, 0xBF}; // UTF-8 BOM FILE* fp; fp = fopen("chinese_utf8.txt", "wb"); if (!fp) return -1; fwrite(utf8_bom, sizeof(char), 3, fp); fwrite("你好,世界。\n", sizeof(char), 7, fp); fclose(fp); } ``` 这段代码先向新创建的`.txt`文件写入了一个UTF-8 BOM签名,接着再追加一段含有汉字的内容。由于这里假设源码本身也是以UTF-8形式存储的,所以可以直接传递给`fwrite()`函数而无需额外转换。 #### 使用宽字符支持Unicode输入输出 另一种更通用的方式是利用标准库提供的宽字符功能,这允许直接操作各种类型的Unicode字符而不必担心底层的具体表示方式。不过这样做可能涉及到更多复杂的API调用以及平台特有的设置过程。 ```c #include <locale.h> #include <wchar.h> #include <fcntl.h> /* _O_U16TEXT */ #include <io.h> /* _setmode */ void set_output_encoding(void){ #ifdef _WIN32 _setmode(_fileno(stdout), _O_WTEXT); /* Windows needs this to output wide characters. */ #endif } int main(){ setlocale(LC_ALL,"chs"); wchar_t str[] = L"你好,中国!"; wprintf(L"%ls\n",str); FILE *fp; errno_t err; err = _wfopen_s(&fp,L"./output_wchar.txt",L"w,ccs=UTF-8"); if(err != 0 || !fp){ printf("File opening failed.\n"); return 1; } fwprintf(fp,L"%ls",str); fclose(fp); return 0; } ``` 此示例首先设置了本地化环境变量以便正确显示中文字符;其次通过指定`ccs=UTF-8`参数告知编译器所使用的字符编码规则;最后借助于`fwprintf()`完成实际的数据写出工作。 以上两种方案都可以有效地解决C语言下对含有多国文字尤其是亚洲地区特有符号的支持问题。具体选择哪一种取决于项目需求和个人偏好等因素。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值