LINUX.ORG.RU

Помогить отладить маленькую программку (segmentation fault)


0

0

Только-только начал изучать C по одной книжке, вот там задание такое: написать программу, которая считывает длину квадрата и любой символ, и передает их функции, рисующей на экране квадрат с введенной стороной из указанных символов. В C со строками вроде нужно работать не как с обычными переменными, а как-то хитро, в общем не могу понять... Появляется Segmentation fault после ввода символа.

#include <stdio.h>

void draw(int,char);

main()
{
	int side;
	char chars;
	while (1 == 1) {
		printf("Side, 0 to exit: ");
		scanf("%d", &side);
		if (side == 0)
			return 0;
		printf("Character: ");
		scanf("%s", chars);
		draw(side, chars);
	}
	return 0;
}

void draw(int side, char fillCharacter)
{
	int a, b;

	for (a=1; a<=side; a++){
		for (b=1; b<=side; b++)
			printf("%s", fillCharacter);
		printf("\n");
	}
}
anonymous

Вместо:
scanf("%s", chars);
надо:
scanf("\n%c", &chars);
\n - это маленький хак из-за особенностей scanf.

Вместо:
printf("%s", fillCharacter);
надо:
printf("%c", fillCharacter);

Rock
()

Очевидно!

char chars;
.
.
.
scanf("%s", chars);

во-первых scanf("%s", &chars);во-вторых если хочешь считывать строку то объяви массив char chars[xxx](напрмер 256), или же с помощью оператора malloc:
char* chars;

chars = (char*)malloc(num);, где num число байтов которое ты хочешь выделить.
scanf("%s", chars); в этом случае в сканфе пишится chars без &.

Если хочешь считать один символ, то у тебя всё правильно за исключением:
scanf("%c", &chars);

void draw(int side, char* fillCharacter) - так правильно, если хочешь передавать строку в функцию.

соответственно вызов этой функции должен выглядеть так: draw(side, &chars);(естественно если ты используешь malloc для выделения памяти массиву chars, то у тебя написан вызов функции правильно).

ЗЫ Моё ИМХО: даже начиная изучать C, уже можно протрассировать прогу и
найти ошибки в ней......




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

На самом деле, scanf - одна из самых дурацких функций C. Применяется только в школе, да на лабах в институте :) Если надо читать символ, то, как правило - getchar, если строку - fgets (но не gets!). А если уж совсем для пользователя удобно надо сделать - readline.

> во-вторых если хочешь считывать строку то объяви массив char chars[xxx](напрмер 256), или же с помощью оператора malloc

А что сделает scanf, если я вбабахаю ей на вход пару килобайт текста?

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

> А что сделает scanf, если я вбабахаю ей на вход пару килобайт текста?

Ответ : буферизует ее :-)

А кто сказал что scanf читает только одну строку или всю
строку до конца?
Рекомендую попробовать на кошках:
main(){
int i,j;
scanf("%d", &i);
scanf("%d", &j);
printf("%d - %d\n", i, j);
}
i и j могут быть в одной строке с мусором далее, могут быть в разных.

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

>На самом деле, scanf - одна из самых дурацких функций C.
>Применяется только в школе, да на лабах в институте :

Спасибо за науку, буду иметь в виду. Просто когда писалась та книжка, по которой я C изучаю, линукса еще в проекте не было :) Да и меня тоже :) И не потому, что я такой молодой ;)

>ЗЫ Моё ИМХО: даже начиная изучать C, уже можно
>протрассировать прогу и найти ошибки в ней......

А как, можно узнать? Я ведь раньше "программировал" только в маздае, а на каком языке даже не скажу - стыдно ;) Так там удобно было - можно было ставить точки останова, узнавать значения переменных во время работы программы, прерывать ее выполнение в любой момент и т.п. А такое можно сделать в линуксе?

PS а программа заработала :)

anonymous
()
Ответ на: комментарий от io

> А кто сказал что scanf читает только одну строку или всю строку до конца?

Я сделаю так, что прочитает. И запишет. Если в той паре килобайт текста не будет пробелов, переводов строки, табуляций?, ...?, то scanf как миленькая запишет весь этот хлам любой длины в буфер, переданный спецификатору %s.

Твой пример не очень удачен. %d, %f, %c, ... использовать достаточно безопасно - их результат имеет фиксированную, известную на этапе компиляции длину. А вот с %s сложнее. Длина результата заранее неизвестна, а scanf не позволяет указать ограничение на неё и не занимается сама выделением памяти нужного размера под результат. Посмотри для сравнения на gets и fgets и подумай, почему gets считается небезопасной, а fgets - безопасной, если писать правильно.

Rock
()
Ответ на: комментарий от anonymous

>А как, можно узнать? Я ведь раньше "программировал" только в маздае, а на каком языке даже не скажу - стыдно ;) Так там удобно было - можно было ставить точки останова, узнавать значения переменных во время работы программы, прерывать ее выполнение в любой момент и т.п. А такое можно сделать в линуксе?


Программил ты наверное на Visual Basic'е. Смеятся не буду, сам(когда-то давно-давно, хотя я ни такой и старый:)) начинал с него. Потом был VC++.И только потом перешел на Линукс и программлю теперь уже на С, использую компилятор gcc. Вообще ничего стыдного в этом нету, все мы когда-то с чего-то начинали.
Ладно это было лирическое отступление.

А отлаживать проги в Линуксе можно с помощью gdb. Трудно сказать чего НЕ
умеет эта прога. Почитай доки, маны по этой проге и заценишь её...

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

OK, спасибо, поискал, нашел доку.

Кстати, когда у меня была Mandrake 9.0, там в домашнем каталоге (или где-то еще, не помню точно), после падения прог создавались файлы *.core. А в Slackware 9.1 я таких файлов чего-то не вижу. Может, их создание отключено?

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

Да отключено по-умолчанию сделай ulimit -sC 10000000.

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