2016-09-29 5 views
-1

Я только начал изучать C. Мой первый проект - это программа, которая читает текст из текстового файла и затем форматирует его на основе команд в файле.Как найти слово в файле, поместить его в массив и удалить его в C

Моим решением было сделать программу сканированием через текстовый файл, найти команды, удалить их из текстового файла и затем поместить их в массив. Затем запустите оставшуюся часть текста, используя инструкции каждой команды.

Например, если команда удаляет лишние пробелы, она удаляет лишние пробелы из кода и так далее. До сих пор я просто код, который считывает файл и выводит его из

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
FILE *fp; 
char *filename; 
char ch; 



// Check if a filename has been specified in the command 
    if (argc < 2) 
    { 
     printf("Missing Filename\n"); 
     return(1); 
    } 
    else 
    { 
     filename = argv[1]; 
     printf("Filename : %s\n", filename); 
    } 

    // Open file in read-only mode 
    fp = fopen(filename,"r"); 


    // If file opened successfully, then print the contents 
    if (fp) 
     { 
     printf("File contents:\n"); 
     while ((ch = fgetc(fp)) != EOF) 
      { 
       printf("%c",ch); 
      } 

     } 
    else 
     { 
     printf("Failed to open the file\n"); 
     } 

return(0); 
} 

Этот код не совсем мой, я должен отметить.

Моя проблема есть. Я пытаюсь написать фрагмент кода, который сканирует текстовый файл, находит конкретное слово, удаляет его из текстового файла и сохраняет его в массиве. Вот и все. После того, как слово найдено в текстовом файле, оно сохраняется в массиве и затем удаляется из текстового файла. Это слово будет вариантом форматирования. Затем текст отформатируется в соответствии с тем, что является опцией, а затем распечатывается в другой текстовый файл.

Например, он сканирует текст и находит слово «LW30», это слово означает, что каждая строка должна содержать не более 30 символов. Когда программа находит этот параметр, он форматирует текст в соответствии с тем, что означает опция. Это может быть более одного варианта, каждый из которых означает разные вещи, но есть только 5 возможных вариантов, и, конечно же, он будет читать случайный текстовый файл, поэтому я не знаю, какие будут варианты.

Команды форматирования:

.LW (ширина) каждая строка форматируется так, что никогда не бывает больше, чем «ширина» символов в каждой строке

.LM (слева) здесь каждая строка следующего за команда будет иметь отступы «левые» пробелы из поля левой руки. Отступ включен в ширину страницы.

.FT [off | on] Используется для включения и выключения форматирования. Если команда появляется с «выключено», то весь текст под командой до следующей команды «.FT» выводится без форматирования. Если он появляется с надписью «включено», то весь текст под командой до следующей команды «.FT» выводится с таким количеством слов, которое заполняет заданную ширину страницы

.LS (linespacing), если «linespacing» is но не 0 (0), то между каждой текстовой строкой появятся строки, пробельные пустые строки. Пустая строка во входном файле считается такой же, как текстовая строка.

Кроме того, каждая команда будет иметь свою собственную линию в тексте

Я бы очень признателен за помощь в этом.

+1

Пожалуйста, сообщите, какие именно проблемы в коде, что вам нужна помощь с. Вы пытались решить проблему? – Gerhard

+0

Не рекомендуется изменять файл и читать его снова. Вместо этого вы должны анализировать его на лету. Однако ответ зависит от структуры файла, который вы берете в качестве входных данных. Без дополнительной информации мы не можем помочь –

+0

@Gerhard Я отредактировал его, я повторил свою проблему в абзаце после кода. Пожалуйста, скажите мне, нужно ли мне быть более ясным. –

ответ

1

Это проблема, которую нужно разделить на небольшие, чтобы ее легко решить.

  1. Прочитайте входной файл строка за строки

    а. если это команда форматирования, измените состояние программы с опциями форматирования

    b.else напечатать строку, правильно отформатированную во временном файле

  2. Переопределите входной файл с содержимым временного файла.

Сначала давайте определим несколько типов, которые будут использованы позже. Если вы новичок в C, я приглашаю вас проверить this page и прочитать, что такое enum, struct и union.

Перечисление возможных команд

typedef enum Command_e { CMD_NONE, LW , LM , FT , LS } Command; 

enumaration из различного рода линий. В основном у Вас есть два вида линий: регулярные линии, чтобы быть отформатированы, и один, содержащие команды

typedef enum LineType_e { LT_NONE, REGULAR , COMMAND } LineType; 

структуры, представляющая линию. Строка содержит ее тип. Кроме того, строка REGULAR содержит ее длину и ее содержание. A COMMAND содержит его тип и его параметр. Мы будем представлять значения on и off соответственно на 1 и 0.

typedef struct Line_s 
{ 
    LineType type; 

    union 
    { 
    struct cmd_s 
    { 
     Command type; 
     int  arg; 
    } cmd; 

    struct reg_s 
    { 
     char * str; 
     size_t len; 
    } reg; 

    } content; 

} Line; 

В C нет стандарта getline функция. Тем не менее, это легко сделать с помощью функции fgets.

// Read a line from the stream and returns a string containing every 
// characters of the line until a newline character is read or end-of-file 
// is reached. size is filled with the size of the string including the 
// newline character. 
// If end-of-file is reached before any character is read, the function 
// returns NULL 
char * getline(FILE * stream, size_t * s) 
{ 
    char * buf = NULL; // Buffer to return 
    int cnt = 0; 
    int size = 0; // Buffer size 
    int start = 0; // Where to start writing in the buffer 

    do 
    { 
    // Resize the buffer to (2^cnt * BUFF_SIZE) and fill the expanded 
    // part with the a null character 
    size = BUFF_SIZE * (1 << cnt); 
    start = BUFF_SIZE * (1 << (cnt - 1)) - 1; 
    start = start < 0 ? 0 : start; 
    buf = realloc(buf, size * sizeof(char)); 

    memset(& buf[start], '\0', size - start); 

    // Read a maximum of (size - start) characters from the stream or 
    // until a newline character has been reached 
    fgets(& buf[start], size - start, stream); 
    cnt ++; 
    } // Loop until a complete line has been read 
    while(buf[size - 2] != '\0' && 
     buf[size - 2] != '\n' && 
     ! feof(stdin)); 

    // If nothing has been read from the file, free the memory and returns 
    // a NULL pointer 
    if(buf[0] == '\0') 
    { 
    free(buf); 
    buf = NULL; 
    (* s) = 0; 
    } 
    else 
    { 
    (* s) = strlen(buf); 
    } 

    return buf; 
} 

Где BUFF_SIZE макрос, который определяет типичный размер для буфера. Эта функция требует включения string.h, поскольку она использует memset и stdlib.h для использования realloc.

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

int getNextLine(FILE * stream, Line * line) 
{ 
    size_t size; 
    char * str = getline(stream, & size); 

    if(! str) 
    { 
    line->type = LT_NONE; 
    return 0; 
    } 

    str[size - 1] = '\0'; // Remove the newline character 

    if(size - 1 > 2) 
    { 
    if(str[0] == 'L' && (str[1] == 'W' || str[1] == 'M' || str[1] == 'S')) 
    { 
     // If the remaining of the string is made characters between '0' and 
     // '9', then, str is a LW, LM or LS command 
     int val = 0; 
     int i; 
     for(i = 2; i < size - 1; i ++) 
     { 
     if(str[i] < '0' || str[i] > '9') break; 

     val = val * 10 + (str[i] - '0'); 
     } 

     if(i < size - 1) 
     { 
     line->type   = REGULAR; 
     line->content.reg.str = str; 
     line->content.reg.len = size; 
     } 
     else 
     { 
     line->type   = COMMAND; 
     line->content.cmd.arg = val; 

     switch(str[1]) 
     { 
      case 'W' : line->content.cmd.type = LW; break; 
      case 'M' : line->content.cmd.type = LM; break; 
      case 'S' : line->content.cmd.type = LS; break; 
     } 
     } 

     return 1; 
    } 

    if(size - 1 == 4 && str[0] == 'F' && str[1] == 'T' && 
         str[2] == 'o' && str[3] == 'n') 
    { 
     // FTon command found 
     line->type    = COMMAND; 
     line->content.cmd.type = FT; 
     line->content.cmd.arg = 1; 

     return 1; 
    } 

    if(size - 1 == 5 && str[0] == 'F' && str[1] == 'T' && 
         str[2] == 'o' && str[3] == 'f' && str[4] == 'f') 
    { 
     // FToff command found 
     line->type  = COMMAND; 
     line->content.cmd.type = FT; 
     line->content.cmd.arg = 0; 

     return 1; 
    } 
    } 

    // If we reach this point no command have been found 
    line->type = REGULAR; 
    line->content.reg.str = str; 
    line->content.reg.len = size; 

    return 1; 
} 

