2016-01-13 3 views
0

Я только начал изучать C, и я совершенно не уверен, как «правильно» получить доступ и редактировать значения символьного указателя.Как редактировать значения строки char * в C?

Например:

#include <stdio.h> 
#include <stdlib.h> 
int main() 
{ 
    char* text = malloc(20); 
    char* othertext = "Teststring"; 

    do 
    { 
    *text++ = *othertext++; 
    } while (*othertext != '\0'); 

    printf("%s\n", text + 3); 
    free(text); 
    return 0; 
} 

Во-первых, почему функция делать-то время не работает? Содержимое «othertext» не копируется в «текстовый» указатель. Кроме того, программа вылетает, когда выполняется бесплатный (текст)!

Мы знаем, что этот код работает, если добавить второй указатель:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    char* text = malloc(20); 
    char* othertext = "Teststring"; 

    char *ptr1 = text; 
    char *ptr2 = othertext; 

    do 
    { 
    *ptr1++ = *ptr2++; 
    } while (*ptr2 != '\0'); 

    printf("%s\n", text + 3); 
    free(text); 
    return 0; 
} 

Но оба указателя имеют в основном один и тот же адрес! Они имеют одинаковые значения в отладчике, так как второй указатель имеет значение?

В качестве окончательного замечания: Нам не разрешено использовать string.h. И мы знаем, что между массивами и указателями есть тонкая разница. Но нам нужно конкретно понять, как работает char *!

+1

«char *» не является ни строкой, ни массивом., Это указатель на символ. C не имеет строкового типа. Это все конвенция. – Olaf

+0

Почему «правильно» в Dr Evil цитирует? У вас есть какая-то странная интерпретация «правильной», которая отличается от обычной? –

+0

Потому что, по-видимому, у нас есть «неправильная» концепция того, как ее следует копировать;) –

ответ

0

Вы должны перейти к free() Указатель вернул malloc() (тот же адрес). Вы передаете измененный указатель т.е. text указателя в настоящее время не имеет адреса указателя, возвращаемый malloc() вместо что это адрес последнего элемента text, используйте другой указатель, чтобы скопировать данные, или лучше индекс

size_t i; 
for (i = 0 ; othertext[i] != '\0' ; ++i) 
    text[i] = othertext[i]; 
text[i] = '\0'; 

Вы говорите

Но оба указателя имеют в основном один и тот же адрес!

Это не верно, попробуйте это

printf("%p -- %p\n", (void *) text, (void *) ptr1); 
+0

Спасибо! Хорошо, но один вопрос: перед циклом while указатели «text» и «ptr1» имеют один и тот же адрес. Только после цикла они указывают на разные адреса? Так как же все это по-другому? –

+0

Потому что, когда вы выполняете арифметику указателя, вы меняете адрес, хранящийся в указателе, это точка. После 'ptr1 ++' 'ptr1' указывает на второй символ в' text'. –

+0

Это становится все яснее и яснее! Последний вопрос: если у меня есть «char * test»; (поэтому он не инициализирован с помощью malloc). После этого я не могу изменить содержимое? Потому что даже со вторым указателем, который указывает на «тест», программа заканчивается ошибкой сегментации! Это потому, что нам разрешено изменять в куче? Иначе это только для чтения? –

0

Вы изменяете значение text указателя в цикле, так что в конце концов это не указывает на начало области памяти вы выделяемой; это (часть), почему вы не видите текст, и почему сбой free.

Вам необходимо сохранить это исходное значение указателя (которое вы делаете во втором фрагменте).

0

Вы на самом деле меняете адрес, который указывает также text.

Рассмотрим очень простую память, в которой text точки для решения 5 и othertext точек для решения 42, на которых T из TestString был размещен.

Теперь скопировать символ найден по адресу 42 обратиться 5, так что адрес 5 также содержит T. Однако теперь вы увеличиваете адрес, который указывает также text. Другими словами, text теперь указывает по адресу 6. Вы также увеличиваете othertext, который теперь указывает на адрес 43.

В следующем раунде вы копируете e по адресу 43 по адресу 6 и приращивайте оба раза. Все в порядке.

Однако после завершения копирования text укажет на 5 + 10 = 15. Однако по адресу 15 вы ничего не можете печатать, и вы не можете удалить то, что есть.

В вашей второй части кода нет проблем, потому что text продолжает указывать адрес 5.

0

выполните эту печать f внутри цикла после строки назначения. Я думаю, вы поймете, почему он не работает;)

printf("%s\n", text);