Начинаю осваивать C, появляются вопросы...

Модератор: Модераторы разделов

Аватара пользователя
devilr
Сообщения: 3665
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: Начинаю осваивать C, появляются вопросы...

Сообщение devilr »

QWERTYASDF писала:
23.09.2018 13:21
Да меня то устраивает. Просто, насколько сейчас понимаю, "пустую строку" можно трактовать по-разному. Или я ошибаюсь и все однозначно. В этом и вопрос.
Пустая строка - вполне однозначное понятие. Главное - не путать её с НЕинициализированным указателем. Т.е.
char *temp;
ещё не строка и обращение к неё к ничему хорошему не примедёт.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Начинаю осваивать C, появляются вопросы...

Сообщение Bizdelnick »

QWERTYASDF писала:
23.09.2018 13:21
Просто, насколько сейчас понимаю, "пустую строку" можно трактовать по-разному. Или я ошибаюсь и все однозначно.
Очевидно, в данном контексте речь идёт о line, а не string. Потому что входной поток можно разделить на строки, которые line, в то время как string — понятие, относящееся к внутреннему хозяйству программы. В конце концов, можно найти английскую версию книги, и уточнить.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
s.xbatob
Сообщения: 1139
ОС: Fedora

Re: Начинаю осваивать C, появляются вопросы...

Сообщение s.xbatob »

Нет ничего ни в начале, ни в конце! Да, в конструкции типа int c = "string" добавляется в конце нулевой байт, только за этим никакой мистики нет. Более того, в строке "какая-то кириллица" тоже нет мистики -- это набор байт, которые нынче совсем не то, что символы, и они никак не интерпретируются. Нет встроенного механизма преобразования строк!
Спасибо сказали:
QWERTYASDF
Сообщения: 989
Статус: Чайник со свистком
ОС: GNU/Linux

Re: Начинаю осваивать C, появляются вопросы...

Сообщение QWERTYASDF »

Спасибо. Ну, как понимаю - пустая строка - значит, содержащая ничего. Т.е. место внутри "буфера"/"входного потока", в котором ничего нет. Ну тогда программа написана верно, разобрались.
Спасибо сказали:
Аватара пользователя
bormant
Сообщения: 1354

Re: Начинаю осваивать C, появляются вопросы...

Сообщение bormant »

В 1.18 задание такое:
Write a program to remove all trailing blanks and tabs from each line of input, and to delete entirely blank lines.
соответственно, речь о строках файла, а не строках в смысле языка Си. Строки в файле разделены '\n' (по крайней мере в *nix-like системах). Поэтому пустая строка в этом задании -- всякая строка файла, в которой нет ничего кроме пробелов и табуляций.
'\n' -- это разделитель строк, он не рассматривается как часть строки файла.
'\0' -- это признак конца строки в памяти для строковых функций, работающих с ASCIIZ. С точки зрения логической строки, он не является ее частью, но с точки зрения размещения в памяти -- это часть буфера, требующая своего места. Т.е. "string" -- это 's','t','r','i','n','g','\0' -- 7 char-ов в памяти, но strlen("string") даст 6.

Алгоритм решения простой -- накапливаем в буфер идущие подряд ' ' и '\t', как только получаем непробельный символ (и не '\n'), сбрасываем буфер, затем символ, взводим флаг, что строка уже не пуста. По получении '\n' пишем его только если взведен флаг, что строка не пуста, сбрасываем флаг пустоты строки. Повторяем, пока не кончится входной поток.
Спасибо сказали:
QWERTYASDF
Сообщения: 989
Статус: Чайник со свистком
ОС: GNU/Linux

Re: Начинаю осваивать C, появляются вопросы...

Сообщение QWERTYASDF »

bormant писал(а):
23.09.2018 16:28
В 1.18 задание такое:
Write a program to remove all trailing blanks and tabs from each line of input, and to delete entirely blank lines.
соответственно, речь о строках файла, а не строках в смысле языка Си. Строки в файле разделены '\n' (по крайней мере в *nix-like системах). Поэтому пустая строка в этом задании -- всякая строка файла, в которой нет ничего кроме пробелов и табуляций.
'\n' -- это разделитель строк, он не рассматривается как часть строки файла.
'\0' -- это признак конца строки в памяти для строковых функций, работающих с ASCIIZ. С точки зрения логической строки, он не является ее частью, но с точки зрения размещения в памяти -- это часть буфера, требующая своего места. Т.е. "string" -- это 's','t','r','i','n','g','\0' -- 7 char-ов в памяти, но strlen("string") даст 6.

Алгоритм решения простой -- накапливаем в буфер идущие подряд ' ' и '\t', как только получаем непробельный символ (и не '\n'), сбрасываем буфер, затем символ, взводим флаг, что строка уже не пуста. По получении '\n' пишем его только если взведен флаг, что строка не пуста, сбрасываем флаг пустоты строки. Повторяем, пока не кончится входной поток.
Спасибо.

Нет ничего кроме пробелов и табуляций - или, нет вообще ничего т.е. "\n\n" (?)

Ну примерно так у меня и сделано.

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

/* Упражнение 1.18 из учебника K&R.
 * Программа должна удалять лишние пробелы и табуляции на хвосте каждой строки входного потока.
 * Также, программа должна удалять пустые строки.
*/

#include <stdio.h>
#define MAXLINE 1000	/* максимальная длина строки в потоке с учетом того, что максимальное число печатных символов будет MAXLINE-2 (предпоследний - '\n' и последний '\0' ; или последний - '\0') */

int mygetline(char line[], int maxline);

int main()
{
   int spch = 0;		//счетчик символов табуляций или пробелов
   int len = 0;			//длина текущей строки
   int i;
   char line[MAXLINE];		//текущая введенная строка

   while ((len = mygetline(line, MAXLINE)) > 0) {
      for (i=0 ; i < len-1; ++i) {
         if (line[i] != ' ' && line[i] != '\t') {
	    spch = 0;
	 }
	 else
	 {
	    ++spch;
	 }
       }
   
   if (spch > 0 && ((line[len-1] == '\t' || line[len-1] == ' ') || (line[len-1] == '\n' && (line[len-2] == ' ' || line[len-2] == '\t')))) {
      for (i=0; i<=(len-(spch+2)); ++i) {
         putchar(line[i]);
      }
      printf ("\n");
   }
   else {
      if (line[len-1] == '\n') 
          printf("%s", line);
       else   			//если длина вх. строки выше лимита - корректное отображение, с \n на конце.
          printf("%s\n", line);
   }
   
   }
   return 0;
}

/* mygetline: считывает строку в s, возвращает ее длину */
int mygetline(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;
	++i;
    }
    s[i] = '\0';
    return i;
}

Спасибо сказали:
Аватара пользователя
bormant
Сообщения: 1354

Re: Начинаю осваивать C, появляются вопросы...

Сообщение bormant »

Нет ничего, кроме пробелов и табуляций.

При выбранном вами варианте строка ограничена MAXLINE. Но если буфер использовать только для пробелов/табов, то ограничено будет только количество непрерывных пробелов/табов.

С буфером на целую строку решение тривиальное: читаем до \n, идем по строке с конца пока там пустые символы, при первом непустом пишем за ним \0, если осталось что-то, выводим printf("%s\n",line);
Спасибо сказали:
Ответить