Выбрать все строки из файла, содержащие искомую подстроку, и вывести их на стандартный вывод задом наперед - C (СИ)
Формулировка задачи:
Здравствуйте. Мне нужно было сделать программу-поисковик по файлу. Задача была следующая. Есть текстовый файл неопределенной длины. Пользователь задает искомую подстроку. Нужно выбрать все строки из файла, содержащие искомую подстроку, и вывести их на стандартный вывод задом на перед. При этом искомая подстрока задается как аргумент командной строки(argv). В си я программирую не очень долго, так что косячница я знатная. Пожалуйста, помогите найти ошибку в моей программе. То, что закомментировано - моя попытка заставить программу работать при вводе подстроки в самой программе.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHUNK_SIZE 1
typedef struct tagSp
{
char *s;
struct tagSp *next;
}
sp;
int grow(char **buf, int new_size)
{
if (new_size % CHUNK_SIZE == 0)
{
*buf = realloc(*buf, new_size);
if (*buf == NULL)
return 1;
}
return 0;
}
void print_reverse(char *line)
{
int i,n;
char c;
for(i=0;line[i]!='\n' && line[i]!=EOF;i++);
for(n=i;n>=0;n--)
{
printf("%c",line[n]);
}
printf("\n");
}
void find_and_print(char **lines,char *s,int lines_pos)
{
int i;
for(i=0;i<lines_pos;i++){
if (strstr(lines[i],s)!=NULL)
print_reverse(lines[i]);
}
}
int main(int argc, char **argv)
{
FILE *f;
char *buf,c,*s;
char **lines;
size_t buf_size,buf_pos;
int err,i;
if(argc!=2) {
printf("Вы забыли ввести искомую строку.\n");
exit(1);
}
f = fopen("c:\\1.txt","r+");
if (f == NULL)
{
printf("error: can't open file\n");
return 1;
}
lines=(char**)malloc(sizeof(char*));
int size_lines=sizeof(char*),lines_pos=0;
for(i=0;c!=EOF;i++){
buf_size = CHUNK_SIZE;
buf_pos = 0;
buf = malloc(CHUNK_SIZE);
while((c = fgetc(f)) != EOF && c!='\n')
{
err = grow(&buf,++buf_size);
if (err == 1)
return 1;
buf[buf_pos++] = c;
}
buf[++buf_pos] = 10;
grow(lines,size_lines+sizeof(char*));
lines_pos++;
lines[i]=buf;
printf("%s\n",lines[i]);
}
/*buf = malloc(CHUNK_SIZE);
buf_pos=0;
while((c = fgetc(stdin)) != EOF && c!='\n')
{
err = grow(&buf,++buf_size);
if (err == 1)
return 1;
buf[buf_pos++] = c;
}*/
printf("%s\n",buf);
printf("%s\n",argv[1]);
buf=argv[1];
find_and_print(lines,buf,lines_pos);
for(i=0;i<lines_pos;i++)
free(lines[i]);
free(lines);
return 0;
}Решение задачи: «Выбрать все строки из файла, содержащие искомую подстроку, и вывести их на стандартный вывод задом наперед»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *revStr(char *str){
char *h, *t, c;
for ( h = str, t = str + strlen(str) - 1; h < t; h++, t-- ){
c = *h;
*h = *t;
*t = c;
}
return str;
}
/*
Есть текстовый файл неопределенной длины. Пользователь задает искомую подстроку. Нужно выбрать все строки из файла,
содержащие искомую подстроку, и вывести их на стандартный вывод задом на перед. При этом искомая подстрока задается
как аргумент командной строки(argv).
*/
/* первый аргумент - имя файла, второй - что ищем (если из нескольких слов, то в кавычках) */
int main(int argc, char **argv){
FILE *f;
char buf[BUFSIZ], *p, **strings;
long count, i;
if ( argc < 3 ){
printf("Usage: %s <file_name> <string_to_find>\n", *argv);
exit(1);
}
if ( ( f = fopen(argv[1], "rb") ) == NULL ){
fprintf(stderr, "%s: can't open file %s for input!\n", argv[0], argv[1]);
exit(1);
}
strings = NULL;
count = 0;
while ( fgets(buf, sizeof(buf), f) ){
if ( p = strrchr(buf, '\n') )
*p = 0;
if ( strstr(buf, argv[2]) ){
if ( ( strings = (char**)realloc(strings, sizeof(char*) * (count + 1)) ) == NULL ){
fprintf(stderr, "%s: memory error!\n", *argv);
exit(1);
}
if ( ( strings[count] = strdup(buf) ) == NULL ){
fprintf(stderr, "%s: memory error!\n", *argv);
exit(1);
}
++count;
}
}
if ( ferror(f) ){
fprintf(stderr, "%s: error while reading file %s\n", argv[0], argv[1]);
exit(1);
}
fclose(f);
if ( !strings || !count ){
fprintf(stderr, "%s: no strings containing \"%s\" found in file %s\n", argv[0], argv[2], argv[1]);
exit(1);
}
for ( i = count - 1; i >= 0; --i )
printf("%s\n", revStr(strings[i]));
for ( i = 0; i < count; ++i )
free(strings[i]);
free(strings);
exit(0);
}
Объяснение кода листинга программы
- Первый аргумент функции main() - имя файла, второй аргумент - искомая подстрока.
- Создается массив символов 'buf' для чтения файла построчно.
- Если аргументов командной строки меньше 3, выводится сообщение об ошибке и программа завершается.
- Открывается файл для чтения.
- В случае ошибки при открытии файла выводится сообщение об ошибке и программа завершается.
- Строки из файла сохраняются в массиве строк 'strings'.
- Если произошла ошибка при выделении памяти для массива строк или при выделении памяти для каждой строки, выводится сообщение об ошибке и программа завершается.
- Последняя строка в каждой строке удаляется (заменит символ новой строки на 0).
- Если строка содержит искомую подстроку, она добавляется в массив строк.
- Если при чтении файла произошла ошибка, выводится сообщение об ошибке и программа завершается.
- Файл закрывается.
- Если массив строк пуст или не содержит ни одной строки с искомой подстрокой, выводится сообщение об ошибке и программа завершается.
- Все строки из массива строк выводятся в обратном порядке.
- Все строки из массива строк освобождаются.
- Массив строк освобождается.
- Программа завершается.