Путаница в том, как использовать strchr в C - PullRequest
1 голос
/ 25 января 2020
char *strchr( const char *s, int c );

Я понимаю, что strchr находит первое вхождение символа c в строке s. Если найдено c, возвращается указатель на c в s. В противном случае возвращается указатель NULL.

Так почему приведенный ниже код выводит num в strlen (строку), а не для того, для чего он предназначен?

num=0;
   while((strchr(string,letter))!=NULL)
   {
      num++;
      string++;
   }

Но этот код дает правильный вывод

num=0;
   while((string=strchr(string,letter))!=NULL)
   {
      num++;
      string++;
   }

Я не понимаю, почему присвоение указателя, который возвращается другому квалифицированному указателю, даже имеет значение. Я только проверяю, является ли возвращаемое значение пустым указателем или нет.

Ответы [ 3 ]

3 голосов
/ 25 января 2020
  1. string - указатель.

  2. В первом примере вы просто перемещаете его вправо на одну позицию независимо от того, где (или если!) Была найдена «буква».

  3. Во втором примере, каждый раз, когда вы найдете «букву», вы:

    a) обновите «строку», чтобы она указала на букву, затем

    b) обновите «строку» еще раз, чтобы она указала сразу за буквой.

1 голос
/ 25 января 2020

Позвольте мне попытаться выразить это по-другому:

strchr

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

В первой части вашего сниппета возвращаемое значение не фиксируется, в качестве аргумента передается непосредственная следующая позиция string от того места, на которое ранее она указывала. Короче говоря, фрагмент подсчитывает общее количество символов до последнего появления letter

const char* string = "hello"
char letter = 'l'
num=0;
while((strchr(string,letter))!=NULL)
{
    num++;
    string++;
}

Как это,

            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
              ^
              |
+-------+     |
+string +-----+
+-------+
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                  ^
                  |
+-------+         |
+string +---------+
+-------+

            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                      ^
                      |
+-------+             |
+string +-------------+
+-------+



            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                              ^
                              |
+-------+                     |
+string +---------------------+
+-------+

Во втором фрагменте фиксируется возвращаемое значение strchr обратно в string и следующий адрес сразу же передается в качестве аргумента в следующей итерации,

const char* string = "hello"
char letter = 'l'
num=0;
while((string = strchr(string,letter))!=NULL)
{
    num++;
    string++;
}

Примерно так:

+-------+     
+string +-----+
+-------+     |
              |
/*input pointer to strchr*/
              |
              v
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                      |
                      |
               /*return pointer from strchr*/
                      |
+-------+             |
+string +<------------+
+-------+     


+-------+                 
+string +-----------------+
+-------+                 |
                          |
            /*input pointer to strchr*/
                          |
                          v
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+
                          |
                          |
              /*return pointer from strchr*/
+-------+                 |
+string +<----------------+
+-------+     

+-------+                     
+string +---------------------+
+-------+                     |
                              |
                /*input pointer to strchr*/
                              |
                              v
            +---+---+---+---+---+----+
            |'h'|'e'|'l'|'l'|'o'|'/0,|
            +---+---+---+---+---+----+

                   /*NULL return from strchr*/
+-------+                     |
+string +<--------------------+
+-------+
0 голосов
/ 25 января 2020

Первый фрагмент кода:

Так почему приведенный ниже код выводит num в strlen (строку), а не то, для чего он предназначен?

Выходные данные не всегда могут быть strlen(string) и будут зависеть от входной строки string и символа letter, переданного в strchr(). Например, если входное значение равно

string = "hello"
letter = 'l'

, то вы получите выходное значение 4, которое не равно длине строки "hello". Если входное значение равно

string = "hello"
letter = 'o'

, то полученное значение равно 5, что равно длине строки "hello". Если входное значение равно

string = "hello"
letter = 'x'

, то полученное значение равно 0.
Выходное значение фактически зависит от позиции последнего вхождения символа letter во входной строке.

Причина в том, что существует только один оператор, который изменяет позицию указателя string, и этот оператор

      string++;

Он работает таким образом -
Если присутствует символ в string strchr() будет возвращать ненулевое значение до тех пор, пока указатель ввода string не укажет на символ на последнем вхождении символа letter в строке или до него. Если указатель string указывает на один символ после последнего вхождения символа letter в строке, strchr() вернет NULL, и l oop завершится, а num будет равно позиции последнего вхождения letter символов в строке. Таким образом, вы получите вывод в диапазоне от 0 до strlen(string), а не strlen(string) всегда.

string = "hello", letter = 'e', num = 0
strchr(string, letter) will return not null as 'e' present in input string
num++; string++;

string = "ello", letter = 'e', num = 1
strchr(string, letter) will return not null as 'e' present in input string
num++; string++;

string = "llo", letter = 'e', num = 2
strchr(string, letter) will return null as it does not find 'e' in input string and loop exits

Output will be 2

Второй фрагмент кода:

Но этот код дает правильный вывод

Да, причина в strchr() возвращаемый указатель присваивается указателю string. Возьмите тот же пример, что и выше, предположим, что ввод

string = "hello"
letter = 'l'

strchr(string, letter) вернет указатель на первое вхождение символа l, и он назначен указателю string. Итак, теперь указатель строки указывает на первое вхождение l. Это означает, что теперь string равен

string = "llo"

, а в теле l oop вы выполняете

string++;

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

string = "lo"
letter = `l`

и strchr(string, letter) вернет указатель на символ, на который указывает string в данный момент, поскольку он соответствует символу letter. Из-за string++ в теле l oop, теперь строка будет указывать на следующий символ

string = "o"
letter = `l`

, а strchr(string, letter) вернет NULL и l oop завершится. num увеличивается столько раз, сколько символов letter найдено в string. Следовательно, второй фрагмент дает правильный вывод.

...