Теперь вы почти закончили. В основном цикле, который остановится, когда getNextLine вернется 0, вы можете установить несколько переменных в соответствии с полученными вами командами, а когда вы получаете регулярную линию, вы можете просто вызвать функцию формата, которая выведет строку, отформатированную так, как должна поток. Вот пример такой функции.

void format(FILE * stream, Line line, int ft, int lw, int lm, int ls) 
{ 
    if(! ft) 
    { 
    // If the formatting is disabled, simply send the line to the stream 
    fprintf(stream, "%s\n", line.content.reg.str); 
    } 
    else 
    { 
    int i; 
    int j; 
    char f[16] = { 0 }; 
    sprintf(f, "%%.%ds\n", lw - lm); 

    i = 0; 

    do 
    { 
     for(j = 0; j < lm; j ++) fprintf(stream, " "); 
     fprintf(stream, f, & line.content.reg.str[i * (lw - lm)]); 
     for(j = 0; j < ls; j ++) fprintf(stream, "\n"); 

     i++; 
    } 
    while(i * (lw - lm) < line.content.reg.len); 
    } 
} 

временный файл я говорил ранее, могут быть открыты с помощью функции tmpfile. Когда вы достигнете конца входного файла, вам просто нужно закрыть ваш входной файл и скопировать содержимое временного файла в него. Это делается просто с buffers и fprintf. Не забудьте освободить память, вызвав функцию free после того, как вы напечатали форматированную строку во временном файле, чтобы избежать утечек памяти.

В конце файла, как

FTon 
LW30 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam est arcu, congue vehicula consectetur in, tempus ac ex. Integer urna lectus, maximus vel felis sed, dapibus gravida risus. Curabitur diam arcu, accumsan at magna id, laoreet condimentum ante. 

FToff 
Nulla id velit justo. Aenean leo risus, interdum lobortis enim sit amet, aliquet elementum dolor. Morbi pretium velit sed mauris molestie viverra. Cras ut cursus nibh. Aliquam ut aliquam nunc, eget rhoncus sapien. 

LS1 
Sed efficitur justo aliquam orci molestie, vel condimentum dui semper. Sed lobortis dignissim ligula ut bibendum. Pellentesque finibus euismod massa a congue. 

FTon 
Sed placerat quam eget ante rutrum pretium a in orci. Quisque id lorem dapibus, tincidunt lorem et, convallis orci. Etiam sed placerat ante. 

LM5 
Donec mi est, sodales sed faucibus ac, elementum eu velit. Nam mollis varius porttitor. Sed dignissim sodales malesuada. 
LW15 
Donec nec tempus turpis, at condimentum velit. 

даст вам следующий вывод

Lorem ipsum dolor sit amet, co 
nsectetur adipiscing elit. Ali 
quam est arcu, congue vehicula 
consectetur in, tempus ac ex. 
Integer urna lectus, maximus 
vel felis sed, dapibus gravida 
risus. Curabitur diam arcu, a 
ccumsan at magna id, laoreet c 
ondimentum ante. 

Nulla id velit justo. Aenean leo risus, interdum lobortis enim sit amet, aliquet elementum dolor. Morbi pretium velit sed mauris molestie viverra. Cras ut cursus nibh. Aliquam ut aliquam nunc, eget rhoncus sapien. 

Sed efficitur justo aliquam orci molestie, vel condimentum dui semper. Sed lobortis dignissim ligula ut bibendum. Pellentesque finibus euismod massa a congue. 

Sed placerat quam eget ante ru 

trum pretium a in orci. Quisqu 

e id lorem dapibus, tincidunt 

lorem et, convallis orci. Etia 

m sed placerat ante. 



    Donec mi est, sodales sed 

     faucibus ac, elementum e 

    u velit. Nam mollis variu 

    s porttitor. Sed dignissi 

    m sodales malesuada. 

    Donec nec 

    tempus tur 

    pis, at co 

    ndimentum 

    velit. 
+0

Спасибо m8, это сработало отлично! –

+1

Я ценю вас, объясняя каждую часть. Есть еще определенные части, которые я не получаю, но я просто посмотрю на них. Я не планирую, как копировать вашу работу в точности, я все же хочу сделать сам, чтобы я учился, но я буду использовать это, чтобы помочь. Возможно, просто скопируйте небольшие блоки кода, но спасибо. Это было действительно хорошо сделано –

+0

Это дух! Не стесняйтесь комментировать здесь, если вам нужна дополнительная информация –