migf1 Δημοσ. 14 Φεβρουαρίου 2012 Μέλος Δημοσ. 14 Φεβρουαρίου 2012 Αφού πάει με τον compiler (βασικά με το runtime) και όχι με το λειτουργικό, πώς έχουμε εγγύηση ότι είναι ακριβώς 16 bits? Υποθέτω πως όλοι οι compilers όταν τρέχουν σε Windows μεταφράζουν το wchar_t σε 16-bits. Ο κώδικας δοκιμάστηκε από μένα τόσο με mingw-gcc 32bits σε XP/32bits και σε 7/64bits, όσο και με pelles-c 32bits σε XP/32bits, αλλά και με pelles-c 64bits σε 7/64bits. Δοκιμάστηκε επίσης από τον DirectX με Visual C++ και με Borland C++ σε XP (δεν ξέρω που αλλού τον δοκίμασε... ας μας πει αν διαβάζει το ποστ αυτό). Βγάζει πάντα το ίδιο αποτέλεσμα. Γενικά το point μου είναι πως χρησιμοποιώντας wchar_t απο εμπειρία μου πιστεύω ότι δημιουργείς περισσότερα προβλήματα απ' ότι λύνεις. Απλώς όταν είσαι αποκλειστικά σε VS και Windows τυχαίνει να δουλεύουν. Link που μόλις έκανα google και αναφέρεται στα θέματα που θίγω. Και ένα δεύτερο, που μάλλον είναι καλύτερο. (BTW σχετικά με το τελευταίο link στη FirstObject: αν δουλεύετε με XML έχουν ένα δωρεάν πρόγραμμα που για την τιμή του απλά τα σπάει). Το link που δίνεις στο StackOverflow γράφει all over the place πως στα Windows το wchar_t είναι 16bits από όλους όσους έχουν σχολιάσει/απαντήσει. Αν δεν πείθεσαι και θέλεις να το σταντάρεις 100% βάζεις το typedef που έγραψα πριν... >typedef wchar_t uint16_t; (θέλει unsigned νομίζω και όχι signed που έχω στο typedef του προηγούμενου post). Η όλη ιδέα του κώδικά μου είναι να αποφύγεις όλα αυτά τα προβλήματα που αναφέρει το link που παραθέτεις, καθώς επίσης και την (μη) αναγκαιότητα χρήσης του τρέχοντος locale, αλλά και της iconv. EDIT: Καλά, τα έχω σκοτώσει τα typedefs > #include <stdint.h> #define wchar_t uint16_t για να τελειώνει μια και καλή
defacer Δημοσ. 14 Φεβρουαρίου 2012 Δημοσ. 14 Φεβρουαρίου 2012 Το ψοφήσαμε λίγο το ζήτημα... Ας πούμε απλά πως είμαι off topic μιας και συγκεκριμένα αναφέρεσαι σε Windows.
migf1 Δημοσ. 14 Φεβρουαρίου 2012 Μέλος Δημοσ. 14 Φεβρουαρίου 2012 Το ψοφήσαμε λίγο το ζήτημα... Ας πούμε απλά πως είμαι off topic μιας και συγκεκριμένα αναφέρεσαι σε Windows. Ε ναι ρε συ, αφού είπαμε "wchar_t wrapper του Win32API"... δεν πήγε καν το μυαλό μου πως εννοούσες portability με άλλες πλατφόρμες.
Directx Δημοσ. 14 Φεβρουαρίου 2012 Δημοσ. 14 Φεβρουαρίου 2012 Αυτά ήθελα να αποφύγω ρε συ! Μέχρι στιγμής δεν το βλέπω να μπορώ Νομίζω πάντως πως δεν χρειάζεται να φτιάξεις ξεχωριστή κονσόλα για τα 1-2-3... μπορείς και στην στάνταρ, έτσι δεν είναι; Παρεμπιπτόντως, η παρακάτω ρουτίνα δείχνει να λύνει το θέμα του redirection στην έξοδο, αλλά δεν είναι code-page agnostic. Αντιθέτως, μετατρέπει τα πάντα στην τρέχουσα κωδικοσελίδα της κονσόλας... > DWORD w_print( const wchar_t *wtext ) { DWORD ret; /* # of bytes writetn */ DWORD outMode; /* current mode of stdout */ HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* get handle of stdout */ UINT outCP; /* console's output code-page*/ char *strout = NULL; /* mb string (ansi) to output*/ int lenstrout = 0; /* length of strout in chars */ /* is stdout a character file (console or LPT) with valid output mode? */ if( (GetFileType(hOut) & FILE_TYPE_CHAR) && GetConsoleMode(hOut, &outMode) ) { WriteConsoleW( hOut, wtext, wcslen(wtext), &ret, 0 ); } /* stdout is either disk or pipe, take redirection into account */ else { /* get console's output CP */ outCP = GetConsoleOutputCP(); /* get the length needed for converting wtext to mb strout */ lenstrout = WideCharToMultiByte(outCP, 0, wtext, -1, 0, 0, NULL, NULL); /* create the mb strout & convert wtext to strout */ strout = malloc(lenstrout * sizeof(char)); WideCharToMultiByte(outCP, 0, wtext, -1, strout, lenstrout, NULL,NULL); /* write the mb strout to hOut, without the nil-terminator char */ WriteFile( hOut, strout, lenstrout-1, &ret, NULL ); free( strout ); } /* Note: * WriteFile writes charCount-1 bytes to filter out the NULL terminator. */ return ret; } Αν και δεν έχω ασχοληθεί με το ζήτημα της εγγραφής UNICODE χαρακτήρων στην κοσνόλα, μου φαίνεται αρκετά λογικό όταν κάνεις redirection την έξοδο της σε αρχείο (που ουσιαστικά δεν είναι το αυτόματο κλασσικό redirection αλλά άμεσο μέσο WriteFile) να λαμβάνεις ως έξοδο στο αρχείο σου το περιεχόμενο του wchar_t που φυσικά δίχως το κατάλληλο BOM δεν είναι άμεσα αναγνώσιμο. Όταν τώρα γράφεις κανονικά στην έξοδο της κονσόλα μέσο του WriteConsoleW θεωρώ αρκετά πιθανό αυτό να κάνει το "τρικ" της μετατροπής για εσένα. Για παράδειγμα, ας υποθέσουμε ότι τροποποιώ το: >WriteFile( hOut, strout, lenstrout-1, &ret, NULL ); σε: >WriteFile(hOut, wtext, lstrlenW(wtext) * sizeof(wchar_t), &ret, NULL); Και ορίζω ως w_print(L"Ελληνικά!"); Αν .exe > out.txt λαμβάνω ως περιεχόμενο το: >9503 BB03 BB03 B703 BD03 B903 BA03 AC03 2100 Ε λ λ ή ν ι κ α ! Πράγμα λογικό. Όταν κάνεις redirection στην κονσόλα είναι λογικό να λαμβάνεις τα καθαρά περιεχόμενα του (η "μαγεία" της WriteConsoleW έχει χαθεί), τώρα αν ορίσεις στην αρχή του binary stream σου ένα "FFFE" που είναι το UNICODE BOM (που μας χρειάζεται) τότε το TYPE στην κονσόλα σου (για XP) θα λειτουργήσει σωστά (καθώς η κονσόλα πιάνει το BOM αυτόματα). Συνεπώς αν ορίσεις την έξοδο ως: >FFFE 9503 BB03 BB03 B703 BD03 B903 BA03 AC03 2100 Θα δεις το σωστό κείμενο (μέσο ενός απλού TYPE) στην κονσόλα και σε κάθε εφαρμογή που σέβεται το Unicode BOM (πχ. Notepad) και όλα αυτά ανεξαρτήτως CHCP. Θα μπορούσες δηλαδή να κάνεις κάτι σαν: > const unsigned char BOM[] = { 0xFF, 0xFE }; WriteFile(hOut, BOM, sizeof(BOM), &ret, NULL); WriteFile(hOut, wtext, lstrlenW(wtext) * sizeof(wchar_t), &ret, NULL); ώστε να συμπεριλαμβάνεις πάντα το ενδεδειγμένο BOM για την έξοδο σου (αρχείο σου). Υ.Γ. Για περισσότερα σχετικά με το BOM δες εδώ (διότι εξαρτάται άμεσα από το περιβάλλον εργασίας σου). --EDIT: Έχω τροποποιήσει και διορθώσει την αρχική μου ανάρτηση σε διάφορα σημεία για να είναι πιο ευανάγνωστη.
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Φίλε DirectX, είμαι πολύ κομμάτια τώρα για να διαβάσω διεξοδικά το τελευταίο σου post (δηλαδή να το διασταυρώσω με κώδικα, να ψάξω τεκμηρίωση συναρτήσεων, κλπ) έχω όμως την εντύπωση πως το redirection της κονσόλας γίνεται αυτόματα στην τρέχουσα κωδικοσελίδα της κονσόλας. Αλλά από default η κονσόλα δεν μπορεί να κάνει redirect unicode χαρακτήρες. Για να κάνει πρέπει να την ξεκινήσεις με /u... > cmd.exe /u Οπότε το πρόβλημα δεν είναι στο BOM (πάρα πολλοί editors είναι σε θέση να αναγνωρίζουν unicode αρχεία ανεξάρτητα με το αν υπάρχει ή όχι BOM στην αρχή του αρχείου). Το ερώτημα είναι αν υπάρχει στο Win32API ρουτίνα που να μεταφράζει αυτόματα τα (wchar_t *) σε (utf16le *) πριν τα γράψει. H WriteConsoleW() το κάνει αυτόματα, ενώ η WriteFile() όχι (και δεν υπάρχει WriteFileW() ή δεν τη βρήκα εγώ). Όλα αυτά με κάθε επιφύλαξη, μέχρι να βρω ευκαιρία να το ψάξω διεξοδικά (πιθανότατα αύριο).
Directx Δημοσ. 15 Φεβρουαρίου 2012 Δημοσ. 15 Φεβρουαρίου 2012 (επεξεργασμένο) Αυτα που σου έγραψα δουλεύουν στην κονσόλα των Windows XP SP3 μου, τώρα μένει να τα επιβεβαιώσεις και στον δικό σου υπολογιστή. --EDIT: Δεν χρειάζεσαι /U για αυτή την δουλειά (όσο γράφεις δικά σου δεδομένα σε μορφή raw-Unicode πάντα) καθώς το redirection σου γίνεται όπως προανέφερα από δικό σου κώδικα μέσο της WriteFile (η ύπαρξη της WriteFileW είναι περιττή και δεν υπάρχει) από εκεί και πέρα το μόνο που χρειάζεται είναι ο ορισμός του BOM στην έναρξη του αρχείου σου ώστε να βοηθήσεις την κονσόλα να αναγνωρίζει αυτόματα το περιεχόμενο του αρχείου σου και φυσικά όσους editors δεν μπορούν να πράξουν κάτι τέτοιο αυτόματα (και είναι αρκετοί διότι δεν αποθηκεύεις πχ σε UTF-8 αλλά σε raw Unicode οπότε δεν μπορούν να κρίνουν μόνοι τους άμεσα το Edianness). Δοκίμασε την τροποποίηση της ρουτίνας που σου ανάρτησα (πέταξε τα πάντα από το μπλοκ που ακολουθεί όταν ανιχνεύσεις "disk or pipe" και κράτα μόνο τα WriteFile όπως στα έδωσα) και δοκίμασε να κάνεις TYPE (ή να ανοίξεις μέσο πχ. Notepad) αυτό που θα προκείψει, κανονικά θα δεις ανεξαρτήτως CHCP το κείμενο σου (εγώ το τέσταρα με το string L"Ελληνικά!"). Ακολουθεί ένα βίντεο που παρουσιάζει τα λεγόμενα μου: http://www.youtube.com/watch?v=ITpzSDOvN6c (Το "Press any key to continue . . ." χάνεται διότι δεν αποθηκεύεται σε Unicode μορφή δηλαδή με 2 bytes κάθε γράμμα -διότι εκεί αναλαμβάνει η κονσόλα το redirection αντί του κώδικα σου οπότε ίσως πρέπει να ανακατευθύνεις όλο το input σε δικό σου buffer αλλάζοντας τα console Handlers βλ. GetStdHandler/SetStdHandler για να το μετατρέψεις σε Unicode αν σε ενδιαφέρει πλήρες redirection πάντα). Καλή συνέχεια!! Επεξ/σία 15 Φεβρουαρίου 2012 από Directx
migf1 Δημοσ. 15 Φεβρουαρίου 2012 Μέλος Δημοσ. 15 Φεβρουαρίου 2012 Αυτα που σου έγραψα δουλεύουν στην κονσόλα των Windows XP SP3 μου, τώρα μένει να τα επιβεβαιώσεις και στον δικό σου υπολογιστή. ... Δοκίμασε την τροποποίηση της ρουτίνας που σου ανάρτησα (πέταξε τα πάντα από το μπλοκ που ακολουθεί όταν ανιχνεύσεις "disk or pipe" και κράτα μόνο τα WriteFile όπως στα έδωσα) και δοκίμασε να κάνεις TYPE (ή να ανοίξεις μέσο πχ. Notepad) αυτό που θα προκείψει, κανονικά θα δεις ανεξαρτήτως CHCP το κείμενο σου (εγώ το τέσταρα με το string L"Ελληνικά!"). ... Καλή συνέχεια!! Εννοείται πως θα τα δοκιμάσω φίλε DirectX και σε ευχαριστώ! Το απογευματάκι μάλλον, γιατί τώρα παλεύω με κάτι... const pointers (θα ανοίξω ξεχωριστό νήμα).
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα