LinuxForum.Fans
Тема

Чтение символов из файла. C

Автор: marikk 8 сообщений 2785 просмотров
#382342

Всем привет. Подскажите пожалуйста как прочитать n-ое количество символов из файла?
Проблема собственно в следующем. В системе установлена кодировка utf-8. В ней русские символы занимают 2 байта. А все библиотечные функции(fread, fgets) считывают определенное количество байт(кроме fgets). Другими словами в случае неудачи теряется один символ.
Пример

text

  FILE *fin, *fou;

if ((fin=fopen(argv[1], "r")) == NULL) { // если исходник не открылся выходим perror ("Ошибка открытия входного файла"); exit -1; } char ts[SZ]; memset (ts, 0, SZ);

fread (ts, 11, 1, fin); printf ("%s||| \n", ts); fclose(fin);

Алфовитную последовательность выводит так


абвгд?|||

Подскажите пожалуйста как с этим бороться ?

#382350
"marikk" написал:
fread (ts, 11, 1, fin);

Я не спец по C, но почему считывается 11 байт, а не 12? Получается, что последний символ до конца не прочитан, вот его и не может вывести.

Upd. Вы указываете размер блока для чтения и количество. И при двухбайтовой кодировке последний символ не читается. Попробуйте 12 указать.

#382355
"rizado" написал:
Я не спец по C, но почему считывается 11 байт, а не 12? Получается, что последний символ до конца не прочитан, вот его и не может вывести.
Upd. Вы указываете размер блока для чтения и количество. И при двухбайтовой кодировке последний символ не читается. Попробуйте 12 указать.

Пробелы цифры и латинские символы занимают по одному байту. В этом то и вся проблема.

#382356
"marikk" написал:
Пробелы цифры и латинские символы занимают по одному байту. В этом то и вся проблема.

Так у Вас написано:

"marikk" написал:
Алфовитную последовательность выводит так

абвгд?|||

Алфавит-то русский, значит, в данном случае 12 байт.

#382362
"rizado" написал:
Алфавит-то русский, значит, в данном случае 12 байт.

Ну алфавит в качестве исходного текста был выбран для наглядности. По условию лабораторной это большой текстовый файл. В котором все русские буквы нужно заменить на следующими за ними по алфавиту.

Предполагаю сделать так.

text

FILE *fi, fo;

открыть потоки

while (!feof(fi)) { прочитать порцию данных из fi перевести в cp1251 заменить русские символы перевести обратно записать в fo. }

#382364
"marikk" написал:
перевести в cp1251

Перед этим рекомендую проверять, русская ли это буква. А то попадёт что-то из испанского или французского алфавита с диакритическими знаками, а вы его в 1251 :) .

#382401

marikk, используй fgetws/c для чтения и соответствующие функции для работы с многобайтовыми символами...
да, учитывая постановку задачи, преподу, возможно, проидётся объяснять, что такое utf-8.

#382658

Рабочий исходник. Если комy интересно

Показать
text

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

#define SZ 300 // размер блока

int main (int argc, char **argv) { if (!setlocale(LC_ALL, "ru_RU.UTF-8")) { // óстанавливаем лоакаль. Необходимо для правильного отображения символов perror ("SETLOCALE FAIL"); exit (-1); }

if (argc < 3) { // проверяем число аргóментов. 1 - имя программы 2 - входной файл 3 - выхлоп printf ("Неправильное количество аргóментов. \n"); exit -1; }

FILE *fin, *fou;

if ((fin=fopen(argv[1], "r")) == NULL) { // если исходник не открылся выходим perror ("Ошибка открытия входного файла"); exit -1; }

if ((fou=fopen(argv[2], "wa")) == NULL) { // если выхлоп не открылся закрываем исходник, вываливаемся fclose (fin); perror ("Ошибка открытия выхлопа"); exit -1; }

while (!feof (fin)) { // пока lseek в fin не достиг конца файла wchar_t ws[SZ]; if (fgetws(ws, SZ, fin) == NULL) { // читаем порцию символов perror ("Ошибка чтения <-"); break; } int i; int sz= (int)wcslen(ws); for (i=0; i<sz; i++) { // крóтим массив. преобразóем все рóсские символы if ( (ws[i] >= 1072 && ws[i] < 1103) || (ws[i] >= 1040 && ws[i] < 1071) ) ws[i]++; } if (fputws(ws, fou) < 0) { // записываем perror ("Ошибка записи в ->"); break; } } fclose (fin); fclose (fou); }

Код отрабатывает нормально. Только вот возникает такая ситуация.

Размер файла 10 символов. При первом заходе функция чтения захватывает все данные далее отрабатывает нормально.
Потом выполнение попадает на условие !feof (fin), и почему то выполнение не прерывается. Может я где ошибся ?

Войдите или зарегистрируйтесь, чтобы ответить.