Как работает функция "указатель"? А условие *p?

Не могу понять, что это за функция и как она работает? Также что такое условие * p в цикле for? Чем он занимается?

char *uppercase(char *s) 
{
    for(char *p = s; *p; ++p) 
    {
        if ('a' <= *p && *p <= 'z')
            *p = *p - 32;
    }

    return s;
}

Я не могу назвать это как верхний регистр ("любая строка"), и этот char *uppercase меня смущает.

Тип указателя по-прежнему остается типом, в вашем случае — типом char *.

Ron 11.12.2020 20:27

Нет видов функций. Это просто: функция

user253751 11.12.2020 20:30

Строки в C — это char массивы. Соглашение состоит в том, что существует сигнальное значение «конец строки», равное 0x00. *p; — это способ остановки цикла при обнаружении сигнализатора EOS (т. е. при достижении конца строки). Он продолжает цикл, только если текущий персонаж не является часовым. *p; это сокращение от *p != 0;

Craig Estey 11.12.2020 20:33

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

Ron 11.12.2020 20:41

@Ron Как я могу передать постоянную строку?

Barak 11.12.2020 20:43

@Bobamas Вы не можете передать указатель на постоянную строку в свою функцию, так как ваша функция изменяет данные, на которые указывает. Попытка изменить постоянную строку, на которую указывает указатель, является UB. Таким образом, передача указателя, определенного как char* c = "Hello World";, является UB. Передача имени массива символов, определенного как char c[] = "Hello World";, допустима.

Ron 11.12.2020 20:44

@Bobamas I can call it like uppercase("any string") - нет, нельзя. В этом примере вызывается Undefined Behavior

0___________ 11.12.2020 20:54
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
7
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

char *uppercase(char *s) объявляет uppercase функцией с параметром s типа char *, которая возвращает char *. (char * означает тип, который является указателем на char объект в памяти.)

for(char *p = s; *p; ++p) определяет char * с именем p и инициализирует его как s. Итак, когда этот цикл начинается, p указывает на то же место, на которое указывает s. Второй элемент, *p, говорит продолжать цикл до тех пор, пока *p не равно нулю. (*p — это char, на который в данный момент указывает p.) Третий элемент, ++p, говорит об увеличении p на единицу на каждой итерации. Это заставляет p указывать на следующее char в памяти.

if ('a' <= *p && *p <= 'z') — это непереносимая проверка того, является ли p строчной буквой. Стандарт C не гарантирует, что коды строчных букв от a до z находятся между значениями кодов a и z или что между ними нет других кодов. Правильный способ написать это if (islower((unsigned char) *p)).

*p = *p - 32; — плохой способ изменить код строчной буквы на код соответствующей прописной буквы. Это плохо, потому что он зависит от разницы между кодами этих букв, равной 32. Это особенность ASCII, но стандарт C не гарантирует этого. *p += 'A' - 'a'; было бы немного лучше написать это, но стандарт C предлагает лучший способ: *p = toupper(*p);.

Эти islower и toupper функции объявлены в заголовке <ctype.h>. (Примечание. Использование toupper с символами, которые, как известно, не входят в базовый набор символов выполнения, требует преобразования его ввода в unsigned char и учета того факта, что его выходное значение может переполнить char. Поскольку этот исходный код применяет toupper только к символам, которые уже известно, что это строчные буквы, которые входят в базовый набор символов выполнения, это не проблема.)

Таким образом, функция проверит каждый символ в строке, на которую указывает s, и изменит все строчные буквы на прописные.

Omg Большое спасибо за это гладкое объяснение!! Если я хочу сделать эту функцию нулевой безопасной, достаточно ли if (*s == NULL){ return 1;}?

Barak 11.12.2020 20:40

@Bobamas: если функция вызывается с нулевым аргументом, она должна объявить об ошибке (возможно, напечатать сообщение и выйти из программы, или вызвать какую-либо процедуру обработки ошибок, или запустить сигнал) и/или вернуть нулевой указатель. Он не должен возвращать 1. (Вы можете использовать return 0;, чтобы вернуть нулевой указатель, или return (void *) 0;, чтобы прояснить намерение, или return NULL;, если включен подходящий заголовок.)

Eric Postpischil 11.12.2020 20:48

@Bobamas помните, что вы не можете использовать это так uppercase("hello world");

0___________ 11.12.2020 20:56

@P__JsupportswomeninPoland Есть ли решения для такого использования?

Barak 11.12.2020 20:58

Вам нужно выделить новый массив символов для сохранения результата.

0___________ 11.12.2020 21:01

Я много думаю об этом, но не могу понять, как сохранить результат

Barak 11.12.2020 21:02

статическая переменная, malloc

0___________ 11.12.2020 21:04

Другие вопросы по теме