Скажите в чем моя ошибка! (работа со строками)

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
edimus
Сообщения: 7
Зарегистрирован: 21 ноя 2007, 16:28

Скажите в чем моя ошибка! (работа со строками)

Сообщение edimus » 21 ноя 2007, 16:33

Программа должна считывать строки из файла, в строке данные разделены пробелами (только после первого данного идет 3 пробела). программа должна сохранять данные в переменные... Вот что у мя получилось...
компилится, но либо вылетает, либо уходит в бесконечный цикл... уже 3й день парюсь над ней... как поправить не знаю... ПОМОГИТЕ ПЛИЗ! Пишу на Си


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{ FILE * pFile;
int c_count;
char * string ; // обрабатываемая строка
char * p1, * p2, * p3, * p4, * p5, * p6, * p7, * p8, * p9, * p10;
char * pch;

pFile = fopen ("access.log.1" , "r");

if (pFile == NULL) perror ("Error opening file");
else while ( !feof(pFile) )
{ c_count=1;
fgets(string ,255,pFile);
puts(string);
pch=strchr(string,' ');
while (pch!=NULL)
{pch=strchr(pch+1,' ');
switch(c_count)
{
case 1: strncpy(p1,string,pch-string+4);
case 2: strncpy(p2,string,pch-string+1);
case 3: strncpy(p3,string,pch-string+1);
case 4: strncpy(p4,string,pch-string+1);
case 5: strncpy(p5,string,pch-string+1);
case 6: strncpy(p6,string,pch-string+1);
case 7: strncpy(p7,string,pch-string+1);
case 8: strncpy(p8,string,pch-string+1);
case 9: strncpy(p9,string,pch-string+1);
case 10: strncpy(p10,string,pch-string+1); }
if (strchr(string,' ')) c_count++;
}
fclose(pFile);
}


//printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
system("PAUSE");
return 0;
}

Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Re: Скажите в чем моя ошибка! (работа со строками)

Сообщение Romeo » 23 ноя 2007, 10:37

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

Выделять память можно двумя способабами: динамически и статически.

Динамичечкое выделение подразумевает использование парных функций malloc и free в случае С и парных операторов new и delete в случае С++. В случае динамического выделения память резервируется в так называемой heap области памяти. Её ещё называют динамической областью.

Стачиское выделение подразумевает использование синтаксической конструкции char pszBudder[ELEMENTS_NUMBER], где ELEMENTS_NUMBER - константа, указывающая на количество резервируемых элементов (синтаксис одинаков для С и С++). В этом случае память выделяется либо в сегменте данных, если декларация помещена вне функций, либо на стеке, если декларация помещена внутри функции (или метода для С++).

В твоём случае память должны быть выделена под все указатели на char твоей программы, исключая pch. Однако программу можно подифицировать так, чтобы память выделялась только под string, а все остальные поинтеры просто указывали на какой либо элемент этого массива. Для этого вместо вызова strncpy нужно использовать присвоение, а в конце слова на месте пробела ставить символ '\0', чтобы функция printf "думала", что на этом слово и заканчивается.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.

edimus
Сообщения: 7
Зарегистрирован: 21 ноя 2007, 16:28

Re: Скажите в чем моя ошибка! (работа со строками)

Сообщение edimus » 23 ноя 2007, 10:41

Romeo писал(а):Ты определил миллион указателей на char, но я нигде не вижу где выделяется память под строку, в которую ты собираешься считывать данные.

Выделять память можно двумя способабами: динамически и статически.

Динамичечкое выделение подразумевает использование парных функций malloc и free в случае С и парных операторов new и delete в случае С++. В случае динамического выделения память резервируется в так называемой heap области памяти. Её ещё называют динамической областью.

Стачиское выделение подразумевает использование синтаксической конструкции char pszBudder[ELEMENTS_NUMBER], где ELEMENTS_NUMBER - константа, указывающая на количество резервируемых элементов (Синтаксис одинаков для С и С++). В этом случае память выделяется либо в сегменте данных, если декларация помещена вне функций, либо на стеке, если декларация помещена внутри функции (либо метода для С++).

В твоём случае память должны быть выделена под все указатели на char твоей программы, исключая pch. Однако программу можно подифицировать так, чтобы память выделялась только под string, а все остальные поинтеры просто указывали на какой либо элемент этого массива. Для этого вместо вызова strncpy нужно использовать присвоение, а в конце слова на месте пробела ставить символ '\0', чтобы функция printf "думала", что на этом слово и заканчивается.
Cпасибо! Исправил уже! Если интересно как могу выложить код! =)

Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Re: Скажите в чем моя ошибка! (работа со строками)

Сообщение Romeo » 23 ноя 2007, 11:34

Выложи. Это будет полезно читателям. Заодно я покритикую, если ты вне против :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.

edimus
Сообщения: 7
Зарегистрирован: 21 ноя 2007, 16:28

Re: Скажите в чем моя ошибка! (работа со строками)

Сообщение edimus » 23 ноя 2007, 11:50

Romeo писал(а):Выложи. Это будет полезно читателям. Заодно я покритикую, если ты вне против :)
не против пожалуйтса критикуйте и разносите меня в пух и прах! =)))

Код:

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

int main()
{ FILE * pFile;
int c_count;
char * str ; // обрабатываемая строка
char pch[]=" ";
char *word;
char *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10;
int i; //счетчик
pFile = fopen ("access.log.0" , "r");
if (pFile == NULL) perror ("Error opening file");
else
while ( !feof(pFile) )
{ i=1;
fgets(str ,255,pFile);
puts(str);
printf("\n");
}
word=strtok(str,pch);
while(word!=NULL)
printf("%s\n",word);
{ switch (i)
{case 1: p1=word;
case 2: p2=word;
case 3: p3=word;
case 4: p4=word;
case 5: p5=word;
case 6: p6=word;
case 7: p7=word;
case 8: p8=word;
case 9: p9=word;
case 10: p10=word; }

i++;

word=strtok(NULL,pch);

}
fclose(pFile);
printf("%s\n","MEDBED ");
system("PAUSE");
return 0;
}

Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Re: Скажите в чем моя ошибка! (работа со строками)

Сообщение Romeo » 23 ноя 2007, 12:08

Не верю, что работает. Ты так и не послушался меня и не выделил память под str. Если работает, то тебе просто очень повезло. Значит в str по чистой случайности попало значение адреса из сегмента данных в который можно писать. В релиз сборке, где все указатели автоматически инициализируются NULL, работать точно не будет. Замени char * str на char char str[256].

Ещё один коментарий. Подождать нажатия клавиши можно значительно проще, чем вызываю функцию системы (в данном случае DOS). Достаточно вызвать getch();. Он находится в хеадере conio.h.

Если лень вызывать подключать ещё один хеадер, могу найчить как это сделать на ассемблере :)

Код: Выделить всё

asm{
   xor ax, ax
   int 16h
}
Кстати, если не будешь использовать вызов system, то от включения stdlib.h можно будет отказаться. Опять-таки экономим на размере исполняемого файла.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.

Ответить