Сложности файлового ввода / вывода в C - PullRequest
3 голосов
/ 10 февраля 2011

Я пишу версию утилиты Unix expand, которая заменяет вкладки пробелами в файле.Для этого я читаю каждый символ и проверяю, является ли он символом табуляции.Если это так, он заменяет вкладку указанным количеством пробелов, в противном случае символ печатается.

Мой основной метод выглядит так:

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

 char *help1="-help";
 char *help2= "--help";

 //int spaces; //number of spaces to replace tabs

 fp= fopen(argv[1], "rw");
 parse_file(fp, 4);
 fclose(fp);

 return 0;
}

метод parse_file выглядит как

void parse_file(FILE *fp, int spaces)
{
  int i; //loop counter
  char c; //current character
  while (c!= EOF)
{
    c= getchar(); //get char from stream

    if (c=='\t') //if char is a tab
    {
        for (i=0; i< spaces; i++)
            putchar(" "); //replace with spaces

    } 
    else 
        putchar(c); //otherwise, print the character

}

}

При компиляции я получаю целое число из указателя без предупреждения приведения для putchar(" ");, и программа выполняет ошибку segfault при выполнении.

Итак, мои вопросы:

1- Что означает предупреждение «делает целое число из указателя без приведения»?Что я могу сделать, чтобы решить эту проблему?

2- Код генерирует ошибку при выполнении с текстовым файлом, переданным в качестве аргумента.Есть ли в этом коде что-нибудь, что могло бы вызвать это?

Ответы [ 6 ]

8 голосов
/ 10 февраля 2011

вы должны использовать

putchar(' ')

вместо

putchar(" ")
5 голосов
/ 10 февраля 2011
  1. Вы вызываете putchar в строке (" "), но требуется аргумент char (' '). (На самом деле int, но только пропуск char безопасен.)

  2. Сегфоут, вероятно, из-за fclose на fp, который может быть NULL. Вам следует проверить возвращаемое значение из fopen. Причина, которую вы замечаете только после parse_file, заключается в том, что он вообще не касается fp (он читает из stdin и записывает в stdout). Чтобы использовать поток fp, вы должны использовать getc(fp) и putc(fp). (Это все равно не сработает, потому что вы перезапишете поток большим количеством данных, чем читаете из него, поэтому вы получите мусор.)

На самом деле, программа обязательно произойдет, если аргумент командной строки не задан. Либо fopen segfaults, поскольку ему передается нулевой указатель argv[1], либо он возвращает сам нулевой указатель.

При написании программ такого типа, пожалуйста, придерживайтесь философии Unix и пишите их как filters : читать из stdin, писать в stdout. Не изменяйте файл на месте, если вам не нужно.

4 голосов
/ 10 февраля 2011

В строковых литералах C имеют тип char *, указатель на некоторую область, содержащую строковые символы." " является строковым литералом, а не символом.Используйте ' ', когда вам нужен один символ

1 голос
/ 10 февраля 2011

Чтобы подвести итог проблем (я повторяю то, что говорили другие люди, но вопрос s 5 и 6 , имеющий , пока не упомянут):

  1. putchar() не принимает указатель строки в качестве аргумента, но int - константа ' ' является допустимым параметром
  2. вы не проверяете, что argc > 1перед использованием argv[1]
  3. вы не проверяете, что fopen() успешно открывает файл
  4. c должен быть определен как int, поскольку в некоторых наборах символов (char) -1 (0xFF) является допустимым символом, и сравнение c == EOF может завершиться неудачей, если c не является расширенным знаком
  5. Первый раз в цикле c используется неинициализированным и в цикле вы такжеотноситесь к EOF как к нормальному персонажу.Обычная идиома в программах на Си:

    int c;
    while ((c = fgetc(fp)) != EOF)
    { 
        // do stuff with c
    }
    
  6. Вы получаете символы из stdin, а не fp, поэтому используйте fgetc(), а не getchar()

Я думаю, что это охватывает все.

Чтобы ответить на ваш явный вопрос, вы получите предупреждение «делает целое число из указателя без приведения», когда ожидается int, но вы используете указатель (в этомcase тип " " является const char*).

1 голос
/ 10 февраля 2011

Как все остальные говорят, ре.Использование символа против строки.Что касается логики, стоящей за реальным сообщением об ошибке, которое вы видите, строка является указателем на массив символов const.Следовательно, ошибка говорит, что он конвертирует указатель в int.Большинство функций char работают с целыми числами.

0 голосов
/ 10 февраля 2011

В дополнение к тому, что уже было сказано, getchar () возвращает int, а не char.EOF - это константа типа int.Вам нужно будет прочитать результат из getchar () в int, проверить EOF и, если не найден, преобразовать int в char.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...