C Работа с указателями на символы - PullRequest
1 голос
/ 03 октября 2009

просто освежаю немного C для класса, и я наткнулся на кое-что, что заставляет меня почесать голову. Для этого кода:

char * findString(const char * s){
/* Allocate space */    
char * ret = malloc(strlen(s) + 1);    
/* Copy characters */
char * n;
n = ret;
for ( ;*s != 0; s++)
    if (isLetter(*s))
        *n++ = *s;
*n = 0;   
/* return pointer to beginning of string */
return ret;

}

(Мы просто предполагаем, что isLetter возвращает 1/0).

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

Итак, как работает 'ret' в этом случае? Я очень озадачен возвратом 'ret', когда 'n = ret' объявлено над циклом for, а 'ret' никогда не устанавливается ни на что после. Очевидно, я что-то здесь упускаю. Помогите!

-R. L.

Ответы [ 5 ]

1 голос
/ 03 октября 2009

и ret и n являются указателями на один и тот же блок памяти. их «значения» являются просто адресами памяти - при изменении *n вы изменяете *ret, даже если n и ret сохраняют свои исходные значения.

//make n point to the beginning of the block of memory pointed
//to by ret
n = ret;

//iterate through the string which was passed to
//the function
for ( ;*s != 0; s++)
        //if the current character is a letter:
        if (isLetter(*s))
                //set the character pointed to by n to
                //the current character in the string, and then
                //make n point to the next one.
                *n++ = *s;

обратите внимание, что цикл увеличивается n, а затем после цикла устанавливает последний символ равным 0 (чтобы завершить строку нулем). Теперь n указывает на конец строки - но поскольку ret никогда не изменялся, он по-прежнему указывает на начало памяти, которую вы malloc редактировали перед циклом. Когда вы его возвращаете, вы возвращаете указатель на новую строку, то есть строку, которую вы передали функции, за вычетом всех не-букв.

Обратите внимание, что после возврата этой функции вызывающая сторона несет ответственность за free() память, выделенную функцией, чтобы вы не бродили по утечкам памяти.

0 голосов
/ 03 октября 2009

ret - указатель на начало возвращаемой строки. Вам нужно создать еще один указатель, n, поскольку этот указатель не всегда будет указывать на начало возвращаемой строки, он будет перемещаться по ней, изменяя ее символы. И, чтобы иметь возможность вернуть строку, вы должны вернуть указатель на начало строки, и вам нужно знать, где она заканчивается (поэтому вам нужно добавить 0 в конец).

Надеюсь, я помог!

0 голосов
/ 03 октября 2009

Не так много, на самом деле, строка 3 выделяет пустую строку, ret, которая достаточно длинна, чтобы содержать аргумент, даже если это все буквы. Эта строка в конечном итоге будет возвращена. Затем функция перебирает аргумент и, если это буква, помещает ее в возвращаемую строку с помощью промежуточного указателя n, который отслеживает текущую позицию в возвращаемой строке.

0 голосов
/ 03 октября 2009

n и ret являются указателями, что означает, что они содержат адреса. В этом случае они оба содержат адрес одного и того же символьного буфера, который выделяется с помощью malloc. В этом смысле n и ret являются взаимозаменяемыми.

0 голосов
/ 03 октября 2009

ret, хотя семантически является строкой, фактически является указателем на первый символ строки. n используется как указатель на текущую позицию в этой строке. Таким образом, ret остается указывать на начало строки, в то время как n перемещается вдоль строки, когда она заполнена. *n = 0 добавляет нулевой терминатор. Таким образом, хотя ret ничего не установлено, содержимое строки, на которую он указывает , установлено .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...