Member 13013165 Ответов: 2

Почему программа на языке Си дает такие результаты?


Когда я вызываю следующую функцию, только 2-й printf будет печатать ожидаемый результат, в то время как первый printf будет печатать только символ (не обязательно связанный с начальной строкой). Однако, если я комментирую утверждения, относящиеся к *s2, довольно странно, что первый printf дает мне требуемый вывод.

Например:
char a []= " Привет, мир";
char b []= " меня зовут Джон";
вызов afunction(a, b) приведет к чему-то вроде этого:
н
меня зовут Джон

но комментирование полей, относящихся к *s2, даст:
всем привет

Почему, черт возьми? Спасибо.

Что я уже пробовал:

int afunction(char *s1, char *s2){
	char *a,*b,*c,*d;
	c=a;
	d=b;
	while (*s1!='\0'){
		*a++=tolower(*s1++);
	}
	*a='\0';
	
	while (*s2!='\0'){
		*b++=tolower(*s2);
		s2++;
	}
	*b='\0';	
	printf("%s\n",c);
	printf("%s\n",d);
	return 0;
}

PIEBALDconsult

Потому что ты так сказал.
Я удивлен, что вы не попали в аварию, что я и получаю (и ожидаю).
Что вы на самом деле пытаетесь сделать?

Graeme_Grant

Самый простой способ запомнить ... указатели должны указывать на что-то. ;)

PIEBALDconsult

И они всегда так делают...

Graeme_Grant

;)

2 Ответов

Рейтинг:
8

Patrice T

Вы забыли инициализировать *a и *b в место, где можно найти строчные строки.
Результат зависит от компилятора и может быть где угодно-от правильных результатов, частичных результатов до сбоя или ошибки сегмента.

Когда вы не понимаете, что делает ваш код или почему он делает то, что делает, ответ таков: отладчик.
Используйте отладчик, чтобы увидеть, что делает ваш код. Просто установите точку останова и посмотрите, как работает ваш код, отладчик позволяет вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения, это невероятный инструмент обучения.

Отладчик-Википедия, свободная энциклопедия[^]
Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]

Отладчик здесь для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.
В отладчике нет никакой магии, он не находит ошибок, он просто помогает вам. Когда код не делает того, что ожидается, вы близки к ошибке.


Рейтинг:
19

leon de boer

Это несколько забавных строк кода .. ты забываешь, как непонятны вещи для начинающих :-)

Ладно, большой совет, вам действительно не нужны a, b, c и d, и у вас уже есть s1 и s2, то есть шесть указателей. Вы заблудились в сложности сдвига, которую сами же и создали, имея так много указателей. Часть вашего обучения кодированию состоит в том, чтобы свести проблему к абсолютному минимуму.

Итак, ваша проблема заключается в первых 3 строках внутри функции

char *a,*b,*c,*d;   // You define 4 pointers they don't point anywhere and are just junk so far
c=a;  // here you set c to have the same junk value as a
d=b;  // here you set d to have the same junk value as b

Итак, все остальные говорят вам, что вы, возможно, захотите указать где-то точки А и в ... вероятно, значения s1 и s2, и это возвращает нас к проблеме ... почему так много указателей.

Я предполагаю, что вам нужен только 1 дополнительный указатель, который является временным, по которому вы двигаетесь. Вы устанавливаете его на s1, перемещаете его вперед, выполняя преобразование вашего дела по ходу дела. Затем вы устанавливаете его в положение s2, перемещая его вперед, выполняя преобразование падежа для каждого символа по ходу движения. Затем вы показываете s1 и s2 и выполняете работу. Я не уверен, что вы хотите перемещать s1 и s2, которые являются указателем на ваши фактические текстовые буферы, и вы теряете их, и вы мертвы в воде.


PIEBALDconsult

Ну, он даже не уточнил, хочет ли он делать на месте нижнюю обшивку или нет.

leon de boer

Он в основном должен быть на месте, потому что у него нет доступа ни к чему другому, если вы не позволите чистую глупость и не собираетесь установить указатель на глобальный. Можно было бы надеяться, что они все еще учат, что установка указателя char* на Глобал не только опасна, но и на самом деле глупа и безрассудна. Вы были бы уволены за это в моей компании, поскольку это базовая безопасность указателя 101, потому что поставить дополнительный указатель на интерфейс для вывода очень сложно.

Так что я думаю, если мы последуем вашему примеру, он делает все это неправильно, он должен иметь s1 и s2 в качестве глобалов, черт возьми, кому нужен локальный интерфейс, это просто пустая трата времени, и мы в конечном итоге напишем что-то похожее на GW Basic :-)

PIEBALDconsult

Правильно, так что если он не пытается сделать это на месте, мы должны знать, а он не ответил.

leon de boer

Если он не делает этого на месте, ему нужно изменить свой интерфейс, чтобы он не совершил преступления против человечества.

int afunction(char *s1, char *s2, char* outbuf)
ОПЕРАЦИОННАЯ
int afunction(char *s1, char *s2, char* outs1, char* outs2)

Тогда ему все еще не нужно количество указателей, которые у него есть, потому что интерфейс определяет 4, и ему все еще нужно только 1 внутри функции, чтобы перемещаться как его временный (я бы принял два для новичка). В этом весь смысл локального интерфейса он заставляет его устанавливать указатели или он не будет компилироваться и его здесь не будет :-)

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

Member 13013165

Только что с работы. Итак, я на самом деле пытался выполнить упражнение K&R 5.15 и хочу написать функцию, чтобы сложить символы перед их strcmp. Отсюда и неуклюжий код. Овации. Сначала я приму душ и вернусь.