как работает функция, указатель и строка?почему strchr () получает символы после искомого символа? - PullRequest
0 голосов
/ 26 апреля 2018

Пример ниже.В моем понимании, t и p - это одни и те же указатели, указывающие на адрес строки?Я запутался с указателем и строкой.puts(p) даст адрес строки вместо символов?Кроме того, я не могу понять, как работает strchr функция.++ p будет указывать на следующий символ после ':', то есть, как он работает, правильно?Пожалуйста помоги!Спасибо.

char *t = "MEAS:VOLT:DC?";
char *p;  
p = t;     
puts( p );
while(( p = strchr( p, ':' )) != NULL )
{ puts( ++p )}}

1 Ответ

0 голосов
/ 26 апреля 2018

Что такое указатель?Указатель - это переменная, которая хранит адрес (ячейку памяти).Это может быть адрес другой переменной

int n = 9;
int *ptr = &n; // stores the address of n

или это может быть начало блока памяти, например, динамически выделяемого блока памяти:

int *fields = malloc(len * sizeof *fields);

Независимо от того, какой адрес указатель являетсяуказывая на, мы используем указатели для прямого доступа к памяти, которая хранится в указателе (мы также говорим , где указатель указывает на ).

Что такое строки?Вы должны понимать, что в C нет строкового типа, как в других языках программирования.В C строка - это просто последовательность 8-битных значений (представляющих символы), которые заканчиваются байтом, определяющим '\0'.Естественный тип для одного символа - char, поэтому мы используем char* или char[] для получения строки.

Когда вы делаете

const char *str = "Hello";

strуказывает где-то в памяти, и это выглядит так:

b = base address of the first character in the
    sequence

b     b+1   b+2   b+3   b+4   b+5
+-----+-----+-----+-----+-----+------+
| 'H' | 'e' | 'l' | 'l' | 'o' | '\0' |
+-----+-----+-----+-----+-----+------+

Целочисленные значения символьных констант, таких как 'H', определяются таблицей ASCII .Итак, на самом деле память выглядит так:

b = base address of the first character in the
    sequence

b     b+1   b+2   b+3   b+4   b+5
+----+-----+-----+-----+-----+-----+
| 72 | 101 | 108 | 108 | 111 |  0  |
+----+-----+-----+-----+-----+-----+

Итак, str указывает на это местоположение b, str[0] - первый символ, str[1] - второй и т. Д. Как вы видите, чтобы получить строку, все, что вам нужно, это доступ к первому символу в последовательности.Вот почему мы используем указатель char* для адресации строк, потому что с указателем char* мы имеем доступ к первому и последующим символам в строке.

Функция, подобная puts(str), выполняетследующее:

  • является ли текущий символ байтом, определяющим '\0'?
    • , если да, затем выйти
    • , если нет, затем распечатать символ и перейти к следующему

Так что puts(str) делаетне печатать адрес, на который указывает указатель, он печатает содержимое памяти, на которую указывает указатель.

Функция, подобная strchr, работает следующим образом:

man strchr

char *strchr(const char *s, int c);

ОПИСАНИЕ

Функция strchr() возвращает указатель на первое вхождение символа c в строкеs.

Теперь, когда вы знаете расположение строк в памяти, это должно быть легко понять.Давайте посмотрим на это:

const char *str = "Hello";
char *f = strchr(str, 'l');

Помните, что расположение памяти, на которое указывает str:

b = base address of the first character in the
    sequence

b     b+1   b+2   b+3   b+4   b+5
+-----+-----+-----+-----+-----+------+
| 'H' | 'e' | 'l' | 'l' | 'o' | '\0' |
+-----+-----+-----+-----+-----+------+
               ^
               ¦
       first occurrence
            of 'l'

, так что strchr возвращает указательна b+2 (или str+2, потому что в моем примере b это значение, которое хранит указатель str).

Вот почему, когда вы puts(str) получаете Hello, а когдавы делаете puts(f) вы получаете llo.

Простая реализация для strchr:

char *strchr(const char *s, int c);
{
    // stop when the \0-terminating byte is reached
    for(size_t i = 0; s[i] != '\0'; ++i)
    {
        if(s[i] == c)
            return &s[i];  // or return s+i; using pointer arithmetic
    }

    return NULL; // c is not found in the string
}

Так что же это делает?

while(( p = strchr( p, ':' )) != NULL )
{ 
    puts( ++p )
}

Когда strchr в первый раз возвращает значение, отличное от NULL, оно вернет указатель на первое вхождение двоеточия :.puts(++p) эквивалентно

p = p + 1; // let p point to the next next character after the colon
puts(p);   // prints the string

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

MEAS:VOLT:DC?       // puts( p );
VOLT:DC?            // 1. puts( ++p ); of the loop
DC?                 // 2. puts( ++p ); of the loop
...