yagami_md Ответов: 2

Удалить возврат каретки и перевод строки в файле с помощью C ?


привет друзья
Я хочу удалить "возврат каретки" и "перевод строки" в моем файле * :)
спасибо!

Что я уже пробовал:

Я ничего не пробовал я просто хочу идею

PIEBALDconsult

То, что вы предлагаете, может быть слишком ограничено в полезности. Я рекомендую реализовать "фильтр", через который вы можете передавать поток, а не требовать файл.
Кроме того, вы можете захотеть, чтобы он принимал параметры, чтобы указать детали своей работы.
Еще лучше, если вы разрешите регулярные выражения.
Считать:
Тип oldfile.txt / REPLACECHARS "\r\n" "" > newfile.txt
Я написал такую вещь и использую ее для ряда задач, а не только для удаления "новых строк".

Andreas Gieriet

Это UNIX tr командование, верно? Иногда я задаюсь вопросом, почему нужно заново изобретать такой инструмент в среде Windows...
Овации
Энди

2 Ответов

Рейтинг:
4

Sergey Alexandrovich Kryukov

Это трудно сделать каким-либо простым способом в одном файле, по одной простой причине. Допустим, у вас есть большой файл, и вы удаляете один символ в самом начале. Поскольку остальная часть содержимого смещается, это означает, что вам придется переписать все содержимое файла. Именно это и произойдет с концами линий.

Это должно привести вас к следующей идее: если вам нужно переписать файл (за исключением, возможно, небольшой части перед первым концом строки), вы должны признать это и переписать его. Адекватное решение таково: откройте исходный файл только для чтения, новый временный файл только для записи и запишите все содержимое исходного файла во временный файл, пропустив только символы конца строки. Вы можете сделать это в некоторых кусках данных (скажем, 1 м) и удалить ненужные символы из строки перед ее копированием, используя какой-то метод замены строки. Если вы хотите простоты, кусок может быть одним символом.

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

А теперь одна маленькая проблема: что такое "конец линии". К сожалению, уродливый факт природы таков: это зависящая от платформы строка. Пожалуйста, смотрите: Новая строка-Википедия, свободная энциклопедия.

На практике вы можете игнорировать эту возможность, если у вас есть ненормально расположенные символы конца строки, и просто удалить их все, что означает удаление всех символов 0xA и 0xD. Вы также можете удалить редко используемые символы-разделители Юникода.

—СА


PIEBALDconsult

И, возможно, замените "последовательность новой строки" пробелом, если это уместно.

Sergey Alexandrovich Kryukov

Ну, спрашивающий сказал "удалить", так что это "удалить". Но можем ли мы быть уверены, что наш исследователь действительно знает, что нужно делать?
—СА

PIEBALDconsult

'ardly ч никогда.

Richard MacCutchan

... использовал большую, большую букву "Д"?

PIEBALDconsult

:большой палец вверх:

Рейтинг:
15

Andreas Gieriet

Простым решением для удаления только любого вхождения CR или NL является

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    const char *remove_any_of = "\n\r";
    int c;
    while((c = getchar()) != EOF) {
        if (!strchr(remove_any_of, c)) putchar(c);
    }
    return EXIT_SUCCESS;
}
Имейте в виду, что это хорошо работает для текста в кодировке ASCII, а также для текста в кодировке UTF-8, но не для любого другого текста.

Использование в качестве фильтра командной строки предлагается PIEBALDconsult: потребление stdin и запись в stdout.

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

Овации
Энди

PS: примерная версия альтернативного решения, упомянутого выше (с полномасштабной обработкой ошибок), может быть следующей. Получайте удовольствие! :-)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char *buffer;
    size_t capacity;
    size_t next_pos;
} pos_t;

pos_t slurp(const char *file_name)
{
    pos_t pos = { NULL, 0, 0 };
    FILE *file = fopen(file_name, "rb");
    if (!file) {
        perror("Failed to open file in read mode");
        return pos;
    }
    if (fseek(file, 0, SEEK_END)) {
        perror("Failed to go to the end of the file");
        fclose(file);
        return pos;
    }
    long size = ftell(file);
    if (size < 0) {
        perror("Failed to get the length of the file");
        fclose(file);
        return pos;
    }
    rewind(file);

    char *slurped = malloc(size);
    if (!slurped) {
        perror("Failed to allocate memory");
        fclose(file);
        return pos;
    }
    if (fread(slurped, 1, size, file) != size) {
        perror("Failed to slurp the file");
        free(slurped);
        fclose(file);
        return pos;
    }
    fclose(file);
    pos.buffer = slurped;
    pos.capacity = size;

    printf("slurp: %s = %ld bytes\n", file_name, size);

    return pos;
}

void dump(const char *file_name, pos_t *pos)
{
    FILE *file = fopen(file_name, "wb");
    if (!file) {
        perror("Failed to open file in write mode");
        return;
    }

    if (fwrite(pos->buffer, 1, pos->next_pos, file) != pos->next_pos) {
        perror("Failed to write to the file");
        fclose(file);
        return;
    }
    if (fclose(file)) {
        perror("Failed to close file");
        return;
    }

    printf("dump: %s = %ld bytes\n", file_name, pos->next_pos);
}

int read_char(pos_t *pos)
{
    if (pos->capacity <= pos->next_pos) return EOF;
    return pos->buffer[pos->next_pos++];
}

void write_char(char c, pos_t *pos)
{
    if (pos->capacity <= pos->next_pos) return;
    pos->buffer[pos->next_pos++] = c;
}

int main(unsigned int argc, const char *argv[])
{
    if (argc < 2) {
        printf("Missing file name\n");
        return EXIT_FAILURE;
    }
    
    const char *file_name = argv[1];
    pos_t read = slurp(file_name);
    pos_t write = read; // share the buffer
    if (read.capacity == 0) {
        printf("Rejected to process file %s\n", file_name);
        return EXIT_FAILURE;
    }

    const char *remove_any_of = "\n\r";
    int c;
    while((c = read_char(&read)) != EOF) {
        if (!strchr(remove_any_of, c)) write_char(c, &write);
    }
    dump(file_name, &write);

    free(read.buffer);

    return EXIT_SUCCESS;
}