Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
2 / 2 / 2
Регистрация: 15.05.2015
Сообщений: 93
1

Керниган/ритчи задачи 1.18

08.08.2017, 19:24. Просмотров 1979. Ответов 21
Метки нет (Все метки)

Упражнение 1.18. Напишите программу, которая будет в каждой вводимой строке заменять стоящие подряд символы пробелов и табуляций на один пробел и удалять пустые строки.

Нижеприведенный код удаляет лишние пробелы, но вот табуляцию постоянно меняет на пробел, т.е. замест
2-ух подряд табуляций выведет 2 пробела, нужен 1. Меня не хватило дальше на этот код)

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 #include <stdio.h>
 #define MAX 1000;
main()
{
    int c, lastc = 'a';
    while ((c = getchar()) != EOF)
    {
        if (c != ' ' && c != '\t')
            putchar(c);
        else if (lastc == ' ' || lastc == '/t')
            ;
        else if (c == '\t')
            putchar(' ');
        else if (c == '\n' && lastc == '\n')
            putchar('\b');      
        else
            putchar(c);
        lastc = c;      
    }       
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.08.2017, 19:24
Ответы с готовыми решениями:

Ритчи и Керниган
В этом учебники в некоторых примерах прототип функции объявляется внутри другой функции. Доля того,...

Керниган/Ритчи упражнение 1.20
&quot;Упражнение 1.20. Напишите программу detab, заменяющую символы табуляции во вводимом тексте нужным...

Указатели, Керниган и Ритчи 5.4
Здравствуйте, нужна помощь начинающему. Читаю Керниган и Ритчи и не могу понять следующую вещь:...

Керниган/Ритчи упражнение 1.22
&quot;Упражнение 1.22. Напишите программу, печатающую символы входного потока так, чтобы строки текста...

21
1118 / 931 / 429
Регистрация: 25.12.2016
Сообщений: 3,029
08.08.2017, 19:29 2
Вот похожая программа: Цикл в цикле
Правда там не учитываются табуляции, а только пробелы.
0
111 / 111 / 16
Регистрация: 19.08.2013
Сообщений: 298
08.08.2017, 19:36 3
AlexeyChun, обратите внимание на 10-ую строчку.
1
2 / 2 / 2
Регистрация: 15.05.2015
Сообщений: 93
08.08.2017, 20:18  [ТС] 4
не понимаю чем плоха 10-я строка(
8,9 - вывод символа не пробела и не табуляции
10,11 - если табуляция или пробел, и если предыдущий был пробелом или табуляцией то ничего не выводим.
0
1118 / 931 / 429
Регистрация: 25.12.2016
Сообщений: 3,029
08.08.2017, 20:26 5
Лучший ответ Сообщение было отмечено AlexeyChun как решение

Решение

Цитата Сообщение от AlexeyChun Посмотреть сообщение
C
10
lastc == '/t'
C
10
lastc == '\t'
2
2 / 2 / 2
Регистрация: 15.05.2015
Сообщений: 93
08.08.2017, 20:30  [ТС] 6
0
40 / 40 / 15
Регистрация: 29.12.2016
Сообщений: 291
08.08.2017, 22:07 7
AlexeyChun,

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
/*
 * Упражнение 1.18. Напишите программу, которая будет в каждой вводимой строке заменять стоящие подряд символы пробелов
 * и табуляций на один пробел и удалять пустые строки.
 */
 
int main()
{
  int c, ns = 0;
 
  printf("Enter string:\n");
  
  while ((c = getchar()) != EOF)
    {
      if (c != ' ' && c != '\t' && c !='\n') { ns = 0; }
      if (c == '\t' || c == ' ' || c == '\n') { ++ns; }
      if (ns <= 1) { putchar (c); }
    }
 
  return 0;
}
1
40 / 40 / 15
Регистрация: 29.12.2016
Сообщений: 291
08.08.2017, 22:27 8
Результат программы:
Керниган/ритчи задачи 1.18
строку printf("Enter string:\n"): в принципе можно убрать, если читаете внешний файл
0
2 / 2 / 2
Регистрация: 15.05.2015
Сообщений: 93
08.08.2017, 23:36  [ТС] 9
Есть ответы на задачи к книге?)
0
40 / 40 / 15
Регистрация: 29.12.2016
Сообщений: 291
09.08.2017, 04:23 10
AlexeyChun, А смысл тогда в задачах, если ответы переписывать, так ничему и не научитесь, мозг должен работать, что непонятно, спрашивайте у народа, выкладывайте свое решение, народ подправит, поможет.
0
733 / 538 / 416
Регистрация: 17.09.2015
Сообщений: 1,601
09.08.2017, 05:25 11
Цитата Сообщение от AlexeyChun Посмотреть сообщение
в каждой вводимой строке
Цитата Сообщение от AlexeyChun Посмотреть сообщение
и удалять пустые строки
В условии задачи подразумевается возможность ввода нескольких строк,а в вашем решении только одна.
0
862 / 602 / 210
Регистрация: 30.06.2015
Сообщений: 3,363
Записей в блоге: 32
09.08.2017, 14:19 12
Цитата Сообщение от AlexeyChun Посмотреть сообщение
Есть ответы на задачи к книге?)
Есть.
Погугли книгу: "К. Тондо С. Гимпел. Язык Си. Книга ответов."
0
2 / 2 / 2
Регистрация: 15.05.2015
Сообщений: 93
09.08.2017, 14:56  [ТС] 13
Цитата Сообщение от LFC Посмотреть сообщение
В условии задачи подразумевается возможность ввода нескольких строк,а в вашем решении только одна
как это реализовать?

