Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.51/35: Рейтинг темы: голосов - 35, средняя оценка - 4.51
18 / 18 / 5
Регистрация: 08.10.2009
Сообщений: 94
1

Обработка .txt кодировка ANSI и UTF-8 (буква "я" в ANSI воспринимается как EOF)

06.07.2011, 23:08. Просмотров 7255. Ответов 19
Метки нет (Все метки)

Есть следующий кусок кода:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
FILE* fp = fopen("G:\OPND1.txt", "r");
 
    if (fp!=NULL) // если файл удалось открыть
    {   while((ch = getc(fp)) != EOF) 
            str_file[i++]=ch; 
    
            str_file[i] = '\0';  
            cout << str_file << endl;
    }
    else printf("ERROR!");
 
    fclose(fp);
    system("Pause");
Ситуация следующая - если файл OPND1.txt (он состоит как из русских так и из латинских символов) в формате UTF-8 - то все отрабатывает как и рассчитано.
Если OPND1.txt - в формате ANSI - то текст выводится не полностью, а если быть точным, до первой буквы "я", которая на вывод не попадает, а вместо нее компилятор принимает EOF (Visual Studio 2010).

Что не так? Как исправить? Пожалуйста, помогите...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.07.2011, 23:08
Ответы с готовыми решениями:

Unicode, UTF-8 и ANSI в одном консольном приложении. Можно ли "на лету" конвертировать массив строк?
Всем доброго дня) Подскажите такую весчь: можно ли в консольном приложении работать с...

Кодировка ANSI в UTF-8
Здравствуйте. Кодирую текстовый файл. Файл типа txt с кодировкой utf-8. Загружаю в массив...

Кодировка Unicode, UTF-8, ANSI
Изначально текстовый файл в кодировке unicode (вроде). Открываю файл через TStringList, прогоняю...

Кодировка файла csv полученного в ANSI в UTF-8
Имеется скрипт который из файла csv добавляет данные в mysql. база у меня в UTF-8 и если файл...

19
Эксперт С++
3056 / 1398 / 421
Регистрация: 19.01.2009
Сообщений: 3,761
06.07.2011, 23:12 2
Цитата Сообщение от Neonjke Посмотреть сообщение
FILE* fp = fopen("G:\OPND1.txt", "r");
fopen не найдет такого файла. нужно:
C
1
FILE* fp = fopen("G:\\OPND1.txt", "r");
и еще попробуйте читать его в бинарном режиме или используйте функцию feof().
0
18 / 18 / 5
Регистрация: 08.10.2009
Сообщений: 94
06.07.2011, 23:16  [ТС] 3
Цитата Сообщение от schdub Посмотреть сообщение
fopen не найдет такого файла. нужно:
C
1
FILE* fp = fopen("G:\\OPND1.txt", "r");
и еще попробуйте читать его в бинарном режиме или используйте функцию feof().

fopen прекрасно находит этот файл как и в моем, так и в Вашем варианте (возможно, это особенности среды Visual Studio).
бинарный попробую, но все таки мне интересна причина это проблемы, почему "я" интерпретируется как EOF.
Замечу, что когда файл в UTF-8 или в Unicode такой проблемы не наблюдается.

Кто ответит, пожалуйста?
0
95 / 95 / 5
Регистрация: 10.04.2011
Сообщений: 256
06.07.2011, 23:17 4
Используй функцию feof(). Например цикл while(!feof(fp)) будет итерироваться до конца файла
0
18 / 18 / 5
Регистрация: 08.10.2009
Сообщений: 94
06.07.2011, 23:27  [ТС] 5
Не особо представляю, как должен выглядеть мой код с feof()
Куда там вставить счетчик?

