Разбить массив символов на два массива символов - PullRequest
0 голосов
/ 12 июля 2011

Я хотел бы разбить один массив символов char, содержащий две "строки", разделенные '|'в два ряда символов.

Вот мой пример кода.

void splitChar(const char *text,  char *text1, char *text2)
{
   for (;*text!='\0' && *text != '|';) *text1++ = *text++;
   *text1 = '\0';
   for (;*++text!='\0';) *text2++ = *text;
   *text2 = '\0';
}

int main(int argc, char* argv[])
{

    char *text = "monday|tuesday", text1[255], text2 [255];
    splitChar (text, text1, text2);
    return 0;
}

У меня два вопроса:

  1. Как еще улучшить этот кодв C (например, переписать его в 1 для цикла).

  2. Как переписать этот код в C ++?

Ответы [ 7 ]

2 голосов
/ 12 июля 2011

Если вы хотите написать это на C ++, используйте STL

string s = "monday|tuesday";  
int pos = s.find('|');  
if(pos == string::npos)  
    return 1;  
string part1 = s.substr(0, pos);  
string part2 = s.substr(pos+1, s.size() - pos);
1 голос
/ 12 июля 2011

Для A, используя внутренние библиотеки:

void splitChar(const char *text,  char *text1, char *text2)
{
    int len = (strchr(text,'|')-text)*sizeof(char);
    strncpy(text1, text, len);
    strcpy(text2, text+len+1);
}
1 голос
/ 12 июля 2011

Я не знаю об A), но для B) Вот метод из служебной библиотеки, которую я использую в различных проектах, показывающий, как разбить любое количество слов на vector.Он закодирован для разделения на пробел и табуляцию, но вы можете передать это как дополнительный параметр, если хотите.Возвращает количество разделенных слов:

unsigned util::split_line(const string &line, vector<string> &parts)
{
    const string delimiters = " \t";
    unsigned count = 0;
    parts.clear();

    // skip delimiters at beginning.
    string::size_type lastPos = line.find_first_not_of(delimiters, 0);

    // find first "non-delimiter".
    string::size_type pos = line.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // found a token, add it to the vector.
        parts.push_back(line.substr(lastPos, pos - lastPos));
        count++;

        // skip delimiters.  Note the "not_of"
        lastPos = line.find_first_not_of(delimiters, pos);

        // find next "non-delimiter"
        pos = line.find_first_of(delimiters, lastPos);
    }

    return count;
}
0 голосов
/ 12 июля 2011

Я прошу прощения за мой ответ :) Никто не должен попробовать это дома.

Чтобы ответить на первую часть вашего вопроса.

A] Как еще улучшить этот код в C (например, переписать его в 1 для цикла).

Сложность этого алгоритма будет зависеть от того, где находится позиция '|' находится в строке, но этот пример работает только для 2 строк, разделенных '|'. Вы можете легко изменить его позже для более чем.

#include <stdio.h>

void splitChar(char *text,  char **text1, char **text2)
{
    char * temp = *text1 = text;
    while (*temp != '\0' && *temp != '|') temp++;

    if (*temp == '|') 
    {
        *temp ='\0';
        *text2 = temp + 1;
    }
}

int main(int argc, char* argv[])
{

    char text[] = "monday|tuesday", *text1,*text2;
    splitChar (text, &text1, &text2);
    printf("%s\n%s\n%s", text,text1,text2);
    return 0;
}

Это работает, потому что массивы в стиле c используют нулевой символ для завершения строки. Поскольку инициализация символьной строки с помощью «» добавит нулевой символ в конец, все, что вам нужно сделать, это заменить вхождения «|» с нулевым символом и назначьте другие символьные указатели следующему байту после '|'.

Вы должны обязательно инициализировать исходную символьную строку с помощью [], поскольку это говорит компилятору выделить хранилище для вашего символьного массива, где char * может инициализировать строку в статической области памяти, которую нельзя изменить.

0 голосов
/ 12 июля 2011

Я обнаружил, что деструктивное разделение - лучший баланс производительности и гибкости.

void split_destr(std::string &str, char split_by, std::vector<char*> &fields) {
    fields.push_back(&str[0]);
    for (size_t i = 0; i < str.size(); i++) {
        if (str[i] == split_by) {
            str[i] = '\0';
            if (i+1 == str.size())
                str.push_back('\0');
            fields.push_back(&str[i+1]);
        }
    }
}

Тогда неразрушающий вариант для ленивых.

template<typename C>
    void split_copy(const std::string &str_, char split_by, C &container) {
        std::string str = str_;
        std::vector<char*> tokens;
        parse::split_destr(str, split_by, tokens);
        for (size_t i = 0 ; i < tokens.size(); i++)
            container.push_back(std::string( tokens[i] ));
    }

Я пришел к этому, когда такие вещи, как boost :: Tokenizer, потерпели неудачу при работе с файлами размера gb +.

0 голосов
/ 12 июля 2011

Посмотрите на пример, приведенный здесь: strtok, wcstok, _mbstok

0 голосов
/ 12 июля 2011

Возможно, будет работать одно из следующих решений: Разбить строку в C ++?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...