Странный сегфо в Си - PullRequest
       1

Странный сегфо в Си

3 голосов
/ 28 сентября 2011

Хорошо, так что я не совсем уверен, что здесь происходит. У меня есть простая функция, int foo(char *filename), которая берет filename и считает слова в файле.

int foo(char *filename){

  FILE *inFile;
  int wordCount = 0;    

  printf("foo\n"); // test printf() statement (currently prints)

  char word[50];
  inFile = (&filename, "r");

  printf("infile\n");  // test printf() statement (currently prints)

  while (1){
    printf("while");   // test printf() statement (doesn't print)
    fscanf(inFile, "%s", word);
    if (feof(inFile))
        break;
    printf("%d", wordCount); //test printf() statement
    wordCount++;
  }
  fclose(inFile);
  return wordCount;

}

Как видите, я печатаю "infile", но не "while". Я получаю ошибку сегментации. Кто-нибудь имеет какие-либо идеи, почему это не работает Кроме того, правильно ли мое утверждение inFile = (&filename, "r");? Я не очень хорош с указателями.

Ответы [ 4 ]

7 голосов
/ 28 сентября 2011

Я удивлен, что эта строка на самом деле компилируется:

inFile = (&filename, "r");

Если вы пытаетесь открыть файл:

inFile = fopen(filename, "r");

EDIT:

И, как уже упоминалось, вам нужно завершить свои printf s \n или позвонить fflush(stdout), иначе он будет буферизован, а не распечатан.

4 голосов
/ 28 сентября 2011

Что вы ожидаете от этой строки?

inFile = (&filename, "r");

Потому что, похоже, вам не хватает функционального вызова. Я подозреваю, что вы хотели что-то вроде этого:

inFile = fopen(filename, "r");

То есть функция fopen ожидает символьный указатель, и у вас есть это:

int foo(char *filename){

Так что вам не нужно использовать оператор &. Оператор & возвращает адрес переменной, поэтому, введя &filename, вы в конечном итоге получите (указатель на (указатель на (char)). Вы редко будете использовать оператор & со строками; вы обычно увидите, что он используется, когда функция должна вернуть несколько значений (например, функция Unix wait()).

Существует ряд учебных пособий, в которых более подробно рассказывается о C-указателях; поиск Google для «указателей c» дает некоторые вероятные результаты. И, конечно же, прочитайте свой K & R:).

3 голосов
/ 28 сентября 2011

Причина, по которой вы не видите печать "while", заключается в том, что она не заканчивается на \n, поэтому сохраняется в буфере и не распечатывается к моменту возникновения ошибки seg.

Ошибка сегмента возникает в fscanf, потому что вы пропустили fopen и испортили ваши указатели. @ Мистический объяснил, как это исправить.

2 голосов
/ 28 сентября 2011

ВСЕГДА проверьте возвращаемое значение из fopen(), вызов которого, кажется, отсутствует.

FILE *inFile = fopen(filename, "r");
if (inFile == 0)
    ...diagnose error...do not use inFile...

Обратите внимание на отсутствие & из filename взвонок на fopen();вам это просто не нужно.

printf() перед fscanf() ничего не производит, поскольку строка вывода не заканчивается новой строкой;он удерживается до тех пор, пока вы не напечатаете новую строку, и сбой не произойдет до того, как вы это сделаете.

Сбой происходит, потому что строка "r" не является допустимым файловым потоком;если бы вы на самом деле вызвали fopen(), это, вероятно, произошло бы из-за того, что открытие не удалось, и вы не проверили его.

Если ваш компилятор не дал вам предупреждений о коде, найдите лучший компилятор.Если он действительно давал вам предупреждения, научитесь прислушиваться к ним (и исправлять их), прежде чем отправлять сообщения в StackOverflow.


Пока вы это делаете, вы можете подумать, что произойдет, если слово, которое вы получитепрочитано 50 символов или больше.Счастья не бывает.Вам следует рассмотреть возможность использования:

while (fscanf("%49s", word) == 1)
    wordCount++;

Если слово длиннее 49 символов, оно по крайней мере теперь будет разбито на некоторое количество 49-байтовых блоков (каждое считается словом) без предоставления буферапроблемы переполнения (еще один источник сбоев).Если вам нужна диагностическая печать в цикле, пусть будет так;добавьте фигурные скобки и напечатайте.

У меня очень, очень редко была причина использовать feof() в моей (25+ год) карьере программиста.Код, использующий его, обычно подозрительный;Интересно, изучил ли этот человек Паскаль и не разучил его при изучении C.

...