Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.12.2011, 20:20   #1
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию Ошибка в примере K&R

Доброго времени суток! Помогите, пожалуйста, отладить пример из книги Кернигана и Ритчи. Никак не могу сообразить, как заставить его работать.

Вот пример из книги, без изменений:
Код:
// find_orig.c

#include <stdio.h>
#include <string.h>
#define MAXLINE 1000

int getline(char* s, int lim);

/* find: вывод строк, содержащих образец из 1-го аргумента */
int main (int argc, char* argv[]) {
    char line[MAXLINE];
    long lineno = 0;
    int c, except = 0, number = 0, found = 0;

    while (--argc > 0 && (*++argv)[0] == '-')
        while (c == *++argv[0])
            switch (c) {
            case 'x':
                except = 1;
                break;
            case 'n':
                number = 1;
                break;
            default:
                printf("find: illegal option %c\n", c);
                argc = 0;
                found = -1;
                break;
            }
    if (argc != 1)
        printf("Usage: find -x -n pattern\n");
    else
        while (getline(line, MAXLINE) > 0) {
            lineno++;
            if ((strstr(line, MAXLINE) > 0)) {
                if (number)
                    printf("%ld: ", lineno);
                printf("%s", line);
                found++;
            }
        }
    return found;
}

/* getline: считывает строку в s */
int getline(char* s, int lim) {
    int c, i;

    for (i = 0; i<lim-1 && (c = getchar()) != EOF && c != '\n'; i++) {
        s[i] = c;
    }

    if (c == '\n') {
        s[i++] = c;
    }
    s[i] = '\0';

    return i;
}
Ошибки, которые я исправил:
1) Заменил строку:
while (c == *++argv[0]);
на:
while (c = *++argv[0]);
2) Заметил, что ключ 'x' не обрабатывается, но это ерунда, я исправил.
3) Не смог найти ошибку. Предполагаю, что она кроется в отмеченной красным строке. Ведь нельзя же скажем объявить массив int a[10] и произвести операцию: ++a. А здесь это проделали. Как записать правильно? Заранее спасибо всем, кто откликнется на просьбу: помочь разобраться.
8Observer8 вне форума Ответить с цитированием
Старый 08.12.2011, 21:00   #2
Blade
Software Engineer
Участник клуба
 
Аватар для Blade
 
Регистрация: 07.04.2007
Сообщений: 1,618
По умолчанию

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Ведь нельзя же скажем объявить массив int a[10] и произвести операцию: ++a.
Почему? Читаем внимательно арифметику указателей.
Начните с того, что именно у вас не работает?
Мужество есть лишь у тех, кто ощутил сердцем страх, кто смотрит в пропасть, но смотрит с гордостью в глазах. (с) Ария

Последний раз редактировалось Blade; 08.12.2011 в 21:03.
Blade вне форума Ответить с цитированием
Старый 08.12.2011, 21:19   #3
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

У меня компилятор ругается на strstr(line, MAXLINE). Говорит, что не может найти функцию с подходящими параметрами. Оно и понятно. Посмотри объявление функции. А почему в вариантах для switch (c) символы типа case 'x' ? Переменная с объявлена как int. И еще, разве хоть раз выполнится условие (c == *++argv[0])? Переменная с объявлена как int.

Последний раз редактировалось JuniorProger; 08.12.2011 в 21:22.
JuniorProger вне форума Ответить с цитированием
Старый 08.12.2011, 22:22   #4
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
Плохо

> to Blade
Я нашёл это место в книге. Написано, что эта операция не разрешена! Я даже попробовал сейчас:
Код:
#include <stdio.h>
int main () {
    int a[10] = {1,2,3};
    ++a;
    return 0;
}
Компилятор отписался:
error C2105: для "++" требуется левостороннее значениe

> to JuniorProger
Цитата:
У меня компилятор ругается на strstr(line, MAXLINE)
Да, извиняюсь, я забыл написать, что эту ошибку я тоже исправил. Блин такой косячный пример, до этого ни одного косяка, почти.
Цитата:
И еще, разве хоть раз выполнится условие (c == *++argv[0])
Вы пропустили. Я написал в первом сообщении:
Цитата:
Ошибки, которые я исправил:
1) Заменил строку:
while (c == *++argv[0]);
на:
while (c = *++argv[0]);
Цитата:
А почему в вариантах для switch (c) символы типа case 'x' ? Переменная с объявлена как int
Ну здесь точно нет косяка.

Вот исправленный код (кроме except, пока он не нужен), компилится нормально, но всё равно ошибка возникает на этапе выполнения.
Код:
// find_orig.c

#include <stdio.h>
#include <string.h>
#define MAXLINE 1000

int getline(char* s, int lim);

