#c
#c
Вопрос:
Не удается заставить ни один из операторов if запускать и печатать что-либо в main. Я не понимаю, что делать дальше.
Не могли бы вы найти, где я ошибся в этой проблеме. Мне нужно подсчитать количество точек и тире (я упростил это, чтобы сначала работать с точками).
Вопрос должен быть решен с использованием арифметики указателей, и функция была предоставлена
void analyse(char* code, int* p_dots, int* p_dashes);
^
#include <stdio.h>
#include <string.h>
void analyse(char* code, int* p_dots)
{
char *current = code;
int k = 0;
if ((*current k) == '.')
{
p_dots ;
k ;
}
if ((*current k) == '-')
{
//p_dashes ;
k ;
}
if ((*current k) ==' ')
{
//p_dashes ;
k ;
}
}
int main(void)
{
char* morse[] =
{
"... --- ..." // SOS
// "-- --- .-. ... .", // MORSE
// "-.-. --- -.. .", // CODE
// "-.-. --- -- .--. ..... ----- -----", // COMP500
// ". -. ... . ..... ----- .----" // ENSE501
};
char* code = *morse;
int*p_dots=0;
//int*p_dashes = 0;
analyse(code, p_dots);
printf("Line 1 has %d dots", *p_dots);
return 0;
}
Комментарии:
1. Вы в курсе
*current k
(*current) k
, не*(current k)
так ли?2. Нет, я видел кое-что об этом на слайдах лекции и не был уверен, что это значит.
3. Использование
[]
-operator является самым простым (и при этом безопасным) подходом для доступа к элементу массива.4. не используйте
k
ниcurrent
то, ни другое, просто сделайте*code
5. «Арифметика указателей» — это нечто другое — это не означает «считать с помощью указателя». И если есть ограничения на то, что вы можете сделать, пожалуйста, укажите это в вопросе.
Ответ №1:
Вот другой подход:
#include <stdio.h>
void analyse(char *code, int *p_dots, int *p_dashes)
{
for( ; *code ; code)
{
if (*code == '.')
*p_dots = 1;
if (*code == '-')
*p_dashes = 1;
}
}
int main(void)
{
int dots;
int dashes;
char *morse[] =
{
"... --- ...", // SOS
"-- --- .-. ... .", // MORSE
"-.-. --- -.. .", // CODE
"-.-. --- -- .--. ..... ----- -----", // COMP500
". -. ... . ..... ----- .----" // ENSE501
};
for(int i = 0 ; i < sizeof(morse) / sizeof(char *) ; i)
{
dots = 0;
dashes = 0;
analyse(morse[i], amp;dots, amp;dashes);
printf("Line %d ('%s') has %d dots and %d dashesn", i, morse[i], dots, dashes);
}
return 0;
}
Указатель — это переменная, которая содержит адрес чего-либо. Используя указатель, вы можете посмотреть и / или изменить то, на что он указывает. Если вы увеличиваете указатель, вы меняете адрес в указателе, и, таким образом, вы меняете то, на что он указывает.
В этом коде вся арифметика указателей выполняется в for
цикле for( ; *code ; code)
в analyse
функции. Здесь мы говорим о том, что А) нет раздела инициализации (перед первым ;
в инструкции нет кода for
); Б) мы хотим продолжать до тех пор, пока то, что указано на code
указатель, не равно нулю *code
в «тестовой» части for
инструкции; и В)после каждого прохождения цикла мы хотим увеличивать code
указатель ( code
в разделе «increment» for
инструкции).
Если бы вы хотели, вы могли бы заменить for
цикл на analyse
:
while(*code <> 0)
{
if (*code == '.')
*p_dots = 1;
if (*code == '-')
*p_dashes = 1;
code = 1;
}
При просмотре подобного кода я считаю полезным мысленно произносить «объект указателя» всякий раз, когда я вижу звездочку, используемую с переменной указателя, поэтому я бы прочитал первую строку приведенного выше кода как
While object of pointer "code" is not equal to zero...
затем следующие строки читаются как
if object of pointer "code" is equal to the character "period"
then add one to object of pointer "p_dots"
if object of pointer "code" is equal to the character "dash"
then add one to object of pointer "p_dashes"
add one to the variable "code"
Вместо «объекта указателя», возможно, вы могли бы прочитать его как «цель указателя», чтобы напомнить себе, что указатель указывает на что-то, и вы манипулируете тем, на что указывает указатель, или, другими словами, вы манипулируете указателями «target».
Я считаю, что подобные вещи помогают мне немного лучше понимать код на основе указателей. Возможно, это вам тоже поможет.
Комментарии:
1. Спасибо, это немного прояснило ситуацию. Но теперь я не уверен, как мне включить строки, которые я закомментировал. Поскольку указатель увеличивается, как я смогу заставить его остановиться в конце строки и снова перезапустить счетчик?
2. В сторону:
sizeof(morse) / sizeof(char *)
—>sizeof morse / sizeof morse[0]
менее хрупкий.3. @UltraInstinctMessi — вы должны сделать то, что я сделал в моем примере кода — вы увеличиваете указатель только после того, как выполнили все необходимые тесты для каждого отдельного символа.
4. @UltraInstinctMessi — Я добавил немного больше объяснений того, как я читаю код, который использует указатели и манипулирует ими. Возможно, это поможет.
Ответ №2:
Измените все вхождения этого:
(*current k) == '-'
к этому:
*(current k) == '-'
(что означает то же самое, что и следующее:)
current[k] = '-'
Также в main()
вашем коде необходимо обновить значение an int
, поэтому просто создайте обычный int
, а затем передайте его адрес:
int p_dots = 0;
...
analyse(code, amp;p_dots);//sends the address so the value can be updated
Кроме того, для правильного суммирования всех значений в функции void analyse(char* code, int* p_dots)
analyze необходим цикл while: ниже приведен ваш код с циклом while и некоторыми упрощениями: (он только отслеживает p_dots
)
void analyse(char* code, int* p_dots)
{
char *current = code;
int k = 0;
while(*current)//check for NULL character
{
if (*current == '.')
{
(*p_dots) ;
}
if (*current == '-')
{
k ;
}
if (*current ==' ')
{
k ;
}
current ; //increment pointer to next position
}
}
Кстати, один из способов отслеживать каждый из символов ( .
, -
.
) — это создать структуру, а затем передать ее адрес для обновления значений элементов. Пример кода для этого приведен ниже:
typedef struct {
int dot;
int dash;
int space;
} count_s;
void analyse(char* code, count_s *c)//new prototype to track `.`, `-` and ` `
{
char *current = code;
int k = 0;
while(*current)
{
if (*current == '.')
{
(*c).dot ;
}
if (*current == '-')
{
(*c).dash ;
}
if (*current ==' ')
{
(*c).space ;
}
current ;
}
}
int main(void)
{
char* morse[] =
{
"... --- ..." // SOS
// "-- --- .-. ... .", // MORSE
// "-.-. --- -.. .", // CODE
// "-.-. --- -- .--. ..... ----- -----", // COMP500
// ". -. ... . ..... ----- .----" // ENSE501
};
char* code = *morse;
//int p_dots;
count_s count;
//int*p_dashes = 0;
analyse(code, amp;count);
printf("Line 1 has %d dotsn", count.dot);
printf("Line 1 has %d dashesn", count.dash);
printf("Line 1 has %d spacesn", count.space);
return 0;
}
ОТРЕДАКТИРУЙТЕ, чтобы ответить на вопрос в комментариях: Как бы мне сделать это для следующих строк, которые я закомментировал?
Создайте массив строковых литералов
const char *morse[] = {{"... --- ..."},
{"-- --- .-. ... ."},
{"-.-. --- -.. ."},
{"-.-. --- -- .--. ..... ----- -----"},
{". -. ... . ..... ----- .----"}};
Новое main()
…
int main(void)
{
char* code = NULL;//will be used to point to each array line.
count_s count = {0};//instance of struct with accumulators
// place declaration of const char *morse[] here as illustrated above
for(int i=0;i<sizeof(morse)/sizeof(morse[0]);i )
{
code = morse[i];//set pointer to successive array elements 0-4
analyse(code, amp;count);//count will accumulate values as loop progresses.
}
printf(" %d dotsn", count.dot);
printf(" %d dashesn", count.dash);
printf(" %d spacesn", count.space);
return 0;
}
Комментарии:
1. Как бы мне сделать это для следующих строк, которые я закомментировал?
2. Сохраните его в виде массива строковых литералов (который у вас есть) или 2D-массива (любой из них будет работать), затем выполните цикл по каждой строке массива. (См. Редактирование и создание
main
с помощью цикла, прочитайте комментарии для получения разъяснений того, что происходит.)
Ответ №3:
У вас возникли проблемы с приращением точек и сканированием строки, см. p_dots
Обновление в main. Я меняю p_dots
значение на int, чтобы оно было в стеке (я думаю, его следует переименовать). В вашем коде вам нужно выделить немного памяти.
Для сканирования строки: просто увеличьте указатель для чтения символа за символом в бесконечном цикле, используйте переключатель для будущего сканирования ‘-‘, остановитесь на нулевом символе.
code
указывает на начало строки, switch (*code )
считывает текущий символ и перемещает указатель на следующий.
Начать:
"... --- ..."
^
code
Считывание .
и перемещение кода
"... --- ..."
^
code
и так далее
#include <stdio.h>
#include <string.h>
void analyse(char* code, int* p_dots)
{
while (42) {
switch (*code ) {
case '.':
(*p_dots) ;
break;
case '-':
break;
case '':
return;
default:
break;
}
}
}
int main(void)
{
char* morse[] =
{
"... --- ..." // SOS
// "-- --- .-. ... .", // MORSE
// "-.-. --- -.. .", // CODE
// "-.-. --- -- .--. ..... ----- -----", // COMP500
// ". -. ... . ..... ----- .----" // ENSE501
};
char* code = *morse;
int p_dots=0;
//int*p_dashes = 0;
analyse(code, amp;p_dots);
printf("Line 1 has %d dotsn", p_dots);
return 0;
}
Комментарии:
1. Вопрос заключается в том, чтобы конкретно использовать арифметику указателей. Весь этот указатель проходит у меня над головой =
2. Хорошо, я добавлю больше деталей
3. Спасибо, весь этот указатель был удален. Потратил на это дни и просто не могу понять … все еще есть qsort, bsearch, побитовые и двоичные файлы для покрытия..