2016-04-26 6 views
0

OS X Yosemite 10.10.5 XCode 7,2Правильное манипулирование широким полукокса/строки в C

Я читал и экспериментировать целый день, о широком символ/строка в C, и я до сих пор не могу сделать он работает.

Я пытаюсь прочитать файл, состоящий только широкими символами, такие как следующие:

んわらやま (Japanese) 

Я хочу прочитать только один символ в момент, чтобы писать непосредственно внутри другого файла.

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 
    } 
} 

Вот результат:

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

Я понимаю, что моя проблема, вероятно, о том, как я читать данные, но если я думаю об альтернативах я полностью застрял.

  • Я попытался с помощью fgetws, но я не в состоянии отделить символы один от другого;
  • Я пробовал использовать fwscanf с % ls, но я просто закончил с пустым файлом;
  • я заметил, что MAC OS не обеспечивает fgetwc реализации даже если относительный человек страница упоминает о нем, AFAIK getwc должен быть макрос для реализации fgetwc;
  • Не уверен, что это важно, но я создал исходный файл, используя touch command;

Вы можете мне помочь?

PS: Ссылки на дальнейшие чтения по аргументу также очень ценятся. Документация по этому вопросу довольно скудна.


XCode вопрос

Этот вопрос изначально заставил меня думать, что Джонатан Леффлера решение не работает. Фактически код производит различный выход, если я запускаю его через XCode CMD + R или через Терминал.

AFAIK вопроса должен быть каким-то атрибут/свойство/установка XCode использует во время выполнения, так как жесткое кодирование источника и точки назначения параметров до сих пор производят неправильный вывод.

Ради ясности я обеспечиваю экспортированный схему для моего кода:

<?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> 

ответ

3

Этот код, кажется, работает.Вероятно, вы не должны использовать fputs() и узкие строки; вы должны использовать fputws() и широкие строки: L"- ". Обратите внимание на использование setlocale(); это важно (попробуйте исключить его и посмотреть, что вы получите).

#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); 
    } 
} 

Учитывая файл, data, содержащий:

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

(. Вам не придется odx, потому что я написал, но xxd -g 1 data производит более или менее эквивалентный выход) Я запускал программу (так называемый x37), как это:

$ 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: 
$ 

Тестирование на Mac OS X 10.11.4 с GCC (5.3.0, самодельного) и Clang (Apple LLVM версии 7.3.0 (с Ланг-703.0.29)).

С учетом рабочего кода вы можете поэкспериментировать, чтобы определить, какие изменения имеют решающее значение. Я также создавал функции для сообщения ошибок с однострочными вызовами вместо необходимости писать 3 или 4 строки за ошибку. (Фактически «использование» более подходит, чем «создать» - я давно создал такой набор функций и постоянно их использую.)

+0

Проблема с кодом решена, но я также обнаружил ** проблему UNSOLVED **. Я обновил вопрос – Paul