Добавлено через 16 секунд
Цитата Сообщение от LFC Посмотреть сообщение
В условии задачи подразумевается возможность ввода нескольких строк,а в вашем решении только одна
как это реализовать?
0
733 / 538 / 416
Регистрация: 17.09.2015
Сообщений: 1,601
09.08.2017, 15:15 14
Цитата Сообщение от AlexeyChun Посмотреть сообщение
как это реализовать?
впрочем неважно,выводит всё равно одинаково)))
мой вариант:
для завершения ввода введите пустую строку(т.е. нажмите Enter два раза подряд)
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
 
int main()
{
    char c, flag = 0;
    puts("Enter some lines, for finish enter empty line:");
    while(1){
        while((c = getchar()) != '\n'){
            if(!flag && (c != ' ' && c != '\t'))
                flag = 1;
            if (c == ' ' || c == '\t'){
                putchar(' ');
                while ((c = getchar()) != '\n' && (c == ' ' || c == '\t'));
            }
            putchar(c);
        }
        if(!flag)
            break;
        putchar('\n');
        flag = 0;
    }
    return 0;
}
немного непонятен мне пассаж авторов про "удалять пустые строки", если б сохранять в массив строк,тогда да,но ведь это позже по учебнику,емнип. Вообще K&R такие перцы своеобразные-дают задания на еще не объясненный материал, шутники...
0
2 / 2 / 2
Регистрация: 15.05.2015
Сообщений: 93
09.08.2017, 15:35  [ТС] 15
Цитата Сообщение от LightProger Посмотреть сообщение
AlexeyChun, А смысл тогда в задачах, если ответы переписывать, так ничему и не научитесь, мозг должен работать, что непонятно, спрашивайте у народа, выкладывайте свое решение, народ подправит, поможет.
согласен, вот смотрю в книгу К. Тондо С. Гимпел. Язык Си. Книга ответов и думаю лучше б не открывал) такие замысловатые решения.
А по вашему коду - замест этой строки:
Цитата Сообщение от LightProger Посмотреть сообщение
if (c == '\t' || c == ' ' || c == '\n') { ++ns; }
лучше
C
1
else ++ns;
0
40 / 40 / 15
Регистрация: 29.12.2016
Сообщений: 291
09.08.2017, 16:38 16
Цитата Сообщение от AlexeyChun Посмотреть сообщение
if (c == '\t' || c == ' ' || c == '\n') { ++ns; }
лучше
CВыделить код
1
else ++ns;
Можно конечно, у меня просто уже был готовый код из задания 1,9 по этой книге, немного дописал его. Тоже смотрел в книгу ответов, получается мы оба относительно неправильно решили задачу, Вы ничего не сказали про символьные массивы, в первом посте, хотя задача из раздела про массивы, а я не заглянул в книгу, перечитать задание. Тоже начинал с этой книги, дошел до задания 1,14 и забросил ее, на мой взгляд сложновато для начинающего, стал учиться по книге "Программирование на Си для начинающих"- Грег Перри, Дин Миллер. Она написана более простецки, освою ее, потом вернусь к Кернигану и Риччи.
0
3 / 3 / 4
Регистрация: 10.12.2017
Сообщений: 6
10.12.2017, 23:33 17
Здравствуйте, Не хочу создавать новую тему, дабы не засорять форум.
Я тут новенький и вообще пару дней назад начал учить ЯП по Кернигану и Риччи.
решил немного усложнить задачу: "захватить все вводимые элементы в строку, а затем одной функцией редактировать полученную строку, а другой добавить в массив "ОТВЕТ".
Для получения результата необходимо закончить ввод текста нажатием на ENTER и Tab. (да, да, это проблема)

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <stdio.h>
 