Не могли бы пожалуйста переделать мой код с feof? Чтобы выполнялось то же самое.
0
95 / 95 / 5
Регистрация: 10.04.2011
Сообщений: 256
06.07.2011, 23:29 6
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    FILE* fp = fopen("G:\OPND1.txt", "r");
 
        if (fp!=NULL) // если файл удалось открыть
        {       while(!feof(fp)) {
                        ch = getc(fp)
                        str_file[i++]=ch;
 
                        str_file[i] = '\0';
                        cout << str_file << endl;
        }
        else printf("ERROR!");
 
        fclose(fp);
        system("Pause");
Как-то так
0
18 / 18 / 5
Регистрация: 08.10.2009
Сообщений: 94
06.07.2011, 23:31  [ТС] 7
Благодарю.
В действительности вопрос от моей лени, поправил как у вас, но забыл запихнуть в цикл строчку
ch = getc(fp)

И дивился ошибкам. =)
0
95 / 95 / 5
Регистрация: 10.04.2011
Сообщений: 256
06.07.2011, 23:32 8
Бывает
0
Эксперт С++
3056 / 1398 / 421
Регистрация: 19.01.2009
Сообщений: 3,761
06.07.2011, 23:34 9
zuq, строка 7 пропущен }
0
95 / 95 / 5
Регистрация: 10.04.2011
Сообщений: 256
06.07.2011, 23:36 10
schdub, Да пропущен. Как-то не обратил внимания. Я в исходный код от автора просто feof() подставил, за другим уже не следил
0
Эксперт С++
2122 / 1560 / 232
Регистрация: 29.05.2011
Сообщений: 3,238
07.07.2011, 00:45 11
Сдаётся мне, что в самой первой программе ch объявлен как char, потому как если бы он был объявлен как int, то и с первым кодом проблемы бы не было.
0
Заблокирован
07.07.2011, 01:00 12
Цитата Сообщение от grizlik78 Посмотреть сообщение
Сдаётся мне, что в самой первой программе ch объявлен как char, потому как если бы он был объявлен как int, то и с первым кодом проблемы бы не было.
странно... ANSI же 1 байтовый. Не нужен для него никакой int
Может ТС ANSI с юникодом попутал?
0
Эксперт С++
2122 / 1560 / 232
Регистрация: 29.05.2011
Сообщений: 3,238
07.07.2011, 01:07 13
Bers, ничего ни я, ни ТС не путали. Функция (f)getc() возвращает именно int. Угадай, почему? Потому, что иначе нет никакой возможности отличить признак конца файла (EOF == -1) от символа с кодом 255 (что для знакового char тоже -1).
1
Заблокирован
07.07.2011, 01:22 14
Цитата Сообщение от grizlik78 Посмотреть сообщение
Bers, ничего я не путал. (f)getc() возвращает именно int. Угадай, почему? Потому, что иначе нет никакой возможности отличить признак конца файла (EOF == -1) от символа с кодом 255 (что для знакового char тоже -1).
Ну во-первых, я не говорил, что вы что-то попутали. Вы же не ТС.

А во вторых, getc() действительно возвращает int, но она полностью совместима с ANSI Си.
Это значит, что ... приведение int к unsigned char должно быть без потерь данных.

Если конечно ТС юзал знаковый чар.... моя студия на такие косяки обычно сыплет предупреждениями... ошибки из-за потерь данных... наверное, случаются только у тех, кому не интересно программировать, и читать что-то там пишит компилятор. Типа работает, и ладна.

Добавлено через 2 минуты
не не, я что-то похоже сам туплю.

беззнаковый чар тут тоже не вопрёццо. Нет, нужно юзать int без всяких приведений. И не париццо.
0
Эксперт С++
2122 / 1560 / 232
Регистрация: 29.05.2011
Сообщений: 3,238
07.07.2011, 01:31 15
Во-первых, char по-умолчанию почти везде знаковый. Мало где можно встретить беззнаковый char по-умолчанию.
Во-вторых, если бы можно было бы сохранить всю информацию в char, то getc() и возвращала бы char. И знаковость здесь роли не играет.
В коде:
C
1
2
char ch;
while ((ch = getc(fp)) != EOF)
потеря информации происходит как раз при присвоении значения переменной ch, так как для "законных" символов эта функция возвращает числа 0—255, а в случае конца файла, функция возвращает EOF, то есть -1. После присваивания нельзя отличить EOF от символа с кодом 255.
А вот здесь можно:
C
1
2
int ch;
while ((ch = getc(fp)) != EOF)
Добавлено через 2 минуты
Что-то я долго пишу и тоже не сразу понимаю некоторые фразы
0
Заблокирован
07.07.2011, 01:39 16
Цитата Сообщение от grizlik78 Посмотреть сообщение
Что-то я долго пишу и тоже не сразу понимаю некоторые фразы
время без 20 минут 2 часа ночи. Как бы... ничего страшного)
0
4846 / 3267 / 466
Регистрация: 10.12.2008
Сообщений: 10,569
07.07.2011, 09:46 17
Цитата Сообщение от zuq
Используй функцию feof(). Например цикл while(!feof(fp)) будет итерироваться до конца файла
это неправильно
если будет ошибка чтения файла, конец файла никогда не наступит

Цитата Сообщение от grizlik78
Во-первых, char по-умолчанию почти везде знаковый. Мало где можно встретить беззнаковый char по-умолчанию.
надо расчитывать, что он знаковый или беззнаковый
так же, как int - это short или long

Цитата Сообщение от Bers
странно... ANSI же 1 байтовый. Не нужен для него никакой int
EOF - это число, которое меньше нуля
C89
4.9 INPUT/OUTPUT <stdio.h>

...

EOF

which expands to a negative integral constant expression that is
returned by several functions to indicate end-of-file ,that is, no
more input from a stream;
коды символов лежат в диапазоне от 0 до 255
-1 - 11111111
255 - 11111111

даже если char равен unsigned char, то:
-1 - 11111111
255 - 11111111

поэтому делается int, в котором:
-1 - 11111111111111111111111111111111
255 - 00000000000000000000000011111111

Цитата Сообщение от Neonjke
fopen прекрасно находит этот файл как и в моем, так и в Вашем варианте
бекслеш используется для экранирования, следовательно, будет попытка обработать экранирующую последовательность \O, которой не существует
никаких манипуляций с неявным преобразованием \O в \\O не должно быть

C
1
2
3
4
5
6
7
#include <stdio.h>
 
int main(void)
{
    printf("\O");
    return 0;
}
Код
[guest@localhost tests]$ .ansi t.c -o t
t.c: В функции ‘main’:
t.c:6:12: предупреждение: unknown escape sequence: '\O'
[guest@localhost tests]$
C89
A.6.2 Undefined behavior

...

* An unspecified escape sequence is encountered in a character
constant or a string literal ($3.1.3.4).
Добавлено через 17 минут
в C99 пишут, что маленький буквы зарезервированы для будущих стандартов языка
а другие символы, отличные от стандартных и зарезервированных, могут использоваться в расширениях

то есть из этого следует, что даже если компилятор использовал бы С99, то он не имел бы права использовать в fopen пути вида c:\abc
если у тебя прокатывает один бекслеш (не слеш, слеши там можно применять), то он либо запрещает имена файлов маленькими буквами, либо нарушает стандарт языка

Visual Studio 2010 использует C89, в котором любая нестандартная экранирующая последовательность - undefined behavior
0
Эксперт С++
2122 / 1560 / 232
Регистрация: 29.05.2011
Сообщений: 3,238
07.07.2011, 11:05 18
Цитата Сообщение от accept Посмотреть сообщение
надо расчитывать, что он знаковый или беззнаковый
так же, как int - это short или long
Если честно, то мысль не понял.
short int, int, long int могут отличаться размером, могут не отличаться, но все они гарантированно знаковые.
char, unsigned char, signed char имеют одинаковый размер, но если про второй и третий можно сказать, что они беззнаковый и со знаком соответственно, то про char такого сказать нельзя. Он может оказаться как беззнаковым, так и со знаком. Это 3 разных типа, хотя реализация char должна совпадать либо с unsigned char либо с signed char
0
4846 / 3267 / 466
Регистрация: 10.12.2008
Сообщений: 10,569
08.07.2011, 01:50 19
Цитата Сообщение от grizlik78
Если честно, то мысль не понял.
нельзя полагаться на то, что char имеет знак
так же, как нельзя полагаться на то, что int больше 32767

Цитата Сообщение от grizlik78
Во-первых, char по-умолчанию почти везде знаковый. Мало где можно встретить беззнаковый char по-умолчанию.
ключевое слово signed придумали из-за этой особенности char
0
Эксперт С++
2122 / 1560 / 232
Регистрация: 29.05.2011
Сообщений: 3,238
08.07.2011, 02:02 20
Цитата Сообщение от accept Посмотреть сообщение
нельзя полагаться на то, что char имеет знак

Не по теме:

Надеюсь никто не обвиняет меня в том, что я на это полагаюсь. Потому как я как раз и говорю, что он может быть любым.
Никому нельзя верить (c)

0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.07.2011, 02:02

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

Надо перекодировать все файлы txt в папке с utf в ansi
Дайте плис готовый код если не трудно который перекодирует все файлы 'тхт' в папке с утф в анси ...

Как в Qt преобразовать строку "41 4e 53 49" в "ANSI"?
Привет всемогущий All! Цивилизация (программирование) это умение жить в дурацких рамках! ...

Как перекодировать utf 8 в ANSI
Такая ситуация - берутся данные (на русском) из базы постгрес (там кодировка utf-8). необходимо...

UTF-8 файл конвертирует и сохраняет как ANSI
Доброго времени суток. Подскажите ктонибудь пожалуйста что не так делаю? Файл формируется на 1c...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.