Как я связываю константу/литеральные строки в C?

Хорошей идеей является использование «объектно-реляционного картографа», подобного Idiorm :

$user = ORM::for_table('user')
->where_equal('username', 'j4mie')
->find_one();

$user->first_name = 'Jamie';
$user->save();

$tweets = ORM::for_table('tweet')
    ->select('tweet.*')
    ->join('user', array(
        'user.id', '=', 'tweet.user_id'
    ))
    ->where_equal('user.username', 'j4mie')
    ->find_many();

foreach ($tweets as $tweet) {
    echo $tweet->text;
}

Он не только избавляет вас от SQL-инъекций, но и от синтаксических ошибок! Также поддерживает коллекции моделей с цепочкой методов для фильтрации или применения действий к нескольким результатам сразу и нескольких подключений.

323
задан Peter Mortensen 22 May 2017 в 07:41
поделиться

9 ответов

В C "строки" просто char массивы. Поэтому Вы не можете непосредственно связать их с другими "строками".

можно использовать эти strcat функция, которая добавляет строку, на которую указывают src до конца строки, на которую указывают dest:

char *strcat(char *dest, const char *src);

Вот пример с cplusplus.com :

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

Для первого параметра, необходимо обеспечить сам целевой буфер. Целевой буфер должен быть буфером массива символов. Например: char buffer[1024];

Удостоверяются , что первый параметр имеет достаточно пространства для хранения то, что Вы пытаетесь скопировать в него. При наличии Вам, более безопасно использовать функции как: strcpy_s и strcat_s, где явно необходимо определить размер целевого буфера.

Примечание : строковый литерал не может использоваться в качестве буфера, так как это - константа. Таким образом всегда необходимо выделять массив символов для буфера.

возвращаемое значение [1 111] может просто быть проигнорировано, оно просто возвращает тот же указатель, как был передан в как первый аргумент. Это там для удобства и позволяет Вам объединять вызовы в цепочку в одну строку кода:

strcat(strcat(str, foo), bar);

, Таким образом, Ваша проблема могла быть решена следующим образом:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);
358
ответ дан Endre 23 November 2019 в 00:56
поделиться

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

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

, Таким образом, strcat перерывает первый аргумент в пользу нулевого символа. Тогда это заменит это содержанием второго аргумента (пока это не закончится в пустом указателе).

Теперь позволяют нам пройти Ваш код:

message = strcat("TEXT " + var);

Вот, пожалуйста добавление чего-то к указателю на текст "ТЕКСТ" (тип "ТЕКСТА" является константой char*. Указатель.).

, Который не будет обычно работать. Также изменение "ТЕКСТОВОГО" массива не будет работать, поскольку это обычно помещается в постоянный сегмент.

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

, Который мог бы работать лучше, за исключением того, что Вы снова пытаетесь изменить статические тексты. strcat не выделяет новую память для результата.

я предложил бы сделать что-то вроде этого вместо этого:

sprintf(message2, "TEXT %s TEXT %s", foo, bar);

Read документация sprintf для проверки, поскольку это - опции.

И теперь важный момент:

Гарантируют, что буфер имеет достаточно пространства для содержания текста И нулевого символа. Существует несколько функций, которые могут помочь Вам, например, strncat и специальные версии printf, которые выделяют буфер для Вас. Не обеспечение размера буфера приведет к повреждению памяти и удаленно годным для использования ошибкам.

3
ответ дан Peter Mortensen 23 November 2019 в 00:56
поделиться

Это - неопределенное поведение попытаться изменить строковые литералы, который является что что-то как:

strcat ("Hello, ", name);

попытается сделать. Это попытается лавировать на эти name строка до конца строкового литерала "Hello, ", который не четко определен.

Попытка что-то это. Это достигает того, что Вы, кажется, пытаетесь сделать:

char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);

Это создает буферную область, которая является , позволил быть измененным и затем копирует и строковый литерал и другой текст к нему. Просто будьте осторожны с переполнением буфера. Если Вы управляете входными данными (или проверяете его заранее), хорошо использовать буферы фиксированной длины как, я имею.

Иначе, необходимо использовать стратегии смягчения, такие как выделение достаточной памяти от "кучи", чтобы гарантировать, что можно обработать его. Другими словами, что-то как:

const static char TEXT[] = "TEXT ";

// Make *sure* you have enough space.

char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
     handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);

// Need to free message at some point after you're done with it.
3
ответ дан paxdiablo 23 November 2019 в 00:56
поделиться

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

Конкретно:

... надрез...

место назначения

Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

... надрез...

http://www.cplusplus.com/reference/clibrary/cstring/strcat.html

существует пример здесь также.

1
ответ дан Peter Mortensen 23 November 2019 в 00:56
поделиться

Первый аргумент strcat () должен быть в состоянии содержать достаточно пространства для сцепленной строки. Поэтому выделите буфер с достаточным количеством пространства для получения результата.

char bigEnough[64] = "";

strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);

/* and so on */

strcat () свяжет второй спор с первым аргументом и сохранит результат в первом аргументе, возвращенный символ* является просто этим первым аргументом, и только для Вашего удобства.

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

3
ответ дан Pieter 23 November 2019 в 00:56
поделиться

Не забывайте инициализировать буфер вывода. Первым аргументом strcat должна быть завершенная строка пустого указателя с достаточным дополнительным местом, выделенным для получившей строки:

char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string ); 
// null_terminated_string has less than 1023 chars
5
ответ дан David Rodríguez - dribeas 23 November 2019 в 00:56
поделиться

Также malloc и перевыделение полезны, если Вы не знаете заранее, сколько строк связывается.

#include <stdio.h>
#include <string.h>

void example(const char *header, const char **words, size_t num_words)
{
    size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
    char *message = (char*) malloc(message_len);
    strncat(message, header, message_len);

    for(int i = 0; i < num_words; ++i)
    {
       message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
       message = (char*) realloc(message, message_len);
       strncat(strncat(message, ";", message_len), words[i], message_len);
    }

    puts(message);

    free(message);
}
16
ответ дан Reed Hedges 23 November 2019 в 00:56
поделиться

Люди, используйте strncpy (), кошка str n (), или snprintf ().
Превышение Вашего пространства буфера повредит то, что следует в памяти!
(И не забывают предоставлять пространство для запаздывающих пустых '\0' символов!)

24
ответ дан Keith Thompson 23 November 2019 в 00:56
поделиться

Избегайте использования strcat в коде C. Самое чистое и, самое главное, самый безопасный путь состоит в том, чтобы использовать snprintf :

char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

Некоторые комментаторы подняли вопрос, что количество аргументов не может соответствовать строке формата, и код все еще скомпилирует, но большинство компиляторов уже выпускает предупреждение, если это верно.

237
ответ дан Alex B 23 November 2019 в 00:56
поделиться
Другие вопросы по тегам:

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