Как объединить константные / литеральные строки в C? - PullRequest
299 голосов
/ 21 ноября 2008

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

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

message = strcat("TEXT ", var);

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

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

Ответы [ 17 ]

2 голосов
/ 29 июля 2016

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

#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 в соответствии с вашими потребностями.

1 голос
/ 05 ноября 2016
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;
}
1 голос
/ 14 декабря 2014

Предполагая, что у вас есть символ [fixed_size], а не символ *, вы можете использовать один творческий макрос, чтобы сделать все это одновременно с упорядочением <<cout<<like ("скорее% s несвязанный% s \ n", "чем", "формат стиля printf"). Если вы работаете со встроенными системами, этот метод также позволит вам исключить malloc и большое семейство функций *printf, таких как snprintf() (Это не дает диетам жаловаться на * printf тоже)

#include <unistd.h> //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<(int)sizeof(buf))) \
            *bp++=*s++; \
    if (offset!=sizeof(buf))*bp=0; \
}while(0)

char buf[256];
int len=0;

strcpyALL(buf,len,
    "The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
    write(1,buf,len); //outputs our message to stdout
else
    write(2,"error\n",6);

//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
    write(1,buf,len); //outputs both messages
else
    write(2,"error\n",6);
  • Примечание 1, вы, как правило, не используете argv [0] вот так - просто пример
  • Примечание 2, вы можете использовать любую функцию, которая выводит символ *, включая нестандартные функции, такие как itoa (), для преобразования целых чисел в строковые типы.
  • Примечание 3: если вы уже используете printf где-либо в своей программе, нет причин не использовать snprintf (), так как скомпилированный код будет больше (но встроен и значительно быстрее)
1 голос
/ 21 ноября 2008

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

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

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

Теперь пройдемся по вашему коду:

message = strcat("TEXT " + var);

Здесь вы добавляете что-то к указателю на текст «TEXT» (тип «TEXT» является const char *. A pointer.).

Это обычно не работает. Также модификация массива «TEXT» не будет работать, так как он обычно помещается в постоянный сегмент.

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

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

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

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

Прочтите документацию sprintf, чтобы проверить ее параметры.

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

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

1 голос
/ 21 ноября 2008

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

В частности:

... чик ...

назначения

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 голосов
/ 31 декабря 2016

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

#include <stdlib.h>
#include <stdarg.h>

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 голосов
/ 10 апреля 2014

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

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

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...