2016-10-22 2 views
-1

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

char *names[]={"Sachin","Kapil","Ajay","Sunil","Anil"}; 
cout<<"String II is ";cout<<names[1]; 
cout<<"\nString IV is ";cout<<names[3]; 
char *t; 
t=names[1]; 
names[1]=names[3]; 
names[3]=t; 
cout<<"\nString II is ";cout<<names[1]; 
cout<<"\nString IV is ";cout<<names[3]; 

В первой строке я использовал массив указателей на символы, чтобы сохранить адрес 1-го символа строк.

Когда я COUT имена [1] и имена [3]:

Вся строка была напечатана, но не адрес только указателя символов печататься?

Кроме того, как программа печатает всю строку вместо печати только первого символа?

После того, как я скомпилировал, я получил предупреждение из строки 1, в котором говорилось: предупреждение: устаревшее преобразование из строковой константы в 'char *' [-Wwrite-strings] |

Программа работает по назначению, но мне бы хотелось знать, как она работает. Мне удалось реализовать реализацию, в которой они использовали cout.write (names [i], len) для печати всей строки (что имеет смысл) , но, к моему удивлению, вышеупомянутый метод работает тоже (даже без какого-либо увеличения значения указателя для печати следующего символа).

Любые советы и предложения по перечисленным выше вопросам были бы оценены. Спасибо!

+0

Должно быть разбиение 'char * names []' на два блока, подобные этому. 'char *' и 'names []', который представляет собой массив указателей на char, называемых именами. –

ответ

0

Первое - почему вы не просто получаете адрес. Когда вы вставляете «char*» в поток, такой как std::cout<<s;, где s имеет тип char*, логика вставки предполагает, что s указывает на первый символ строки «C». Строка 'C' представляет собой последовательность символов, заканчивающуюся символом nul ('\0'). Таким образом, логика ввода выводит эту последовательность символов.

Вы получите другой результат, если используете std::cout<<static_cast<void*>(c);, потому что вставка указателя void* обрабатывается по-разному.

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

Теперь почему вы получаете это предупреждение. Вы раскрываете некоторые из несчастливого наследия C++, в частности, багажа, унаследованного от C. В плохие старые дни раннего C без модификатора const не было никакого способа указать, что строковые литералы (например, «Sachin») не могут быть изменены во время выполнения и на разных платформах это имело разные эффекты, начиная от безобидного внесения поправок в данные, бросая исключение доступа для модификации всех литералов, ссылающихся на это строковое значение в коде (их может быть несколько).

Так что, когда C++ пришел и представил const (вскоре он был принят C), было вполне правильно подобрать тип строковых литералов в коде const char[]. Однако некоторые компиляторы (когда у вас есть неправильные настройки!) По-прежнему позволяют назначать литералы char[] (или char*) для обратной совместимости. Если вы не поддерживаете древний код, и старший программист дал вам соответствующее указание, никогда не оставляйте эту опцию включенной.

0

В потоковой библиотеке признается тип char * и обрабатывается как строка с нулевым завершением c-style, которая представляет собой просто массив символов, завершенных нулем.

Чтобы получить его для печати адресов, введите листинг строки в пустоту *.

т.е.

cout << "String II is "; cout << (void *)names[1]; 

теперь выход:

String II is 0x400a0b 

Относительно того, почему первый символ не печатаются только, это потому, что поток библиотека рассматривает его как нуль C строки. Но если вы на самом деле хотел только первый символ напечатан вы могли бы так же, как легко сделать это:

cout << "String II is "; cout << *names[1]; 

или:

cout << "String II is "; cout << names[1][0]; 

Манипулирование указатели, как вы в порядке, но манипуляции, что они содержат не тогда, когда как у вас есть. Поэтому вы должны действительно объявить их const. Это также удаляет предупреждения компиляции. Таким образом, код стал бы.

const char *names[]={"Sachin","Kapil","Ajay","Sunil","Anil"}; 
cout << "\nString II is "; cout << (void*)names[1]; 
cout << "\nString IV is "; cout << (void*)names[3]; 

const char *t; 
t = names[1]; 
names[1] = names[3]; 
names[3] = t; 

cout << "\nString II is "; cout <<(void*)names[1]; 
cout << "\nString IV is "; cout <<(void*)names[3]; 
+1

Эта вещь 'endl' неверна,' endl' просто заставляет флеш, который на самом деле вредит производительности. Использование '\ n' в порядке и на самом деле рекомендуется. И я бы добавил, что если вы не хотите буферизации, лучший подход, чем использование '\ n', - это просто использовать' cerr' вместо 'cout'. –

+0

Спасибо за разъяснение @NirFriedman. Я не знал об этом, так как я ненавижу библиотеку iostream и редко использую ее лично. – Matt

Смежные вопросы