Как мне обединить константный/строковые литералы в C?

Я'м работает в C, и мне нужно объединить несколько вещей.

Сейчас у меня есть это:

message = strcat("TEXT ", var);

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

Теперь, если у вас есть опыт работы в C я'м уверена, что вы понимаете, что это дает ошибку сегментации при попытке запустить его. Так как я могу обойти это?

Комментарии к вопросу (2)
Решение

В C, то "строки" и просто голец массивы. Таким образом, вы можете't напрямую соединить их с прочим "ниточки" по.

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

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 массив. Е. Г.: буфер типа char[1024];

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

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

Возвращаемое значение функции strcat` можно просто игнорировать, он просто возвращает тот же указатель, как был передан в качестве первого аргумента. Он есть для удобства, и позволяет цепи звонки в одну строку кода:

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

Так что ваша проблема может быть решена следующим образом:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);
Комментарии (14)

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

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

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

Комментарии (17)

Люди, используйте ул.<б>Н</б>КПЮ(), ул.<б>Н</б>кат(), или S<б>Н</б>функции printf(). <БР>превышение места в буфере мусор все остальное в памяти! <БР>(и не забудьте оставить пространство для трейлинг-нулевой '\0' характер!)

Комментарии (9)

Строки также могут быть объединены во время компиляции.

#define SCHEMA "test"
#define TABLE  "data"

const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry =               // include comments in a string
    " SELECT * "                // get all fields
    " FROM " SCHEMA "." TABLE   /* the table */
    " WHERE x = 1 "             /* the filter */ 
                ;
Комментарии (0)

Также malloc и realloc полезны, если вы не'т знать заранее, сколько строк, объединяемых.

#include 
#include 

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);
}
Комментарии (1)

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

char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string ); 
// null_terminated_string has less than 1023 chars
Комментарии (0)

Как люди отмечали обработки строк значительно улучшилось. Так что вы можете научиться использовать библиотеку строку C++ вместо C-строки. Однако вот решение на C

#include 
#include 
#include 

void appendToHello(const char *s) {
    const char *const hello = "hello ";

    const size_t sLength     = strlen(s);
    const size_t helloLength = strlen(hello);
    const size_t totalLength = sLength + helloLength;

    char *const strBuf = malloc(totalLength + 1);
    if (strBuf == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(EXIT_FAILURE);
    }

    strcpy(strBuf, hello);
    strcpy(strBuf + helloLength, s);

    puts(strBuf);

    free(strBuf);

}

int main (void) {
    appendToHello("blah blah");
    return 0;
}

Я не знаю, насколько это правильно/безопасно, но сейчас я не мог найти лучший способ, чтобы сделать это в ANSI С.

Комментарии (11)

Лучший способ сделать это без того ограниченный размер буфера с помощью asprintf()

char* concat(const char* str1, const char* str2)
{
    char* result;
    asprintf(&result, "%s%s", str1, str2);
    return result;
}
Комментарии (2)

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

strcat ("Hello, ", name);

попытается сделать. Он будет пытаться лавировать на " имя " строку в конец строкового литерала `"Привет " Ну, которая не определена.

Попробовать что-то этого. Это достигает, что вы пытаетесь сделать:

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

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

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

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.
Комментарии (5)

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

char bigEnough[64] = "";

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

/* and so on */

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

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

Комментарии (0)

Вы можете написать свою функцию, которая делает то же самое как функции strcat (), но это вовсе't изменить что-либо:

#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
    static char buffer[MAX_STRING_LENGTH];
    strncpy(buffer,str1,MAX_STRING_LENGTH);
    if(strlen(str1) < MAX_STRING_LENGTH){
        strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
    }
    buffer[MAX_STRING_LENGTH - 1] = '\0';
    return buffer;
}

int main(int argc,char *argv[]){
    printf("%s",strcat_const("Hello ","world"));    //Prints "Hello world"
    return 0;
}

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

Комментарии (16)

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

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

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

Теперь давайте's идти через ваш код:

message = strcat("TEXT " + var);

Вот вы что-то добавляя к указатель к тексту и"текст" и (типа на "текст" это константный тип char*. Указатель.).

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

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

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

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

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

Читать документацию ом, чтобы проверить это's параметры.

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

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

Комментарии (1)

Если у вас есть чар[fixed_size], а не char, то вы можете использовать один, творческих макрос, чтобы сделать это все сразу с <<соиь<<как заказ (на"а % - ов разрозненных %з\п то", то "чем-то", "В Е формате и"). Если вы работаете со встроенными системами, этот метод также позволяет оставить malloc и семьи большие `ефункции, такие каки snprintf()` (это держит dietlibc от слишком жаловаться *е)


#include  //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset
Комментарии (0)

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

В частности:

...СНиП...

пунктом

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

Там'ы пример здесь.

Комментарии (0)
int main()
{
    char input[100];
    gets(input);

    char str[101];
    strcpy(str, " ");
    strcat(str, input);

    char *p = str;

    while(*p) {
       if(*p == ' ' && isalpha(*(p+1)) != 0)
           printf("%c",*(p+1));
       p++;
    }

    return 0;
}
Комментарии (0)

Это было мое решение

#include 
#include 

char *strconcat(int num_args, ...) {
    int strsize = 0;
    va_list ap;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) 
        strsize += strlen(va_arg(ap, char*));

    char *res = malloc(strsize+1);
    strsize = 0;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) {
        char *s = va_arg(ap, char*);
        strcpy(res+strsize, s);
        strsize += strlen(s);
    }
    va_end(ap);
    res[strsize] = '\0';

    return res;
}

но нужно указать, сколько строк вы'ре собирается объединить

char *str = strconcat(3, "testing ", "this ", "thing");
Комментарии (0)

Попробуйте что-то похожее на это:

#include 
#include 

int main(int argc, const char * argv[])
{
  // Insert code here...
  char firstname[100], secondname[100];
  printf("Enter First Name: ");
  fgets(firstname, 100, stdin);
  printf("Enter Second Name: ");
  fgets(secondname,100,stdin);
  firstname[strlen(firstname)-1]= '\0';
  printf("fullname is %s %s", firstname, secondname);

  return 0;
}
Комментарии (0)