LINUX.ORG.RU

Керниган-Ричи, задание 1.16


0

0

Собственно вопрос в том, как решить предложенную в "Язык программирования С" (Издание 2е,по всей видимости) задачку:

Предыстория (копипаст из книги). Чтобы проиллюстрировать использование символьных массивов и работающих с ними функций, напишем программу, которая читает набор текстовых строк и печатает самую длинную из них.
Решение, предложенное в книге :

#include <stdio.h>
#define MAXLINE 1000 /* максимальный размер вводимой строки */

int getline(char line[], int MAXLINE);
void copy(char to[], char from[]);

/* печать самой длинной строки */
main()
{
int len; /* длина текущей строки */
int max; /* длина максимальной из просмотренных строк */
char line[MAXLINE]; /* текущая строка */
char longest[MAXLINE]; /* самая длинная строка */

max = 0;
while (len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* была ли хоть одна строка? */
printf(“%s”, longest);
return 0;
}


/* getline: читает строку в s, возвращает длину */
int getline(char s[], int lim)
{
int c, i;

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

/* copy: копирует из 'from' в 'to'; to достаточно большой */
void copy(char to[], char from[])
{
int i;

i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}

А теперь собственно задание:
Перепишите main предыдущей программы так, чтобы она могла печатать самую длинную строку без каких-либо ограничений на ее размер.
Главная особенность заключается в том, что
1. в рамках первой главы ничего неизвестно о динамическом выделении памяти;
2. в условии требуется менять main, т.е. функции copy и getline менять нельзя


Если самую длинную строку требуется вывести в конце целиком, то без динамического выделения памяти и "каких-либо" ограничений на максимальную длину строки решить задачу нельзя. Если нет необходимости хранить строку, то можно считывать ее кусками, проверяя наличие '\n' в конце.

mannaz
()

Без ограничений длины это можно сделать только с файлами: за первый проход ищется позиция очередного \n и из разницы с предыдущей вычисляется длина строки, максимальную длину строки и позицию ее начала в файле сохраняем в переменных; за второй проход распечатываем эту строку (посимвольно или блочно).

В принципе, здесь функции copy и getline не нужны. Но все равно получится не то, что надо - т.к. с stdin такого не получится.

Eddy_Em ☆☆☆☆☆
()

М-м-м... Последовательно вызываем getline(), пока не прочитаем '\n', в качестве буфера для текущей и максимальной строки используем два временных файла? Других вариантов без динамического выделения в голову не приходит.

kemm
()

В том виде, в котором ты написал - задача не выполнима без динамической памяти. Но походу тут кривой перевод, т.к. в английском варианте задача звучит иначе:

Exercise 1-16. Revise the main routine of the longest-line program so it will correctly print the length of arbitrary long input lines, and as much as possible of the text.

Т.е. нам надо напечатать длину и какой-то кусок (не весь!) текста. Как-то так:

main()
{
	int len; /* ????? ??????? ?????? */
	int max; /* ????? ???????????? ?? ????????????? ????? */
	int tmp;
	int continue;
	char line[MAXLINE]; /* ??????? ?????? */
	char longest[MAXLINE]; /* ????? ??????? ?????? */

	max = 0;
	len = 0;
	while ((tmp = getline(line, MAXLINE)) > 0) {
		len += tmp;
		if (len > max) {
			max = len;
			if (!continue) {
				copy(longest, line);
			}
		}

		if (tmp != MAXLINE) {
			len = 0;
			continue = 0;
		} else {
			continue = 1;
		}
	}
	
	if (max > 0) /* ???? ?? ???? ???? ??????? */
		printf(“%i %s”, max, longest);
		
	return 0;
} 

В итоге мы правильно напечатаем размер самой длинной строки и содержимое буфера с её началом. На работе нечем скомпилировать Сишный код, так что на мелкие ошибки не проверял.

shuthdar ★★★
()
Ответ на: комментарий от shuthdar

main()
{
int len; /* ????? ??????? ?????? */
int max; /* ????? ???????????? ?? ????????????? ????? */
int tmp;
int continue;
char line[MAXLINE]; /* ??????? ?????? */
char longest[MAXLINE]; /* ????? ??????? ?????? */

max = 0;
len = 0;
while ((tmp = getline(line, MAXLINE)) > 0) {
len += tmp;
if (len > max) {
max = len;
if (!continue) {
copy(longest, line);
}
}

if (tmp != MAXLINE) {
len = 0;
continue = 0;
} else {
continue = 1;
}
}

if (max > 0) /* ???? ?? ???? ???? ??????? */
printf(“%s”, longest);

return 0;
}

shuthdar ★★★
()
Ответ на: комментарий от shuthdar

И таки да, лучше наверное проверять на line[tmp-1] == '\n', чтобы надёжней определить, продолжается строка или будет следующая.

shuthdar ★★★
()
Ответ на: комментарий от K-Vrat

>Спасибо, наверно прежде, чем заводить разговор, надо было открыть оригинал задания..

такие мысли обычно вообще не приходят в голову :).

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.