Перейти к содержимому


Фото

Си. Ввод и кроссплатформенность


  • Чтобы отвечать, сперва войдите на форум
10 ответов в теме

#1 Денис Опубликовано 25 Октябрь 2009 - 14:09

Денис
  • Genius loci
  • 6 898 Сообщений:
  • Денис Сумин
Возник у меня вопрос.
Пишу машзальное задание на Си, все вроде просто и понятно.
Надо реализовать программу, которая берет на вход строки, сортирует их, выводит. Потом спрашивает, не хочет ли пользователь еще один набор строк отсортировать.

Получается что-то вроде (можно пропустить, интересное ниже ;)):
int main() {	
	list *p, *temp; char* q; char c;
		
	p = malloc(sizeof(list)); // создали заглавное звено списка
	p->next = NULL;	
				
	temp = malloc(sizeof(list));	
	while (input(temp)!=EOF) { // вводим
		find_place(p, temp); // находим место для элемента
		temp = malloc(sizeof(list));
	}
	free(temp);	
	output(p); // выводим
	free_all(p); // чистим память

// вот здесь спрашиваем пользователя и ждем ответа в виде <y=Да> или <что-либо еще=Нет>
// clearerr(stdin) надо поставить сюда
	printf("Do you want to sort a new list (y/N)?\n");
	q = malloc(3*sizeof(char));
	fgets(q, 3, stdin);
	if ((q[0]=='y' || q[0]=='Y') && (q[1]=='\n' || q[1]=='\r')) main();
	free(q);
	
	return 0;
}

Так вот, на мой взгляд, код простой и вообще. Под убунтой работает прекрасно.
Идем во FreeBsd (в МЗ именно они). Все работает правильно, запрос на повторный запуск не работает.
Смотрим, что пишет поток: там появляются код символов "-80", "-64", "-128", "4" и т. д. Что это значит, пока не понял.
Проблема решается с помощью clearerr(stdin):

The function clearerr() clears the end-of-file and error indicators for the stream pointed to by stream.


Вопрос: чем успевает засориться stdin и является ли clearerr() достаточно кроссплатформенной, чтобы ее использовать везде? Почему под убунтой clearerr() не нужен, а во фри нужен, где разница между системами?

#2 KiberGus Опубликовано 25 Октябрь 2009 - 16:40

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов
А как выглядит функция input? P.S. Рекурсивный вызов main интересное решение. Лучше организовать цикл т.к. в таком виде в твоей программе присутсвует утечка памяти. На каждой итерации ты залезаешь все глубже в рекурсию и уже не нужные, почти отработавшие экземпляры main оседают в стеке. P.P.S. man clearerr: CONFORMING TO The functions clearerr(), feof(), and ferror() conform to C89 and C99.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#3 Денис Опубликовано 25 Октябрь 2009 - 17:23

Денис
  • Genius loci
  • 6 898 Сообщений:
  • Денис Сумин
#define n 5

int input (list *temp) {
	int i, j;
	
	i = 0;	
	temp->s = malloc (n*sizeof(char));
	temp->next = NULL;
	
	fgets(temp->s, n, stdin);
		
	while(temp->s[0]!='\0') {	
		j = (i+1)*(n-1);	
		while (temp->s[j] != '\n' && j>=0) { j--; }
		if (temp->s[j]=='\n') { temp->s[j] = '\0'; break; }
		 else {
			temp->s = realloc(temp->s, (i+2)*(n-1)*sizeof(char)+1);
			fgets((temp->s+(i+1)*(n-1)), n, stdin);
			i++;
		}
	}				
	if(temp->s[0]=='\0') return EOF;
	 else return 0;
}

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

Про рекурсивный main — ага тоже думал, исправлю.

Я правильно понимаю, что с89 и с99 — стандарты Си 89го и 99го годов?

#4 KiberGus Опубликовано 26 Октябрь 2009 - 15:16

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов
Попробуй воспользоваться функций fcntl и посмотреть какие флаги установлены в обеих системах. Вобзможно у тебя по какой-то причине происходит неблокирующее чтение. Что такое "-80", "-64" и "-128" я не знаю, а вот "4" - это Ctrl+D или конец ввода файла. P.S. Это в паскале надо было извращаться с побайтовым вводом т.к. Вирт сделал в нем ну очень убогий ввод/вывод. В С есть куда более удобные функции, например fscanf. А еще для facanf есть замечательный, пока еще нестандартный модификатор m (ожидается в POSIX.1), считывающий строку и сам отводящий под нее буфер. c89 и c99 это стандарты 89 и 99 года.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#5 Syrano Опубликовано 26 Октябрь 2009 - 15:19

Syrano
  • Свои
  • 9 630 Сообщений:
  • Владимир Зайцев

В С есть куда более удобные функции, например fscanf.

Это опасная функция.

С нами сила Алхазашвили!


#6 Денис Опубликовано 26 Октябрь 2009 - 15:52

Денис
  • Genius loci
  • 6 898 Сообщений:
  • Денис Сумин

Попробуй воспользоваться функций fcntl и посмотреть какие флаги установлены в обеих системах. Вобзможно у тебя по какой-то причине происходит неблокирующее чтение. Что такое "-80", "-64" и "-128" я не знаю, а вот "4" - это Ctrl+D или конец ввода файла.

Ага, попробую. А блокирующее/неблокирующее чтение это что?

Это опасная функция.

А чем опасная?

#7 Syrano Опубликовано 26 Октябрь 2009 - 15:59

Syrano
  • Свои
  • 9 630 Сообщений:
  • Владимир Зайцев

Ага, попробую. А блокирующее/неблокирующее чтение это что?

Блокирующее: выход из функции чтения происходит по окончанию ввода или по заполнении буфера. Пока что-то из этого не случилось -- висим и ждем.
Неблокирующее: сколько чего было в буфере -- скопировали тебе в возвращаемое значение и вывалились.

А чем опасная?

Размер отведенной строки нигде не передается. Легко может быть переполнение. И отследить/предотвратить этого нельзя.

С нами сила Алхазашвили!


#8 Денис Опубликовано 26 Октябрь 2009 - 16:25

Денис
  • Genius loci
  • 6 898 Сообщений:
  • Денис Сумин
Ясно, спасибо!

#9 KiberGus Опубликовано 04 Ноябрь 2009 - 9:46

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов

Размер отведенной строки нигде не передается. Легко может быть переполнение. И отследить/предотвратить этого нельзя.

Я поэтому и сказал про расширения. %m не только вводит строку, но и сама заботится о выделении памяти под нее. Поэтому эта функция безопасная.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#10 Syrano Опубликовано 04 Ноябрь 2009 - 10:50

Syrano
  • Свои
  • 9 630 Сообщений:
  • Владимир Зайцев
Леш, я видел, что ты написал. Только тут-то разговор про стандарты идет...

С нами сила Алхазашвили!


#11 GrGr Опубликовано 09 Ноябрь 2009 - 12:41

GrGr
  • Свои
  • 2 280 Сообщений:
  • Григорий Григорьев
Мне вот только непонятно, почему нельзя использовать scanf с параметром %c? Считываем из буфера один символ и радуемся жизни.
А потом пришел злобный Гр и все опошлил...




1 пользователей читают эту тему

0 пользователей, 1 гостей, 0 невидимых