2015-08-24 6 views
1

Это мой алгоритм поиска терминов в файл.Нарушение прав доступа при поиске по файлу

void ricerca_file(char* frase){ 

char* prelievo = ""; 
file = fopen("*userpath*\\file.bin", "rb"); 
while((fgets(prelievo, sizeof(prelievo), file)) != NULL){ 
    if((strstr(prelievo, frase)) != NULL) 
     printf("frase trovata!\n"); 
} 

fclose(file); 
printf("%s", prelievo);} 

я прошу вход frase таким образом:

char* frase = ""; 
printf("insert the term that you want to search.."); 
scanf("%s", frase); 

, а затем я вызвать функцию с:

ricerca_file(frase); 

Компилятор дает мне эту ошибку после того, как я пишу вход (например, номер 2):

pr ove1.exe: 0xC0000005: место записи нарушения доступа 0x00F67BC3.

Если есть обработчик для этого исключения, программа может быть безопасно продолжена.

Что я делаю неправильно?

если не ясно, я учусь. Но я действительно не знал, как управлять поиском термина в файл. Я предполагаю, что с помощью этого алгоритма я могу пропустить множество совпадений, потому что если я ищу «привет», функция strstr, которая перемещает 5 символов за цикл, если у меня есть файл с текстом, подобным этому «abchelloabc», он сначала найдет " abche "и ничего не найдет, а после первого цикла он перейдет к части" lloab ", а затем" c ". Правильно ли я думаю, что он работает так, и это неправильно?

+0

В дополнение к ответам ниже: если ваш файл двоичный, вы не можете использовать 'fgets' по понятным причинам, и если ваш файл является текстовым файлом, вам нужно использовать открытый режим' 'r' 'вместо' 'rb «'. –

ответ

0

Необходимо сохранить память, чтобы сохранить строку, в которую вы сканируете. Вместо этого попробуйте что-то вроде этого:

char frase[80]; 
printf("insert the term that you want to search.."); 
fgets(frase, 80, stdin); 

Это выделяет достаточно места для 80 символов, а затем читает одну строку ввода.

Также проверьте результаты всех этих функций: Если они возвращают ошибку, вы должны действовать соответствующим образом.

+0

Спасибо! Каков лучший вариант между fgets и scanf? – questioner

+0

@questioner Как правило, используйте 'fgets', когда вы хотите прочитать целую строку, используйте' scanf', когда вы хотите анализировать поля в строке. – fuz

4

prelievo указывает на строковый литерал. Это постоянные данные, которые не могут быть записаны. И sizeof(prelievo) будет 2 или 4 (или любые указатели на размер в вашей системе), что вы не хотите.

Вам нужно будет указать вместо prelievo на массив символов, которые могут быть изменен:

char prelievo[1000]; 

Те же проблемы и решения применимы к frase:

char frase[1000]; 
+0

спасибо! это сработало. Но у меня есть некоторые вопросы. Результат показал мне 3 экземпляра термина, который я искал (тогда их было всего 2); этот код должен печатать все вхождения? Я так не думаю .. или strstr добавляет символы, найденные в выходной строке? – questioner

+0

так или иначе, я думал, что был прав относительно моего последнего сомнения. Не strstr() перемещает размер второго параметра int функции? разве это не пропустить определенные слова? – questioner

+0

так strstr() сначала печатает строку, если находит совпадение? – questioner

0

Что я неправильный:

относительно:

char* prelievo = ""; 
file = fopen("*userpath*\\file.bin", "rb"); 
while((fgets(prelievo, sizeof(prelievo), file)) != NULL){ 
    ... 

В вызове функции fgets() должен быть указатель на буфер как его первый параметр.

«Прелиево» - это неэнитализованный указатель.

предложение 1)

char* prelievo = malloc(1024); 
if (prelievo) { 
    file = fopen("*userpath*\\file.bin", "rb"); 
    while((fgets(prelievo, sizeof(prelievo), file)) != NULL){ 

предложение 2)

char prelievo[1024]; 
file = fopen("*userpath*\\file.bin", "rb"); 
while((fgets(prelievo, sizeof(prelievo), file)) != NULL){ 
+0

спасибо! Я не знал, что я мог бы инициализировать указатель непосредственно с помощью malloc. Какой лучший вариант? используя указатель с malloc или массив? – questioner

+0

@questioner Это полностью зависит от вас. В этом случае я бы выбрал массив фиксированного размера, как в предположении 2. Предложение 1 просто неверно, потому что здесь 'sizeof (prelievo)' не будет 1024, а скорее 4 или 8 в зависимости от вашей платформы. –

+0

Предложение 1 неверно, потому что здесь 'sizeof (prelievo)' будет 1024, а скорее 4 или 8 в зависимости от платформы. –

0

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

Если мы не проверяем ошибки/возврат, и программа работает нормально, это не означает, что программа в порядке или безопасна. В качестве примера возьмем следующий сценарий.

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

char *printFile(char *fileName){ 
    size_t length,size; 
    char *buffer; 
    FILE *file; 

    file = fopen (fileName , "r"); 


    fseek (file , 0 , SEEK_END); 
    length = (size_t)ftell (file); 
    fseek (file , 0 , SEEK_SET); 

    buffer = malloc(length); 
    if (buffer == NULL){ 
     fputs ("Memory error",stderr); 
     exit (2); 
    } 


    size = fread (buffer,1,length,file); 
    if (size != length){ 
     fputs ("Reading error",stderr); 
     exit(3); 
    } 

    fclose (file); 
    return buffer; 
} 

int main (void) { 
    char *fileName = "test.txt"; 
    char *stringToSearch = "Addams"; 
    char *fileContent = printFile(fileName); 

    if (strstr(fileContent, stringToSearch)){ 
     printf("%s was Found\n",stringToSearch); 
    }else{ 
     printf("%s was not Found\n",stringToSearch); 
    } 

    free(fileContent); 

    return 0; 
} 

Файл test.txt имеет следующее содержание:

Michael Jackson 
Bryan Addams 
Jack Sparrow 

Так что теперь, если я запускаю эту программу, я получаю:

Аддамс был найден

Кажется, все в порядке, но что произойдет, если я попытаюсь поделиться этой программой с кем-то? Или что произойдет, если я попытаюсь запустить его на другом компьютере? хорошо:

вина Сегментация (ядро сбрасывали)

OMG, что же только теперь? Простой, файл test.txt отсутствует, и я не проверял это в своей программе, поэтому.

Давайте двигаться дальше и создать этот файл и запустить эту программу еще раз:

Аддамс не найдено

Ха, мне удалось это не так? Ну нет, Valgrind имеет другое мнение:

==3657== Invalid read of size 1 
==3657== at 0x4C32FF4: strstr (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3657== by 0x400A2D: main (in /home/michi/program) 
==3657== Address 0x54202b0 is 0 bytes after a block of size 0 alloc'd 
==3657== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3657== by 0x40095E: printFile (in /home/michi/program) 
==3657== by 0x400A16: main (in /home/michi/program) 

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

+0

Спасибо за объяснение! Обычно я использую элементы управления для файлов; теперь я не использовал ничего, потому что я в основном пытался понять код. Но не знал, что это может вызвать серьезные ошибки, поэтому спасибо за подробности! – questioner

Смежные вопросы