Скопировать содержимое, ограничив длину строки N символами - C (СИ)
Формулировка задачи:
Всем доброго времени суток, нужна помощь с задачей: "Скопировать содержимое текстового файла, ограничив длину строки N символами. Слова, не помещающиеся в заданную строку не копировать." Поработав с программами, найденными в интернете получил две разные программы:
1)
2)
И всё бы ничего, но обе программы просто обрывают слова на середине, если эти слова не влезают в длину, а нужно, чтобы если слово не помещалось, то оно целиком и полностью удалялось.
Посидев, пораскинув мозгами прикинул следующую схему:
1) Копируем текстовый документ 1.txt, работаем с каждой строкой по очереди;
2) В общем цикле для работы с каждой строкой: Разбивать строку на слова, слова заносить в массив, а дальше в цикле сравнивать длину i первых слов в массиве (с пробелами) с числом N. Если i < N, то идти дальше. Если i > N, то если кол-во слов больше одного, то записывать [i-1] слов из массива в строку и переходить к следующей строке. Ну или как-то так.
На словах, как говорится, Лев Толстой... А время поджимает.
Попробовав реализовать, понял, что проблема в моих знаниях и опыте. Буду очень благодарен, если доделаете мою программу или предложите свой вариант.
Мои наработки:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN_STR 1024
#define N 5
char seps[10] = " ,.!?:;'\n";
char* text;
char* temp;
FILE* source;
FILE* target;
void main(void)
{
source = fopen("1.txt", "rt");
target = fopen("2.txt", "wt");
text = (char*)calloc(LEN_STR, 1);
temp = (char*)calloc(LEN_STR, 1);
while (!feof(source))
{
fgets(text, LEN_STR, source);
strncpy(temp, text, N);
if (strlen(text) > N)
{
temp[N] = '\n';
temp[N + 1] = 0;
}
fputs(temp, target);
}
fclose(source);
fclose(target);
free(text);
free(temp);
}#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLEN 4 //Макс. длина строки
int main(void)
{
char c=0; //Хранится символ из входного файла, вспомогательная переменная
char String[MAXLEN + 1];
char *pathFileInput=(char*)calloc(20, sizeof(char));
char *pathFileOutput=(char*)calloc(20, sizeof(char));
FILE *fileInput; //Файловая переменная для входного файла
FILE *fileOutput; //Файловая переменная для выходного файла
fileInput=fopen("1.txt", "rt");
fileOutput= fopen("2.txt", "wt");
while(c!=EOF)
{
fgets(String,MAXLEN + 1,fileInput);
fputs(String,fileOutput);
fputc('\n', fileOutput);
while (c != '\n' && c != EOF)
c = fgetc(fileInput);
if (c!=EOF) //Если это не признак конца файла, c = пробел (или любой другой неслужебный символ
c=' '; //иначе мы застрянем во вложенном while на след. итерации
}
free(pathFileInput);
free(pathFileOutput);
fclose (fileInput);
fclose(fileOutput);
return 0;
}#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN_STR 1024
#define N 5
char seps[10] = " ,.!?:;'\n";
char* text;
char* temp;
char* word;
FILE* source;
FILE* target;
char* data[100];
void main(void)
{
source = fopen("1.txt", "rt");
target = fopen("2.txt", "wt");
text = (char*)calloc(LEN_STR, 1);
temp = (char*)calloc(LEN_STR, 1);
while (!feof(source))
{
fgets(text, LEN_STR, source);
//Заимствуем код из программы, удаляющей слова, больше определённого размера
//last = temp;
//word = strtok(temp, seps);
//while (word)
//{
// strncat(res, text + (last - temp), word - last);
// if (strlen(word) <= N)
// strcat(res, word);
//
// last = word + strlen(word);
// word = strtok(NULL, seps);
//}
//strcat(res, text + (last - temp));
word = strtok(temp, seps);
while (word)
{
data = data + word;
if (strlen(data) > N)
{
temp[N] = '\n';
temp[N + 1] = 0;
}
fputs(temp, target);
word = strtok(NULL, seps);
}
strcat(res, text + (last - temp));
}
fclose(source);
fclose(target);
free(text);
free(temp);
}Решение задачи: «Скопировать содержимое, ограничив длину строки N символами»
textual
Листинг программы
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define DEFAULT_OUTPUT_WIDTH (80)
#define PROGRAM_NAME argv[0]
#define INPUT_FILE_NAME argv[1]
#define OUTPUT_FILE_NAME argv[2]
#define OUTPUT_WIDTH argv[3]
#define INPUT_BUFFER_SIZE (2048)
int main(int argc, char ** argv) {
FILE * fIn, * fOut;
char * bufIn, * bufOut, * posPtr;
size_t inpLen, outLen, tmpLen;
if ( argc < 2 ) {
fprintf(stderr, "USAGE: %s input_file [output_file [width]]\n", PROGRAM_NAME);
exit(EXIT_FAILURE);
}
if ( argc == 4 ) {
outLen = atoi(OUTPUT_WIDTH);
if ( outLen < 1 || outLen >= INPUT_BUFFER_SIZE ) {
fprintf(stderr, "%s: wrong parameter to output width - %lu\n", PROGRAM_NAME, outLen);
exit(EXIT_FAILURE);
}
}
else
outLen = DEFAULT_OUTPUT_WIDTH;
if ( ! ( bufIn = malloc(INPUT_BUFFER_SIZE) ) ) {
perror("malloc");
exit(EXIT_FAILURE);
}
if ( ! ( bufOut = malloc(outLen + 2) ) ) {
free(bufIn);
perror("malloc");
exit(EXIT_FAILURE);
}
if ( ! ( fIn = fopen(INPUT_FILE_NAME, "r") ) ) {
fprintf(stderr, "%s: can't open file %s for input!\n", PROGRAM_NAME, INPUT_FILE_NAME);
free(bufIn);
free(bufOut);
exit(EXIT_FAILURE);
}
if ( argc == 2 )
fOut = stdout;
else {
if ( ! ( fOut = fopen(OUTPUT_FILE_NAME, "w") ) ) {
fprintf(stderr, "%s: can't open file %s for output!\n", PROGRAM_NAME, OUTPUT_FILE_NAME);
fclose(fIn);
free(bufIn);
free(bufOut);
exit(EXIT_FAILURE);
}
}
while ( fgets(bufIn, INPUT_BUFFER_SIZE, fIn) ) {
while ( ( inpLen = strlen(bufIn) ) > outLen ) {
for ( posPtr = bufIn + outLen - 1; posPtr >= bufIn && ! isspace(*posPtr); --posPtr )
;
if ( posPtr < bufIn ) {
memcpy(bufOut, bufIn, outLen);
bufOut[outLen] = '\n';
bufOut[outLen + 1] = '\0';
if ( fprintf(fOut, "%s", bufOut) == EOF ) {
fprintf(stderr, "%s: can't write to output file!\n", PROGRAM_NAME);
if ( fclose(fIn) )
perror("While close input file");
if ( fclose(fOut) )
perror("While close output file");
free(bufIn);
free(bufOut);
exit(EXIT_FAILURE);
}
memmove(bufIn, bufIn + outLen, strlen(bufIn + outLen) + 1);
}
else {
tmpLen = posPtr - bufIn;
memcpy(bufOut, bufIn, tmpLen);
bufOut[tmpLen] = '\n';
bufOut[tmpLen + 1] = '\0';
if ( fprintf(fOut, "%s", bufOut) == EOF ) {
fprintf(stderr, "%s: can't write to output file!\n", PROGRAM_NAME);
if ( fclose(fIn) )
perror("While close input file");
if ( fclose(fOut) )
perror("While close output file");
free(bufIn);
free(bufOut);
exit(EXIT_FAILURE);
}
memmove(bufIn, bufIn + tmpLen + 1, strlen(bufIn + tmpLen));
}
}
if ( inpLen ) {
if ( fprintf(fOut, "%s", bufIn) == EOF ) {
fprintf(stderr, "%s: can't write to output file!\n", PROGRAM_NAME);
if ( fclose(fIn) )
perror("While close input file");
if ( fclose(fOut) )
perror("While close output file");
free(bufIn);
free(bufOut);
exit(EXIT_FAILURE);
}
}
}
if ( ferror(fIn) ) {
fprintf(stderr, "%s: error while reading input file!\n", PROGRAM_NAME);
if ( fclose(fIn) )
perror("While close input file");
if ( fclose(fOut) )
perror("While close output file");
free(bufIn);
free(bufOut);
exit(EXIT_FAILURE);
}
if ( fclose(fIn) )
perror("While close input file");
if ( fOut != stdout && fclose(fOut) )
perror("While close output file");
free(bufIn);
free(bufOut);
exit(EXIT_SUCCESS);
}
Объяснение кода листинга программы
Этот код предназначен для копирования содержимого из одного файла в другой с ограничением на количество символов в каждой строке. Он использует стандартные библиотеки C и может быть скомпилирован с помощью любого компилятора C. Список переменных и их значений:
- argc - количество аргументов в командной строке (обычно 2 или 4)
- argv - массив строк, содержащих параметры командной строки
- PROGRAM_NAME - имя программы (обычно имя исполняемого файла)
- INPUT_FILE_NAME - имя входного файла
- OUTPUT_FILE_NAME - имя выходного файла (если не указано, то это stdout)
- OUTPUT_WIDTH - ширина вывода (если не указано, то это 80)
- DEFAULT_OUTPUT_WIDTH - значение по умолчанию для OUTPUT_WIDTH, равное 80
- INPUT_BUFFER_SIZE - размер буфера ввода, равный 2048
- fIn - файловый указатель на входной файл
- fOut - файловый указатель на выходной файл (может быть stdout)
- bufIn - указатель на буфер ввода
- bufOut - указатель на буфер вывода
- inpLen - длина строки в буфере ввода
- outLen - длина строки в буфере вывода
- tmpLen - временная переменная для хранения длины строки
- posPtr - указатель на текущую позицию в строке
- isspace - функция, проверяющая, является ли символ пробелом
- fprintf - функция, используемая для записи в файл вывода
- fclose - функция, используемая для закрытия файла
- perror - функция, используемая для вывода сообщения об ошибке Основной цикл программы считывает строки из входного файла и записывает их в выходной файл, обрезая строки до заданной ширины. Если входной файл содержит символы новой строки ('\n'), они сохраняются в выходном файле. Если выходной файл не stdout, он закрывается после записи всех строк.