Вот мой код:
#include <iostream>
using namespace std;
int countX(char*, char);
int main() {
char msg[] = "there are four a in this sentence a a";
//char *ptr = msg; // <----- question 2!
cout << countX(msg, 'a');
cin.get();
}
int countX(char* ptr, char x) {
int c = 0;
for (; *ptr; ptr++) {
if (*ptr == x) c++;
}
/*
while(*ptr) {
if(*ptr==x) c++;
ptr++;
}
*/
return c;
}
Мне было интересно несколько вещей, касающихся безопасной практики и указателей:
; *ptr ;
; *ptr ;
, является ли эта безопасная практика? Будет ли каждый разрыв, если в памяти будет что-то, хранящееся в памяти рядом с последним элементом массива? Возможно ли это? Как он знает, когда прекратить? Когда *ptr
считается неприемлемым?char *ptr = msg;
в основном): я понимаю, что указатель и массив очень схожи, однако есть ли разница между передачей фактического массива в countX
и передачей указателя (который указывает на начало массива?).countX
я countX
два разных подхода к простой проблеме. Один считается превосходящим другого?Q Мой условный оператор в for-loop; * ptr; это безопасная практика?
Да, большую часть времени. Подробности смотрите ниже.
Q Будет ли это каждый (я знаю, что вы имели в виду когда-либо), если произойдет что-то, хранящееся в памяти, рядом с последним элементом массива?
A Да.
Q Возможно ли это?
A Да. Вы можете легко получить доступ к памяти за прошлым символом массива и сделать ее чем-то отличным от нулевого символа.
Q Как он знает, когда прекращать работу?
A Он прекратится, когда вы столкнетесь с завершающим нулевым символом строки. Если нулевой символ заменен чем-то другим, поведение будет непредсказуемым.
Q Когда * ptr считается неприемлемым?
A Если длина строки равна len
, нормально установить ptr
в диапазоне msg
и msg+len
. Если ptr
указывает на что-либо за пределами этого диапазона, поведение не определено. Следовательно, они должны считаться неприемлемыми в программе.
Q (относительно прокомментированного char * ptr = msg; в основном): я понимаю, что указатель и массив очень схожи, однако есть ли разница между передачей фактического массива в countX и передачей указателя (что указывает на начало массива?).
A, N Они идентичны.
Q В countX я предложил два разных подхода к простой проблеме. Один считается превосходящим другого?
Нет, они не являются. Это сводится к личным вкусам. Мне нравится использовать for
циклов, в то время как я знаю людей, которые любят использовать в while
циклы.
ptr
в диапазоне msg
и msg+len
, это потому, что поскольку msg
является постоянным указателем на первый элемент, что указывает на начало массива?
Q1: Мой условный оператор в for-loop; * ptr; это безопасная практика? Будет ли каждый разрыв, если в памяти будет что-то, хранящееся в памяти рядом с последним элементом массива? Возможно ли это? Как он знает, когда прекратить? Когда * ptr считается неприемлемым?
Ans: При использовании с строками c-стиля да, это безопасная практика. Любая строка c-style обязательно заканчивается на "\ 0", которая в основном равна 0. Поведение не определено, когда "\ 0" не существует. Таким образом, цикл будет разбит в конце строки. * ptr никогда не прекратится, если это что-то другое, кроме строки c-style. Например, c-style "hello" на самом деле представляет собой массив, содержащий "h", "e", "l", "l", "o", "\ 0". Таким образом, цикл существует в '\ 0', никогда не получая доступ к памяти после него. можно получить доступ к памяти после последнего элемента массива. Например,
int a[5] = {0,1,2,3,4,5};
int *p = a+5;
p обращается к элементу после последнего элемента массива a.
Q2: (относительно прокомментированного char * ptr = msg; в основном): я понимаю, что указатель и массив очень схожи, однако есть ли разница между передачей фактического массива в countX и передачей указателя (который указывает к началу массива?).
Ans: Массивы и указатели не совсем похожи. Его просто то, что имя массива - не что иное, как постоянный указатель, указывающий на первый элемент массива. Рассмотрим предыдущий пример, который я написал. В этом случае [3], 3 [a], * (a + 3) и * (p + 3) все относятся к одному и тому же элементу. Поскольку вы проходите по значению, значение константного указателя msg будет просто скопировано в ptr. Итак, нет, это не имеет значения.
Q3: В countX я предложил два разных подхода к простой проблеме. Один считается превосходящим другого?
Анс: Я не эксперт, но я бы сказал, нет.
Кроме того, вам, вероятно, не нужен cin.get().
p
указывает на один конец, что нормально, но не имеет к нему доступа (что было бы неопределенным поведением, если бы вы попытались).
cin.get()
поддерживает cmdprompt открытым (до ENTER), так что я могу перехватить результат до его закрытия. Разве есть лучший способ сделать это, о котором я не знаю? Или вы имели в виду по совершенно другой причине? Для Мэтта МакНабба, да, я немного читал о неопределенном поведении, также довольно новом для этого. Переход к C ++ из Java определенно менее ограничен, я уже нашел.
Это очень плохая практика.
Что вы делаете в условии for
в основном, if (*ptr)
, другими словами, указывает ли память, на которую указывает ptr
ненулевое значение?
Поэтому, если ячейка памяти после строки содержит ненулевое значение (возможно, из другой переменной с использованием пробела) или значение мусора, то ваш цикл может быть бесконечным или дать неверное значение. Вместо этого вы должны запустить цикл от 0 до длины строки.
std::string
иstd::count_if