2016-04-26 9 views
0

OS X Yosemite 10.10.5 XCode 7.2Proper Manipulation von breiten Zeichen/Zeichenfolge in C

Ich habe gelesen, und den ganzen Tag lang zu experimentieren, über breite Zeichen/Zeichenfolge in C und ich kann immer noch nicht machen es funktioniert.

Ich versuche, eine Datei nur durch breite Zeichen wie die Anhängerzusammengesetzt zu lesen:

んわらやま (Japanese) 

Ich mag nur jeweils ein Zeichen der Zeit lesen, in der anderen Datei schreiben sofort. Hier

int main(int argc, const char * argv[]) 
{ 
    FILE *source, *dest; 

    source = fopen(argv[1], "r"); 
    if (source == NULL) { 
     printf ("could not open source file \n"); 
     exit (1); 
    } 

// if [dest] does not exist it is created 
    dest = fopen(argv[2], "w+"); 
    if (dest == NULL) { 
     fclose(source); 

     printf ("could not open dest file \n"); 
     exit (1); 
    } 
    fwide(source, 1); 
    fwide(dest, 1); 

    fileManipulator(source, dest); 

    fclose(source); 
    fclose(dest); 

    return 0; 
    } 

void fileManipulator(FILE* source, FILE* dest) 
{ 
    wint_t token; 

    while (WEOF != (token = getwc(source))) { 
     manipulateToken(token, dest); 
    } 
} 


void manipulateToken(wint_t token, FILE* dest) 
{ 
    char* pre = "- "; 
    char* post= " -\n"; 

    if (EOF == fputs(pre, dest)) 
    { 
//  error handling 
    } 
    if (WEOF == fputwc(token, dest)) 
    { 
//  error handling 
    } 
    if (EOF == fputs(post, dest)) 
    { 
//  error handling 
    } 
} 

ist die Ausgabe:

- „ - 
- Ç - 
- ì - 
- „ - 
- Ç - 
- è - 
- „ - 
- Ç - 
- â - 
- „ - 
- Ç - 
- Ñ - 
- „ - 
- Å - 
- æ - 

Ich kann verstehen, dass mein Problem wahrscheinlich darüber, wie ich die Daten lesen, aber wenn ich über Alternativen denken, bin ich total fest.

  • Ich habe versucht mit fgetws aber ich bin nicht in der Lage Zeichen zu trennen voneinander;
  • Ich habe versucht mit fwscanf mit % ls, aber ich endete gerade mit einer leeren Datei;
  • Ich bemerkte, dass MAC OS nicht fgetwc Implementierung sogar Seite, wenn die relative Mann bereitstellt erwähnt es, AFAIK getwc eine Makro-Implementierung für fgetwc sein sollte;
  • Nicht sicher, ob dies wichtig ist, aber ich erstellte Quelldatei mit Touch Befehl;

können Sie mir helfen?

PS: Links zu weiteren Lesungen des Arguments werden ebenfalls sehr geschätzt. Die Dokumentation ist ziemlich knapp.


Die XCode Ausgabe

Dieses Problem hat mich zunächst denken, dass Jonathan Leffler Lösung nicht funktioniert wurde. Tatsächlich erzeugt der Code einen anderen Ausgang, wenn ich ihn über XCode CMD + R oder über den Terminal durchführe.

AFAIK die Ausgabe muss eine Art von Attribut/Eigenschaft sein/XCode Einstellung zur Laufzeit verwendet, da Hartcodierung Quelle und dest Parameter noch die falsche Ausgabe erzeugt.

Aus Gründen der Klarheit Ich bin für meinen Code des exportierte Schema bereitstellt:

<?xml version="1.0" encoding="UTF-8"?> 
<Scheme 
    LastUpgradeVersion = "0720" 
    version = "1.3"> 
    <BuildAction 
     parallelizeBuildables = "YES" 
     buildImplicitDependencies = "YES"> 
     <BuildActionEntries> 
     <BuildActionEntry 
      buildForTesting = "YES" 
      buildForRunning = "YES" 
      buildForProfiling = "YES" 
      buildForArchiving = "YES" 
      buildForAnalyzing = "YES"> 
      <BuildableReference 
       BuildableIdentifier = "primary" 
       BlueprintIdentifier = "DA36663A1CCF4F8200615958" 
       BuildableName = "FileManipulator" 
       BlueprintName = "FileManipulator" 
       ReferencedContainer = "container:FileManipulator.xcodeproj"> 
      </BuildableReference> 
     </BuildActionEntry> 
     </BuildActionEntries> 
    </BuildAction> 
    <TestAction 
     buildConfiguration = "Debug" 
     selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 
     selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 
     shouldUseLaunchSchemeArgsEnv = "YES"> 
     <Testables> 
     </Testables> 
     <MacroExpansion> 
     <BuildableReference 
      BuildableIdentifier = "primary" 
      BlueprintIdentifier = "DA36663A1CCF4F8200615958" 
      BuildableName = "FileManipulator" 
      BlueprintName = "FileManipulator" 
      ReferencedContainer = "container:FileManipulator.xcodeproj"> 
     </BuildableReference> 
     </MacroExpansion> 
     <AdditionalOptions> 
     </AdditionalOptions> 
    </TestAction> 
    <LaunchAction 
     buildConfiguration = "Debug" 
     selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 
     selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 
     launchStyle = "0" 
     useCustomWorkingDirectory = "NO" 
     ignoresPersistentStateOnLaunch = "NO" 
     debugDocumentVersioning = "YES" 
     enableAddressSanitizer = "YES" 
     debugServiceExtension = "internal" 
     allowLocationSimulation = "YES"> 
     <BuildableProductRunnable 
     runnableDebuggingMode = "0"> 
     <BuildableReference 
      BuildableIdentifier = "primary" 
      BlueprintIdentifier = "DA36663A1CCF4F8200615958" 
      BuildableName = "FileManipulator" 
      BlueprintName = "FileManipulator" 
      ReferencedContainer = "container:FileManipulator.xcodeproj"> 
     </BuildableReference> 
     </BuildableProductRunnable> 
     <CommandLineArguments> 
     <CommandLineArgument 
      argument = "/Users/Paul/TestDirectory/Source.txt" 
      isEnabled = "YES"> 
     </CommandLineArgument> 
     <CommandLineArgument 
      argument = "/Users/Paul/TestDirectory/Destination.txt" 
      isEnabled = "YES"> 
     </CommandLineArgument> 
     </CommandLineArguments> 
     <AdditionalOptions> 
     <AdditionalOption 
      key = "NSZombieEnabled" 
      value = "YES" 
      isEnabled = "YES"> 
     </AdditionalOption> 
     <AdditionalOption 
      key = "NSDOLoggingEnabled" 
      value = "YES" 
      isEnabled = "YES"> 
     </AdditionalOption> 
     </AdditionalOptions> 
    </LaunchAction> 
    <ProfileAction 
     buildConfiguration = "Release" 
     shouldUseLaunchSchemeArgsEnv = "YES" 
     savedToolIdentifier = "" 
     useCustomWorkingDirectory = "NO" 
     debugDocumentVersioning = "YES"> 
     <BuildableProductRunnable 
     runnableDebuggingMode = "0"> 
     <BuildableReference 
      BuildableIdentifier = "primary" 
      BlueprintIdentifier = "DA36663A1CCF4F8200615958" 
      BuildableName = "FileManipulator" 
      BlueprintName = "FileManipulator" 
      ReferencedContainer = "container:FileManipulator.xcodeproj"> 
     </BuildableReference> 
     </BuildableProductRunnable> 
    </ProfileAction> 
    <AnalyzeAction 
     buildConfiguration = "Debug"> 
    </AnalyzeAction> 
    <ArchiveAction 
     buildConfiguration = "Release" 
     revealArchiveInOrganizer = "YES"> 
    </ArchiveAction> 
</Scheme> 

Antwort

3

Dieser Code scheint zu funktionieren.Sie sollten wahrscheinlich und schmale Zeichenfolgen nicht verwenden; Sie sollten fputws() und breite Strings verwenden: L"- ". Beachten Sie die Verwendung von setlocale(); Das ist entscheidend (versuch es wegzulassen und zu sehen, was du bekommst).

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

static void fileManipulator(FILE *source, FILE *dest); 
static void manipulateToken(wint_t token, FILE *dest); 

int main(int argc, const char *argv[]) 
{ 
    FILE *source, *dest; 
    if (argc != 3) 
    { 
     fprintf(stderr, "Usage: %s input output\n", argv[0]); 
     exit(1); 
    } 

    setlocale(LC_ALL, ""); 

    source = fopen(argv[1], "r"); 
    if (source == NULL) 
    { 
     fprintf(stderr, "could not open source file %s\n", argv[1]); 
     exit(1); 
    } 

    dest = fopen(argv[2], "w+"); 
    if (dest == NULL) 
    { 
     fclose(source); 
     fprintf(stderr, "could not open dest file %s\n", argv[2]); 
     exit(1); 
    } 

    fwide(source, 1); 
    fwide(dest, 1); 

    fileManipulator(source, dest); 

    fclose(source); 
    fclose(dest); 

    return 0; 
} 

static void fileManipulator(FILE *source, FILE *dest) 
{ 
    wint_t token; 

    while (WEOF != (token = getwc(source))) 
    { 
     manipulateToken(token, dest); 
    } 
} 

static void manipulateToken(wint_t token, FILE *dest) 
{ 
    wchar_t *pre = L"- "; 
    wchar_t *post = L" -\n"; 

    if (EOF == fputws(pre, dest)) 
    { 
     fprintf(stderr, "Failed to write prefix string\n"); 
     exit(1); 
    } 
    if (WEOF == fputwc(token, dest)) 
    { 
     fprintf(stderr, "Failed to write wide character %d\n", (int)token); 
     exit(1); 
    } 
    if (EOF == fputws(post, dest)) 
    { 
     fprintf(stderr, "Failed to write suffix string\n"); 
     exit(1); 
    } 
} 

eine Datei gegeben, data, enthaltend:

$ cat data 
んわらやま 
$ odx data 
0x0000: E3 82 93 E3 82 8F E3 82 89 E3 82 84 E3 81 BE 0A ................ 
0x0010: 
$ 

(. Sie werden nicht odx, weil ich es geschrieben habe, aber xxd -g 1 data produziert mehr oder weniger gleichwertige Ausgabe) ich das Programm lief (genannt x37) wie folgt aus:

$ x37 data output 
$ cat output 
- ん - 
- わ - 
- ら - 
- や - 
- ま - 
- 
- 
$ odx output 
0x0000: 2D 20 E3 82 93 20 2D 0A 2D 20 E3 82 8F 20 2D 0A - ... -.- ... -. 
0x0010: 2D 20 E3 82 89 20 2D 0A 2D 20 E3 82 84 20 2D 0A - ... -.- ... -. 
0x0020: 2D 20 E3 81 BE 20 2D 0A 2D 20 0A 20 2D 0A   - ... -.- . -. 
0x002E: 
$ 

Testing auf Mac OS X 10.11.4 mit GCC (5.3.0, Eigenbau) und Clang (Apple-LLVM Version 7.3.0 (c lang-703.0.29)).

Mit Arbeitscode können Sie experimentieren, um herauszufinden, welche Änderungen entscheidend sind. Ich würde auch Funktionen erstellen, um Fehler mit einzeiligen Aufrufen zu melden, anstatt 3 oder 4 Zeilen pro Fehler schreiben zu müssen. (Eigentlich ist 'verwenden' passender als 'erstellen' - ich habe vor langer Zeit einen solchen Satz von Funktionen erstellt und benutze sie ständig.)

+0

Code-Problem gelöst, aber ich habe auch ein Problem mit ** UNSOLVED ** aufgezeigt. Ich habe die Frage aktualisiert – Paul