Это далеко не идеальное и не самое правильное решение, просто демонстрация ещё одной возможности:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <getopt.h>
#include <iconv.h>
#define MAX_PATH_LENGTH 256
#define MAX_CHARSET_SEQUENCE_LENGTH 4
#ifdef _WIN32
char* from_encoding = "cp866";
char* to_encoding = "cp1251";
#else
char* from_encoding = "utf-8";
char* to_encoding = "utf-8";
#endif
int decode(const char* source, char* destination, size_t size) {
#ifdef _WIN32
size_t src_len = strlen(source);
iconv_t conv = iconv_open(to_encoding, from_encoding);
if (conv == (iconv_t) -1)
return -1;
size_t r = iconv(conv, (char**) &source, &src_len, &destination, &size);
iconv_close(conv);
if (r != -1)
*destination = 0;
return r;
#else
strncpy(destination, source, size);
return 1;
#endif
}
void parse_args(const int argc, char** argv) {
const struct option options[] = {
{"encoding.console", optional_argument, NULL, 0},
{"encoding.files", optional_argument, NULL, 0},
{NULL, 0, NULL, 0}
};
int c, i;
while ((c = getopt_long(argc, argv, "", options, &i)) != -1) {
switch (c) {
case 0:
if (strcmp("encoding.console", options[i].name) == 0)
from_encoding = optarg;
if (strcmp("encoding.files", options[i].name) == 0)
to_encoding = optarg;
break;
default:
break;
}
}
}
int main(int argc, char* argv[]) {
setlocale(LC_ALL, "");
parse_args(argc, argv);
char file_name[MAX_PATH_LENGTH + 1];
fgets(file_name, MAX_PATH_LENGTH, stdin);
file_name[strcspn(file_name, "\r\n")] = 0;
char decoded[MAX_PATH_LENGTH * MAX_CHARSET_SEQUENCE_LENGTH + 1];
if (decode(file_name, decoded, MAX_PATH_LENGTH * MAX_CHARSET_SEQUENCE_LENGTH) == -1) {
fprintf(stderr, "Не удалось перекодировать имя файла\n");
return EXIT_FAILURE;
}
FILE* fh = fopen(decoded, "r");
if (fh == NULL) {
fprintf(stderr, "Файл %s не найден\n", decoded);
return EXIT_FAILURE;
}
printf("Файл успешно открыт\n");
fclose(fh);
return EXIT_SUCCESS;
}
s. – V-Mor Aug 01 '19 at 06:35setlocale(LC_ALL, "Russian");тоже не подходит – typical Aug 01 '19 at 07:14".UTF8", а не"utf-8". В документации это не отражено, но я проверил, это работает. Консоль в Windows 10 также в некоторой мере поддерживает UTF8, но требует особых телодвижений по настройке буферизации для корректной работы (https://stackoverflow.com/a/45588456/8674428). Но я не думаю, что автору это действительно нужно, реальный ответ - использовать широкие символы. – MSDN.WhiteKnight Aug 01 '19 at 11:54setlocaleв этом не поможет. – Sergey Gornostaev Aug 01 '19 at 18:02wscanfи_wfopen? – Sergey Gornostaev Aug 01 '19 at 18:03