/* find: вывод строк, содержащих образец из 1-го аргумента */
int main (int argc, char* argv[]) {
    char line[MAXLINE];
    long lineno = 0;
    int c, except = 0, number = 0, found = 0;

    while (--argc > 0 && (*++argv)[0] == '-')
        while (c = *++argv[0])
            switch (c) {
            case 'x':
                except = 1;
                break;
            case 'n':
                number = 1;
                break;
            default:
                printf("find: illegal option %c\n", c);
                argc = 0;
                found = -1;
                break;
            }
    if (argc != 1)
        printf("Usage: find -x -n pattern\n");
    else
        while (getline(line, MAXLINE) > 0) {
            lineno++;
            if ((strstr(line, argv[argc]) > 0)) {
                if (number)
                    printf("%ld: ", lineno);
                printf("%s", line);
                found++;
            }
        }
    return found;
}

/* getline: считывает строку в s */
int getline(char* s, int lim) {
    int c, i;

    for (i = 0; i<lim-1 && (c = getchar()) != EOF && c != '\n'; i++) {
        s[i] = c;
    }

    if (c == '\n') {
        s[i++] = c;
    }
    s[i] = '\0';

    return i;
}

Последний раз редактировалось 8Observer8; 08.12.2011 в 22:33.
8Observer8 вне форума Ответить с цитированием
Старый 08.12.2011, 22:30   #5
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

Ну а как насчет того, что int c ?
JuniorProger вне форума Ответить с цитированием
Старый 08.12.2011, 22:36   #6
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

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

Думаю, косяк в этой записи: (*++argv)[0]. Не нравится она мне.

Последний раз редактировалось Stilet; 08.12.2011 в 23:10.
8Observer8 вне форума Ответить с цитированием
Старый 08.12.2011, 22:40   #7
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

Чет я тогда не понимаю. Как он в int найдет 'x' или 'n'? Он всегда будет выходить на default (наверное).

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Думаю, косяк в этой записи: (*++argv)[0]. Не нравится она мне.
Так он ошибку выдает? Попробуй так *(++argv[0])

Последний раз редактировалось Stilet; 08.12.2011 в 23:12.
JuniorProger вне форума Ответить с цитированием
Старый 08.12.2011, 22:48   #8
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Цитата:
Чет я тогда не понимаю. Как он в int найдет 'x' или 'n'? Он всегда будет выходить на default (наверное).
Вот пример:
Код:
#include <stdio.h>

int main () {
    int c;

    c = 'x';
    switch (c) {
       case 'x':
           printf("%c\n", c);
           break;
       default:
           printf("None\n");
           break;
    }
}
Цитата:
Так он ошибку выдает? Попробуй так *(++argv[0])
Попробовал, не работает. Я уже запутался с этими записями и их расшифровками
8Observer8 вне форума Ответить с цитированием
Старый 08.12.2011, 22:52   #9
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

А что вообще делает программа? Я в код не вникал. Разъясни поподробнее.

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Я успел раньше отредактировать Так точно можно, я всегда так делаю и авторы рекомендуют.
Действительно можно, но я не видел чтобы кто-то так рекомендовал делать. По-моему это только ухудшает читаемость программы и создает путанницу. Лучше так не делать.

Последний раз редактировалось Stilet; 08.12.2011 в 23:17.
JuniorProger вне форума Ответить с цитированием
Старый 08.12.2011, 23:04   #10
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Цитата:
А что вообще делает программа? Я в код не вникал. Разъясни поподробнее.
В командной строке вводишь имя .exe файла, ключи (-x или -n) и образец для поиска подстроки в строкаx. Для вывода тех где есть совпадения
Ключи:
-x все строки, кроме образца
-n ставить номер перед выводимой строкой

Ну проще на примерах объяснить:

Пример 1:
find abc

Запрос(введите строки):
abc1344
dfdffdfs
ererrer
dsfabc344

Результат:
abc1344
dsfabc344

Пример 2:
find -x -n abc

Запрос(введите строки):
abc1344
dfdffdfs
ererrer
dsfabc344

Результат:
2: dfdffdfs
3: ererrer

Предыдущий можно ещё и так запускать
Пример 2(перестановка и объединение ключей):
find -nx abc

Последний раз редактировалось 8Observer8; 09.12.2011 в 10:12.
8Observer8 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при установке KOL&MSK DKENT Компоненты Delphi 0 21.09.2011 10:36
Ошибка c AnsiChar & Char Яр|/||< (^_^) Общие вопросы Delphi 3 19.02.2010 21:22
TForm & TImage & PNG & Прозрачность delphi_beginner Общие вопросы Delphi 7 19.09.2009 08:46
EMS InterBase & FireBird Manager 3 ошибка создания Базы данных Gilio БД в Delphi 2 08.05.2009 15:59