简体   繁体   中英

swprintf and fwprintf and %c format

What has happened to wide char printf single characters? VS10 & MCBS:

#include<stdio.h>
#include <windows.h>
int const maxPathFolder = MAX_PATH - 3;
wchar_t const *delims = L"T";
wchar_t *testString = L"Codepage is: ";
int main()
{
FILE *stream = NULL;

    UINT CP = GetConsoleOutputCP();
    wchar_t *testName= (wchar_t *)calloc(maxPathFolder, sizeof(wchar_t));
    wcscat_s(testName, maxPathFolder, L"C:\\printemp.txt");
    stream = _wfopen(testName, L"w");

    if (fwprintf(stream, L"%s%i%c", testString, CP, delims) == EOF) wprintf(L"Problems writing to File.");
    fclose (stream);
    swprintf (testName, L"%s%i%c", testString, CP, delims);
    free (testName);
}

The output in printemp.txt is Codepage is: 850? and the delims variable in swprintf'd testName is the Han character 坠 . According to Igor's comments in this post , wide streams looked a little broken.

The aim ultimately is to output to file arrays of wide char to file separated by a delimiter. Some way around it?

Code page is outdated for the most part, Unicode replaces it. The problem here is the same as before, trying to open Unicode file in Text/ANSI mode.

Since you have tagged this as c++ you can just use Standard Library, std::wstring and std::wfstream , avoiding the headache of c-string allocation.

#include <iostream>
#include <fstream>
#include <string>
#include <io.h> //for _setmode
#include <fcntl.h> //for _O_U16TEXT

int main()
{
    //optional: for non-local languages on console
    _setmode(_fileno(stdout), _O_U16TEXT);

    //write to file (overwrite old file if any)
    wchar_t wbuf[128];
    std::wofstream fout(L"path.txt", std::ios::binary);
    if (fout) 
    {
        fout.rdbuf()->pubsetbuf(wbuf, 128);
        fout << L"ελληνικά\n";
        fout << L"English\n";
        fout << 123 << "\n";
        fout.close();
    }

    std::wifstream fin(L"path.txt", std::ios::binary);
    if (fin) 
    {
        fin.rdbuf()->pubsetbuf(wbuf, 128);
        std::wstring wstr;
        while (getline(fin, wstr, L'\n')) std::wcout << wstr << L"\n";
        fin.close();
    }

    return 0;
}

To be compatible with other software like Notepad you have to add byte order mark at beginning of the file:

fout << L"\xFEFF";

Then skip the first character (first 2 bytes) when reading the file.

If std::wstring is not an option then use new / delete operator instead of malloc .

wchar_t *testName = new wchar_t[MAX_PATH];
...
delete[] testName;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM