Click here to Skip to main content
15,390,456 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello.

If I want to update some software for my uncle's old saw mill machine that has a programmable controller with C, and I want to code it in C or C++98 or in C++03, nothing newer, then how do make the following work for that?

I am doing a test on an old Windows XP Pro 32 bit system with every (at the time of installation) code page installed, and with CodeBlocks 17.12 and GCC of 5.1 . I think that I should be able to code it for the older system with this. It changes the file name.

If I can do it all in C then that is OK.

I prefer to do this in C, but if 98 or 03 works that is OK also.

What I have tried:

/// This works but it creates a file that 
/// has the name                            A_Unicode天file.txt
/// but does Not have the desired name of   A_Unicode天file.txt.

    std::string M23;
    M23 = "Hello World 101010100011101010010101010011010100101101010101\n\n\n\nQWERTYUIOP";



    string nameFile = "A_Unicode天file.txt";

    ofstream out;

    out.open(nameFile.c_str(), ios::out);

    out.write(M23.c_str(), M23.length());
    out.close();
Posted
Updated 25-Jun-22 11:35am

I can't get the code sample to compile without further tricks. The compiler points out that you need a special code page for the special (chinese?) character.
C++
// warning C4566 : The character represented by the universal character name "\u5929" cannot be represented in the current code page(1252).
string nameFile = "A_Unicode天file.txt";

In a current Windows one should use UNICODE anyway, so that it interprets all characters correctly if possible world-wide. If you use wstring instead of string under C++ this would already help. The strange current file name can be processed without problems and the file is created correctly under Win10. Which Windows version you use probably doesn't matter for this problem as long as UNICODE is supported. For access to hardware, however, a suitable driver would be necessary.

I suggest to change all needet texts to UNICODE to solve this Task.
C++
wstring nameFile = TEXT("A_Unicode天file.txt");

ofstream out;

out.open(nameFile.c_str(), ios::out);


//EDIT1:
Although this is how it worked for me, it might make sense to use wfstream or wofstream instead of ofstream.

//EDIT2:
Codeblocks 17.12 uses TDM-GCC v5.1.0  (see info on their site)

I have tested the TDM-GCC-64 under Windows 10. The version results:
g++ -v
gcc version 9.2.0 (tdm64-1)

Without the UNICODE defines:
#define _UNICODE
#define UNICODE

I got several errors compiling with "g++ -std=c++03 demo.cpp  -o demo"

After UNICODE was defined the TEXT() macro worked and the program could be compiled and created the desired file.

Using wfstream or wofstream brings additional problems with gcc:

   58 |     out.write(M23.c_str(), M23.length());
      |               ~~~~~~~~~^~
      |                        |
      |                        const char*

By definition, write expects this:
basic_ostream& std::basic_ostream::write (const char_type* s, streamsize n);


Instead of write it would be better to write the output as a stream:
C++
wstring  M23(TEXT("Hello World 101010100011101010010101010011010100101101010101\n\n\n\nQWERTYUIOP"));
wstring  nameFile(TEXT("A_Unicode天file.txt"));
wfstream out;

out.open(nameFile.c_str(), ios::out);

out << M23.c_str() << "\n";

out.close();
-----------

If your compiler can't handle UNICODE, you might have to use a window specific solution with system calls. I would avoid this and rather use compilers which support  UNICODE. 

Install CodeBlocks with TDM-GCC or download the TDM-GCC here:
https://sourceforge.net/projects/tdm-gcc/
https://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/

----------
I also found this comment:
"ofstream is not very cooperative (refuses to take wstring parameters), and wofstream supposedly needs to know locale and encoding settings." 
https://stackoverflow.com/questions/4053918/how-to-portably-write-stdwstring-to-file
   
v10
Comments
Member 15078716 24-Jun-22 18:43pm
   
Thank you.

I get the following:

wstring nameFile = TEXT("A_Unicode天file.txt");

ofstream out;

out.open(nameFile.c_str(), ios::out);

/*main.cpp|error: no matching function for call to
'std::basic_ofstream<char>::open(const wchar_t*, const openmode&)'|*/

out.write(M23.c_str(), M23.length());

out.close();


Getting closer. Thank you.
merano99 24-Jun-22 18:59pm
   
What flags are you using? For gcc -std=c++03 ? It may be that additional effort is necessary for older versions.
Member 15078716 24-Jun-22 19:21pm
   
When I use -std=c++98 a file (c++0x_warning.h) opens up and the following is highlighted :

#if __cplusplus < 201103L
#error This file requires compiler and library support for the \
ISO C++ 2011 standard. This support is currently experimental, and must be \
enabled with the -std=c++11 or -std=gnu++11 compiler options.
#endif

__________


When I use -std=c++11 , or -std=c++14 , or -std=c++0x (aka C++11) , or -std=c++1z (aka C++17) I get the following which shows up in the compiler messages :

error: no matching function for call to 'std::basic_ofstream<char>::open(const wchar_t*, const openmode&)'|

__________


I am doing a lot of testing and I have the following at the beginning of my code which I think might have covered the code that I am now testing. If it does not, then please advise me of what does.


#define _UNICODE
#define UNICODE

#include <string>
#include <iostream>
#include <windows.h>

#include <locale>
#include <string>
#include <codecvt>
#include <fstream>

#include <cerrno> // For reading and writing to files using C++ streams. https://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html

#pragma comment(lib, "wininet.lib")
#include <winsock.h>
#include <winsock2.h>
#include <wininet.h>

#include <time.h>

#include <wchar.h>

#include <stdio.h>
#include <stdlib.h>

#include <cwchar>

#include <stddef.h>

#include <bitset>

#include <cstddef>
#include <cstring>

#include <algorithm> // For std::transform

#include <sstream>
#include <string>
#include <cstdint>



// Windows API only, pre C++11 implementation.

#include <stdexcept>
#include <vector>

using std::runtime_error;
using std::string;
using std::vector;
using std::wstring;


using namespace std;

// https://stackoverflow.com/questions/56843413/stdbyte-is-not-member-of-std
// "It is undefined behavior to add declarations or definitions to namespace std or to any namespace nested within std, with a few exceptions ..."
// This is "only a workaround not a good solution".

namespace std {
enum class byte : unsigned char {};
};


__________

Thank you for your help.
Randor 24-Jun-22 19:21pm
   
You probably meant to recommend std::wofstream
Member 15078716 24-Jun-22 19:24pm
   
I have now tried

std::wofstream out;
//ofstream out;

I get the same error messages.

__________

I tried putting the file name in directly, as thus

//out.open(nameFile.c_str(), ios::out);
out.open(TEXT("A_Unicode天file.txt"), ios::out);

but that gave the same error messages.

__________

I tried adding the following to the compiler flags

-std=gnu++11

but that gave the same error messages.


Thank you.
Randor 24-Jun-22 19:30pm
   
That's not possible. std::wofstream cannot throw a std::basic_ofstream<char> error if you are passing a wstring filename.
Member 15078716 24-Jun-22 19:42pm
   
With either

out.open(TEXT("A_Unicode天file.txt"), ios::out);
or
out.open(L"A_Unicode天file.txt", ios::out);

I get:

error: no matching function for call to 'std::basic_ofstream<wchar_t>::open(const wchar_t [19], const openmode&)'|

Can this be done in a windows batch file (*.bat) and if so then I can try to run that from my program.

I can type in the file name with the Unicode symbol in it directly. So, it is (seems) logical that I should be able to do that with C or up to C++03 code. Windows 2000 used Unicode. Way back in Visual Studio 6 Unicode was used. It has to be there. C or up to 03 should be able to make it work.

How?

__________

What if I convert the file name to binay and then save the file with a name that is being sent as binary. I do not know how to do that, but it is an idea for a workaround.

?

__________

Maybe I should be sending a wstring instead of a const wchar_t* . Would someone tell me how to convert from a const wchar_t* to a wstring? I looked it up did not find a way (yet).

Thanks.
merano99 24-Jun-22 20:46pm
   
In a wstring object, the string is stored as wchar_t*, so you can assign it, or specify it directly at creation.
wchar_t* test1 = TEXT("Test");
wstring test2(test1);
Which compiler and version do you use exactly?
Member 15078716 24-Jun-22 22:04pm
   
Code::Blocks 17.12
Build: December 2017
File Version: 17.12.0.0
C compiler: mingw32-gcc.exe
C++ compiler: mingw32-g++.exe

__________

I have now tried:

wchar_t* test1 = TEXT("A_Unicode天file.txt");
wstring test2(test1);
out.open(test2, ios::out);

I get:

error: no matching function for call to 'std::basic_ofstream<wchar_t>::open(std::__cxx11::wstring&, const openmode&)'|
merano99 25-Jun-22 5:16am
   
updated my solution
The questioner had stated that he uses Code:Blocks with MinGW under Windows.
MinGW seems to have problems with UNICODE, other compilers like Visual-Studio or TDM-GCC realize at least under Windows with wchar_t. The C++ standard does not seem to guarantee this, probably because not sure that all file systems support it. But since we are looking for a solution for Windows, there is the possibility to use a compiler that supports it, or alternatively to use Windows system calls. I have already offered a solution via wchar_t, here now the alternative via system calls.

Opening a File for Reading or Writing
https://docs.microsoft.com/en-us/windows/win32/fileio/opening-a-file-for-reading-or-writing

Under Windows the system calls CreateFile() and WriteFile exist in the A as well as in the W version.
If UNICODE is defined, the W version is used automatically. To make the program independent of char and wchar_t
one can use the data type TCHAR. If UNICODE was defined the TCHAR becomes wchar_t.

Example:
C
TCHAR *fname=TEXT("A_Unicode天file.txt");
HANDLE hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);             
BOOL bErr = WriteFile( hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);

Annotation:
There is a slightly older article that discusses the problem:

How to open an std::fstream (ofstream or ifstream) with a unicode filename?
https://stackoverflow.com/questions/821873/how-to-open-an-stdfstream-ofstream-or-ifstream-with-a-unicode-filename
   
Comments
Member 15078716 25-Jun-22 23:57pm
   
Ok I added the following :

wstring write_stuff = L"I am Happy";
DWORD dwBytesWritten = 0;

TCHAR *fname=TEXT("A_Unicode_WriteSTuff_天_file.txt");
HANDLE hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//BOOL bErr = WriteFile( hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);
BOOL bErr = WriteFile( hFile, (LPCVOID)&write_stuff[0], sizeof(wchar_t)*write_stuff.size(), &dwBytesWritten, nullptr);


In winbase.h I found "#define CreateFile CreateFileW" so, I do not have to write "W". I guess that makes it work for wide and non-wide both.

I put in GENERIC_READ | GENERIC_WRITE because I want to read it later.

I put in CREATE_ALWAYS because I want to edit the file later. I plan to read it into a wstring, or a const wchar_t*, or a wchar_t ...[], then edit what I read, then overwrite the file with the result.

It gave me a new file A_Unicode_WriteSTuff_天_file.txt which is part of what I wanted: Unicode in the file name. You made it work and in C. Thank you. You explained for the world to see what I am struggling with in using CodeBlocks, which I like a lot. Thank you.

But,

Opening the file with Microsoft Wordpad I get the text "I a m H a p p y " .

Opening the file with Apache OpenOffice 4.1.2 I get the text "I# #a#m# #H#a#p#p#y#" .

Opening the file with Microsoft Word (2000) I get a message box with the following:
The document name or path is not valid.
Try one or more of the following:
* Check the path to make sure it was typed correctly,
* On the File menu, cick Open, Search for the file using this dialog box.
("...A_Unicode_WriteSTuff_?_file.txt")

Opening the file with FireFox (a web browser) I get the text "I a m H a p p y " . (not exactly but similar)

Question: Is this an indication that something is wrong with how the text is being sent to it?
merano99 26-Jun-22 3:39am
   
I'm glad that there is now a solution as requested. Congratulations on the success!

Be careful when using C++ Datatypes with System-Calls.
//BOOL bErr = WriteFile(hFile, (LPCVOID)&write_stuff[0], sizeof(wchar_t)*write_stuff.size(), &dwBytesWritten, nullptr);
BOOL bErr = WriteFile(hFile, (LPCVOID)write_stuff.c_str(), write_stuff.size()*sizeof(TCHAR), &dwBytesWritten, NULL);


I didn't take care of the file format myself. When I got the special character pasted by copy and paste, the Visual Studio code editor changed the file format to include special characters can be saved.
It's not a good idea to edit code with a text editor like Wordpad, though the code that initially looks correct can contain invisible special characters that subsequently disrupt the compiler.
I edit source texts preferably with the associated development environment (IDE) or with Textpad or Notepad++. Textpad notices that special characters are included and offers to "convert" them, the special characters are then either gone or changed. Notepad++ seems to interpret and preserve the special characters correctly.
Windows tries to associate the file format with the extension. If you have an unfavorable or wrong link here, there will be problems. The problem arises here because a source file does not have a header in which the format is clearly defined. In contrast to graphics files, an editor then has to guess the format or rely on the extension. I've been wondering if there's anything wrong with that. It just grew that way historically and is no longer easy to change.
I took a closer look at the file format chosen by my IDE for the demo.cpp. The source text with special characters was encoded in UTF-8.

Please rate the (both?) solutions mark as solution. For further questions better open a new topic.
Randor 26-Jun-22 4:23am
   
You can write a BOM (byte order mark) at the beginning of the file. This will tell Notepad and other text editors about the Unicode text encoding. This should allow your text file to be displayed properly in various text editors.

https://docs.microsoft.com/en-us/globalization/encoding/byte-order-mark
merano99 26-Jun-22 5:47am
   
Thanks for the hint. With some programs you can switch on the writing of the BOM under options. In fact, e.g. Chinese characters are sometimes still not displayed correctly. Notepad++ and Firefox understand it and even my Visual Studio has no problem with the UTF-8 BOM.
Member 15078716 27-Jun-22 20:11pm
   
I have a further question. It is at
https://www.codeproject.com/Questions/5336001/Include-a-BOM-byte-order-mark-utf-8-the-saved-text

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900