Действительно ли возможно изменить строку символа в C?

Вместо basename, вы можете chdir перед глобализацией, поэтому результаты не содержат путь, например:

<?php
$directory = Yii::getPathOfAlias('webroot').'/uploads/';
chdir($directory); // probably add some error handling around this
$images = glob("*.{jpg,JPG,jpeg,JPEG,png,PNG}", GLOB_BRACE);
 foreach($images as $image)
   echo $image;
?>

Это, вероятно, немного быстрее, но не будет иметь никакого значения разница, если у вас нет тонны файлов

65
задан John Baker 18 June 2009 в 08:58
поделиться

7 ответов

Когда вы пишете «строку» в исходном коде, она записывается непосредственно в исполняемый файл, потому что это значение должно быть известно во время компиляции (существуют инструменты, позволяющие разобрать программное обеспечение и найти в них все простые текстовые строки). Когда вы пишете char * a = "This is a string" , местоположение "This is a string" находится в исполняемом файле, а местоположение , на которое указывает , находится в исполняемый файл. Данные в исполняемом образе доступны только для чтения.

Что вам нужно сделать (как указывали другие ответы), так это создать эту память в месте, которое не доступно только для чтения - в куче или в стеке Рамка. Если вы объявляете локальный массив, затем в стеке создается пространство для каждого элемента этого массива, и строковый литерал (который хранится в исполняемом файле) копируется в это пространство в стеке.

char a[] = "This is a string";

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

char *a = malloc(256);
strcpy(a, "This is a string");

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

В основном, вы должны отслеживать, где находятся ваши данные. Всякий раз, когда вы пишете строку в своем источнике, эта строка доступна только для чтения (в противном случае вы потенциально изменили бы поведение исполняемого файла - представьте, если бы вы написали char * a = "hello"; , а затем изменили a [0] до 'c' . Затем где-то еще написано printf ("привет"); . Если вам разрешили изменить первый символ "hello" , и ваш компилятор сохранил его только один раз (должен), то printf ("hello"); выведет ] виолончель !)

141
ответ дан 24 November 2019 в 15:13
поделиться

Многие люди не понимают разницы между char * и char [] в сочетании со строковыми литералами в C. Когда вы пишете:

char *foo = "hello world";

... вы фактически указываете foo на постоянный блок памяти (фактически, то, что компилятор делает с "hello world" в этом случае, зависит от реализации.)

Использование char [] вместо этого сообщает компилятору, что вы хотите создать массив и заполнить его содержание, «привет, мир». foo - это указатель на первый индекс массива char. Оба они являются указателями char, но только char [] будет указывать на локально выделенный и изменяемый блок памяти.

11
ответ дан 24 November 2019 в 15:13
поделиться

Кажется, что на ваш вопрос был дан ответ, но теперь вы можете задаться вопросом, почему char * a = "String" хранится в постоянной памяти. Что ж, на самом деле он не определен стандартом c99, но большинство компиляторов выбирают его таким образом для таких примеров:

printf("Hello, World\n");

c99 standard (pdf) [стр. 130, раздел 6.7.8]:

Объявление:

char s[] = "abc", t[3] = "abc";

определяет "простые" объекты массива символов s и t, элементы которых инициализируются строковыми литералами символов. Это объявление идентично char

s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };

. Содержимое массивов можно изменять. С другой стороны, объявление

char *p = "abc";

определяет p с типом «указатель на char» и инициализирует его, чтобы указать на объект с типом «массив символов» длиной 4, элементы которого инициализируются литералом символьной строки. Если попытаться использовать p для изменения содержимого массива, поведение не определено.

4
ответ дан 24 November 2019 в 15:13
поделиться

Память для a и b не выделена вами. Компилятор может выбрать область памяти только для чтения для хранения символов. Поэтому, если вы попытаетесь изменить, это может привести к ошибке сегмента. Поэтому я предлагаю вам создать массив символов самостоятельно. Примерно так: char a [10]; strcpy (a, "Hello");

6
ответ дан 24 November 2019 в 15:13
поделиться

Нет, вы не можете его изменить, так как строка может храниться в постоянной памяти. Если вы хотите изменить его, вы можете использовать вместо него массив, например

char a[] = "This is a string";

Или, альтернативно, вы можете выделить память с помощью malloc, например,

char *a = malloc(100);
strcpy(a, "This is a string");
free(a); // deallocate memory once you've done
23
ответ дан 24 November 2019 в 15:13
поделиться
char *a = "stack overflow";
char *b = "new string, it's real";
int d = strlen(a);

b = malloc(d * sizeof(char));
b = strcpy(b,a);
printf("%s %s\n", a, b);
0
ответ дан 24 November 2019 в 15:13
поделиться

Вам нужно скопировать строку в другой буфер памяти, а не только для чтения, и изменить ее там. Используйте strncpy () для копирования строки, strlen () для определения длины строки, malloc () и free () для динамического выделения буфера для новой строки.

Например (псевдокод, подобный C ++):

int stringLength = strlen( sourceString );
char* newBuffer = malloc( stringLength + 1 );

// you should check if newBuffer is 0 here to test for memory allocaton failure - omitted

strncpy( newBuffer, sourceString, stringLength );
newBuffer[stringLength] = 0;

// you can now modify the contents of newBuffer freely

free( newBuffer );
newBuffer = 0;
0
ответ дан 24 November 2019 в 15:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: