Конкатенация нескольких строк? - PullRequest
1 голос
/ 05 марта 2011

Я обрабатываю входную строку, которая состоит из имени процесса, за которым следует произвольное количество аргументов.

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

Может кто-нибудь помочь мне с базовым кодом?

Спасибо.

РЕДАКТИРОВАТЬ: я публикую свой код для ясности.Пост Майка ближе всего к тому, что у меня сейчас:

    char * temp;
    strcpy(temp,"");
    for (i = 4; i < argc-1; i++) // last arg is null, so we need argc-1
    {
        strcat(temp,argv[i]);
        strcat(temp," ");
    }

на данный момент игнорирую 4 в моем цикле for (магическое число, я знаю). Я получаю ошибку с этим кодом.Это из-за моего назначения строки?Я предполагаю, что это так, и поэтому я задал вопрос о том, как я мог бы объединить строки.

Ответы [ 5 ]

5 голосов
/ 05 марта 2011

Допустим, ваши входные строки находятся в массиве char указателей, предположительно называемых argv, длины argc.

Сначала нужно определить, сколько места требуется для вывода:

int length = 0;
for (int i = 0; i < argc; ++i)
    length += strlen(argv[i]);

Затем мы выделяем его, добавляя дополнительный char для терминатора '\0':

char *output = (char*)malloc(length + 1);

Наконец, конкатенация:

char *dest = output;
for (int i = 0; i < argc; ++i) {
    char *src = argv[i];
    while (*src)
        *dest++ = *src++;
}
*dest = '\0';

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

Не забудьте освободить строку вывода, когда закончите:

free(output);

Я немного устал, поэтому я могу что-то упустить здесь. Лучшее решение, использующее стандартные библиотечные функции, приветствуется. Было бы удобно, если бы strcat вернул указатель на байт терминатора в dest, но, увы.

1 голос
/ 05 марта 2011

Вы хотите пустую строку C? Это то, что вы ищете: char p[] = "";?


UPDATE

После того, как вы разместили некоторый код, становится ясно, что вы забыли выделить буфер temp. Сначала просто обойдите аргументы, посчитав необходимую длину (используя strlen), а затем выделите temp. Не забывайте место для нулевого терминатора!

0 голосов
/ 05 марта 2011
    #include<stdio.h>
    #include<stdarg.h>

    int main(int argc, char** argv) { 
            // the main parameters are the same situation you described
            // calling this program with    main.exe asdf 123 fdsa, the program prints out: asdf123fdsa

            int lengths[argc];
            int sum =0;
            int i;
            for(i=1; i<argc; i++) { // starting with 1 because first arg is program-path
                    int len = strlen(argv[i]);
                    lengths[i] = len;
                    sum+=len;
            }
            char* all = malloc(sum+1);
            char* writer = all;
            for(i=1; i<argc; i++) {
                    memcpy(writer, argv[i], lengths[i]);
                    writer+=lengths[i];
            }
            *writer = '\0';
            printf("%s\n", all);

            system("pause");
            return 0;
    }
0 голосов
/ 05 марта 2011

Строка в C представлена ​​массивом символов, оканчивающимся нулевым символом, '\ 0' со значением 0. Это позволяет всем строковым функциям знать, где находится конец строки. Вот исследование различных способов объявления пустой строки и их значения.

Обычный способ получить пустую строку будет

char* emptyString = "";

Однако emptyString теперь указывает на строковый литерал, который нельзя изменить. Если затем вы хотите объединить пустую строку в цикле, вы должны объявить ее как массив при инициализации.

char buffer[] = "";

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

char buffer[256] = "";

Строка в buffer теперь является «пустой строкой». buffer[0] равно 0, а остальные записи в буфере могут быть мусором, но они будут заполнены, как только вы объедините другие строки.

К сожалению, проблема с C в том, что вы никогда не можете иметь "бесконечную" строку, где вы можете безопасно конкатенировать, у вас есть , чтобы знать, что она имеет определенный размер с самого начала. Если ваш массив аргументов также является строками, вы можете найти их длину, используя strlen. Это дает вам длину строки, без нулевого символа. Как только вы узнаете длину всех ваших подстрок, вы будете знать, как долго будет длиться ваш последний буфер.

int totalSize; // assume this holds the size of your final concatenated string
// Allocate enough memory for the string. the +1 is for the null terminator
char* buffer = malloc(sizeof(char) * (totalSize + 1));
buffer[0] = 0; // The string is now seen as empty.

После этого вы можете свободно объединять строки, используя strcat.

0 голосов
/ 05 марта 2011

Вы можете предоставить «произвольное количество аргументов» в качестве одного аргумента, то есть массив / список, а затем сделать этот псевдокод:

str = "";
i = 0;
while i < length of input
{
str = strcat ( str , input[i]);
i++;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...