#define MAXLINE 1000
 
int main(){
    int dltek;
    int k, n;
    char stroka[MAXLINE];
    char rezultat[MAXLINE];
    k = 0;
    while ((dltek = getline(stroka, MAXLINE)) > 0){
            dltek = R_prbl(stroka, dltek);
            addFromTo(stroka, rezultat, k);
            k = k+dltek; // прибавить количество символов текущей строки к результату
    }
        printf("OTBET:\n%s\n vsego simvolov v massive: %d  \n", rezultat, k); // вывод результата
    return 0;
}
 
int getline(char s[], int lim) // захват строки
{
    int c, i;
    for(i=0; i < lim-1 && (c = getchar()) != '\t' && c != '\n'; ++i) // захватывать пока не нажаты по очереди ENTER и Tab
        s[i]=c;
    if (c == '\n'){
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i; // возратить количество элеметов (последний элемент \n компенсирует нулевой элемент)
}
 
int addFromTo(char from[], char to[], int u) // функция добавления массива СТРОКА в массив РЕЗУЛЬТАТ
{
    int i;
    i = 0;
    while ((to[i+u] = from[i]) != '\0'){
        //printf("%c %d\t%c %d\n",to[i+u], i+u, from[i], i);       << ПРОВЕРКА КОДА >>
        ++i;
    }
}
int R_prbl(char arr[], int dl){ // функция редактирования захваченой сроки. удаляются ЛИШНИЕ ПРОБЕЛЫ И СТРОКИ
    
    //ЗАДАЧА 1: Не считать пустую строку (у нее первый элемент массива \n)
                                                                     
    if (arr[0] == '\n') // если первый элемент массива равен "переносу строки"
        return 0;       // вернуть длину текущей строки dltek в main равную 0
        
    //ЗАДАЧА 2: Убрать лишние пробелы
        
    else{
    char tmp[dl]; // создание временного символьного массива
    int i;
    int z;
    z = 0;
    for (i = 0; arr[i] != '\0'; ++i){ // проверк каждого i-того элемента массива arr до конца строки
        if (arr[i] != ' '){ //если текущий элемент НЕ ПРОБЕЛ
            tmp[z] = arr[i]; // присвоить значение элемента временного массива
            ++z; // обязательно прибавить 1 к номеру элемента!
        }
        else if(arr[i+1] != ' '){ // если текущий элемент ПРОБЕЛ, а следующий НЕ ПРОБЕЛ
            tmp[z] = arr[i]; /* так же перенести значение и-того элемента текущей строки в з-тый элемент временной строки
                                даже если i не равно z */
            ++z; // обязательо прибавить 1 к номеру элемента
        }
    }
    tmp[z] = '\0'; //задать конец строки
 
    // Обнуление элементов символьного массива arr
    int o;
    for (o = 0; o <=i; o++){
        arr[o] = '\0';
    }
 
    //Копировать элементы из временного массива tmp в заданный arr
    int j;
    for(j=0; tmp[j] != '\0'; j++){
        arr[j] = tmp[j];
    }
    ++j;
    arr[j] = '\0';
    //printf("Debug: /*\nTMP array:\n%s\nARR array:\n%s\nJ = %d\n*/\n", tmp, arr, j);    << ПРОВЕРКА КОДА >>
    return j-1;
    }
}
меня интересуют такие вопросы по данному коду:
1. Можно ли создать массив ОТВЕТА без ограничений по символам? строка 3,8,9
2. Правильно ли обнулять массив подобным образом (циклом)? строка 71
0
1118 / 931 / 429
Регистрация: 25.12.2016
Сообщений: 3,029
11.12.2017, 09:06 18
1. Можно создать динамический массив (функции malloc/calloc), который при необходимости можно расширять (realloc).

2. Если нужно обнулить именно массив, то всё правильно. Хотя для "обнуления" строки достаточно обнулить первый байт. Другое дело, нужно ли вообще как-то обнулять arr в данном конкретном случае.

Кстати, инкремент в 80 строке является лишним: если условие цикла стало ложным, то индекс j уже и так "указывает" на нулевой байт массива tmp.
1
3 / 3 / 4
Регистрация: 10.12.2017
Сообщений: 6
11.12.2017, 23:50 19
спасибо большое за ответы.
была проблема: печатая например строку получал вывод неправильный, например:
захват:
один_два___три
результат:
один_два_три
р

поэтому я решил обнулять.

Ну а теперь понял, что все дело в цикле. Вы меня просветили)
по итогу строки 69-73 убрал (обнуление массива), изменил последний цикл и все стало работать корректно.
C
1
2
3
4
5
6
7
8
    //Копировать элементы из временного массива tmp в заданный arr
    int j;
    for(j=0; tmp[j] != '\0'; j++){
        arr[j] = tmp[j];
    }
    arr[j] = '\0';
    //printf("Debug: /*\nTMP array:\n%s\nARR array:\n%s\nJ = %d\n*/\n", tmp, arr, j);    << ПРОВЕРКА КОДА >>
    return j;
Но ведь это все-равно не верное решение, ведь массив tmp висит в памяти. Вернее будет что б все массивы были динамические, ну и после выполнения своей функции их необходимо стирать?
0
1118 / 931 / 429
Регистрация: 25.12.2016
Сообщений: 3,029
12.12.2017, 09:20 20
Цитата Сообщение от lvadimkal Посмотреть сообщение
Но ведь это все-равно не верное решение, ведь массив tmp висит в памяти.
Не висит.
tmp - это локальный массив, поэтому после завершения функции он будет автоматически уничтожен
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.12.2017, 09:20

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Компилятор С(Керниган ,Ритчи)
Здравствуйте! Открыл книгу Брайана Кернигана и Денниса Ритчи. Первое задание MAIN()...

Керниган Ритчи Упражнение 2.2
Добрый день. Помогите начинающему разобраться пожалуйста. Само задание я решил, но...

Керниган, Ритчи, указатели и упражнение 5.3
Добрый день! &quot;Напишите свою версию функции strcat, ... с применением указателей.&quot; void...

Не запускается прога из Керниган и Ритчи
программа-калькулятор #include &lt;conio.h&gt; #include &lt;math.h&gt; #include &lt;stdio.h&gt; #define...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.