Страницы

Поиск по вопросам

Показаны сообщения с ярлыком строки. Показать все сообщения
Показаны сообщения с ярлыком строки. Показать все сообщения

четверг, 9 апреля 2020 г.

Как прочитать с консоли строку неизвестной заранее длины не используя string?

#cpp #массивы #char #строки

                    
Я прекрасно понимаю, что можно использовать класс string и просто написать cin>>
 str; а затем получить количество элементов.
Я даже видел веселое решение при помощи malloc и realloc функций из C.
но все же, интересно, есть ведь какой-то способ при помощи средств C++, а конкретно
их потоков ввода и стандартных строк в виде массива символов прочитать из консоли строку,
не имея понятия о ее размере, получить впоследствии ее размер и положить в динамически
выделенный массив такого размера??
Вопрос не к спеху и не для какого-то задания, все чисто ради интереса, так что ваши
ответы, типа "не парься и пользуйся тем, что дают" также приветствуются )
    


Ответы

Ответ 1



cin >> str; запишет только до первого разделителя: http://ideone.com/Y5CJxD. Если под строкой понимается последовательность, которая заканчивается переводом строки ('\n'), то вам: std::getline() нужен: http://www.cplusplus.com/reference/string/string/getline/ А так, std::string это и так стандартное средство в C++. Если же хочется извратиться, то нужно читать блоками, проверять - есть ли перевод строки и агрегировать код, но лишнее нужно как-то хранить между вызовами. Либо, что проще, но медленнее - читать посимвольно, проверяя конец строки, например так: istream& getline(istream& is, char *&buffer) { std::istream::sentry s(is); if (s) { std::istreambuf_iterator it(is); std::istreambuf_iterator end; size_t size = 64; size_t grow = 64; size_t len = 0; buffer = new char[size]; while (it != end && *it != '\n') { if (len == (size - 1)) { buffer = buffer_realloc(buffer, size, size + grow); size += grow; } buffer[len++] = *it++; } buffer[len] = '\0'; } return is; } Здесь я не привожу функцию buffer_realloc() - она простая. Использовать как-то так: char *line = nullptr; while (getline(std::cin, line)) { if (line) { cout << line << endl; delete[] line; } } Либо вот вариант, где использует вектор: istream& getline(istream& is, vector &buffer) { std::istream::sentry s(is); if (s) { std::istreambuf_iterator it(is); std::istreambuf_iterator end; const size_t grow = 64; buffer.reserve(grow); while (it != end && *it != '\n') { if (buffer.size() == buffer.capacity() - 1) { buffer.reserve(buffer.size() + grow); } buffer.push_back(*it++); } buffer.push_back('\0'); } return is; } Использовать как-то так: vector line; while (getline(std::cin, line)) { if (!line.empty()) { cout << line.data() << endl; line.clear(); } } Тут реаллокация памяти ложится на плечи vector'а. От вас только почистить его (а можно и в гетлайн всунуть). Плюс бонусом сразу длинна строки за O(1): line.size() - 1 Вот законченные примеры: http://ideone.com/Huj4eQ http://ideone.com/CxNfg4 Но повторюсь: std::string стандартны для С++. Я слабо представляю условия, где есть потоки, но нет строк :)

Ответ 2



По сути, реализация cin выглядит так (игнорируя тот факт, что оба потока и строка шаблоны): std::istream& operator>> (std::istream& in, std::string& value) { std::istream::sentry cerberos(in); if (cerberos) { value.erase(); std::istreambuf_iterator it(in), end; if (it != end) { std::ctype const& ctype(std::use_facet >(in.getloc())); std::back_insert_iterator to(value); std::streamsize n(0), width(in.width()? in.width(): std::string::max_size()); for (; it != end && n != width && !ctype.is(std::ctype_base::space, *it); ++it, ++to) { *to = *it; } } } else { in.setstate(std::ios_base::failbit); } return in; } Выводы думаю вы можете сделать сами.

Ответ 3



Немного странный вопрос, т.к. если нужно сделать то же самое, что можно сделать с помощью std::string - следует хотя бы посмотреть реализацию operator>> для потока ввода и строкового аргумента. Основной смысл в том, что читаем посимвольно и посимвольно же добавляем. В итоге получим ещё и некоторое подобие реализации std::vector для символьного типа.

четверг, 2 апреля 2020 г.

Преобразовать массив строк из статического в динамический

#c #строки

                    
нашел код

char string[]=  "abc/qwe/jkh";
char *array[10];
int i=0;

array[i] = strtok(string,"/");

while(array[i]!=NULL)
{
   array[++i] = strtok(NULL,"/");
}


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

#include 
#include 

char *string = "Value1,123,Value2,456,Value3,789,"; // запятая в конце необходима
char **array_of_strings = NULL; // указатель на указатель строк
int i = 0;
long comma_counter = 0;
int eachLine = 0;

// считаем количество запятых, чтобы понять сколько нам нужно памяти

for (i = 0; i < strlen(string); i++) {
    if (string[i] == ',') {
        comma_counter++;
    }
}
printf("Commas counted: %d\n", (int)comma_counter);

array_of_strings = malloc(comma_counter * sizeof(char*)); // выделяем столько сколько
насчитали 

if (array_of_strings == NULL) {
    printf("Memory allocation failed!");
    exit(1);
}


И вот первая проблема. strok возвращает указатель, и мне его нужно записать в array_of_strings
позиция 0.

Как записать строку в array_of_strings[0]?

---> = strtok(string, ",");
--->printf("%s\n", array_of_strings[eachLine]);

--->while(*array_of_strings) // дальше надо делать снова вызов выделения памяти
--->{
--->    array_of_strings = malloc();
--->    array_of_strings[++i] = strtok(NULL, ",");
--->    array_of_strings++;
--->}


// ну а это будущий вывод строк на экран
for (i = 0; i < comma_counter; i++) {
    printf("%s\n", array_of_strings[i]);
}

    


Ответы

Ответ 1



Пример разбивки строк есть здесь. Часто пользуюсь этим ресурсом. Что-то такое может быть: char string[] = "Value1,123,Value2,456,Value3,789,"; int comma_counter=6; char *pCh; char **array_of_strings=(char**)malloc(sizeof(pCh)*comma_counter); //переменная string изменится int k=0; char * pch= strtok(string, ","); while(pch!=NULL) { array_of_strings[k] = (char*)malloc(strlen(pch)*sizeof(char)+1); if (array_of_strings[k]==NULL) exit (1); strcpy(array_of_strings[k], pch); pch = strtok (NULL, ","); k++; if(k==comma_counter) pch=NULL; } printf ("%s \n %s", array_of_strings[0],array_of_strings[comma_counter-1]); //не забывайте освобождать память for(int i=0;i

понедельник, 30 марта 2020 г.

Как при помощи регулярных выражений получить часть текста

#java #регулярные_выражения #строки


Есть входная строка:

String input = " 2777461-1

Стол: 1 < /td>"; Pattern pattern = Pattern.compile("\\+?(.*)"); Matcher matcher = pattern.matcher(input); while (matcher.find()) { System.out.println(matcher.group()); } необходимо создать из этой строки 3 переменные code = 2777461-1 furniture = Стол count = 1 ошибок нет, но и даже code не удалось получить результат: 2777461-1 Может я ошибаюсь и регулярными выражениями такое не решается?


Ответы

Ответ 1



Самый обычный вариант - использовать парсер, к примеру, jsoup. В вашем случае способ получить данные из документа будет выглядеть так: String input = " " + "2777461-1" + "

" + "" + "Стол: " + "

1

" + "
" + ""; Document html = Jsoup.parse(input); String strong = html.body().getElementById("strong").text(); String furniture = html.body().getElementById("furniture").text(); String count = html.body().getElementById("count").text(); Изучайте библиотеку, у нее есть масса способов парсинга html-документов. Ремарка: для доступа к данным проще использовать id, который вы назначаете на нужный тэг. К примеру, если в документе будет 2 тэга , то по id вытащить строку будет оптимальнее (я подправил ваш исходный html, обратите на это внимание).

воскресенье, 29 марта 2020 г.

Как преобразовать string в char?

#cpp #строки #char #преобразование


Есть произвольная строка не больше 25 символов. Например "wo1fram"
Как преобразовать ее в массив char[255]?
Чтобы потом с char можно было работать как с полноценным массивом символов, оканчивающимся
нуль-символом.
    


Ответы

Ответ 1



Тут, видите ли, есть два решения. Одно - если вам надо только читать эту строку, или там, поменять в ней пару символов - но не менять ее размер (так что всякие strcpy отменяются) - то можно воспользоваться функциями c_str() и data(). Очень рекомендую внимательно почитать описания, а главное - ограничения, накладываемые этими функциями. И другое - если нужно работать с ней как со строкой в стиле С со всеми возможностями - то просто скопируйте ее в массив, типа char buf[255]; strcpy(buf,s.c_str()); или char * buf = strdup(s); Примерно так.

суббота, 21 марта 2020 г.

Поиск “скрытой” подстроки в строке

#алгоритм #строки #поиск #подстрока


Надо узнать если ли в строке "раздробленная" подстрока.
Пример:

У нас имеется строка и предпологаемая подстрока, надо просто вывести true или false
если такая трока имеется
    


Ответы

Ответ 1



string a, b; cin >> a >> b; int bIndex=0; for (size_t i = 0; i < a.size(); i++) { if (b[bIndex] == a[i]) { bIndex++; } } if (bIndex==b.size()) { cout << "YES"; } else { cout << "NO"; }

воскресенье, 15 марта 2020 г.

Определить, какие ключевые слова языка Java содержит файл

#java #строки #java_ee #arraylist


Нагуглил только contains, но он почему-то не работает.. видимо делаю что-то не так

keyWords - ArrayList


sortingList тоже, я так понимаю нужно каким-то образом сравнить все слова в файле
со списком моих слов, а как чет не доходит

for (int i = 0; i < 50; i++) {
    if (sortingList.get(index).contains(keyWords.get(i))) {
        counter++;              
    }
}


Ответ ниже помог, но теперь проблема с повторяющимися словами. они не учитываются

for (String st : keyWords) {
                for (String g : sortingList) {
                    if (st.contains(g) && g.length() > 1) {

                        sortedList.add(g);
                        counter++;
                    }
                }
            }

    


Ответы

Ответ 1



Если честно я не совсем понял вопроса. Вы хотите в увеличивать counter за каждое совпадение слов? Если да, то лучше воспользоваться циклом for-each и сделать вот так. for (String s : keyWords) { for (String g : sortingList) { if (s.contains(g)) { counter++; } } }

воскресенье, 8 марта 2020 г.

Из текстового файла в строки C#

#c_sharp #строки #файлы


Допустим есть текстовый файл, в котором в каждой строке лежит слово и последовательность
цифр. Как мне поместить в одну строку только слова, а в другую - только цифры?

Пример файла:

testText0 1 2 3 4
testText1 2 4

    


Ответы

Ответ 1



Кроме решений в лоб всегда остаётся вариант использования регулярных выражений. using System.Text.RegularExpressions; ........ var Lines = File.ReadAllLines("MyFileName.txt"); var RegEx = new Regex(@"^([a-zA-Z]+)([\d\s]+)$"); var Words = new List(); var Digits = new List(); foreach (var Line in Lines){ var Matches = RegEx.Match(Line); Words.Add(Matches.Groups[1].ToString()); Digits.Add(Matches.Groups[2].ToString()); } Этот подход хорош еще и тем, что он автоматически валидирует входные данные. Проверить регулярные выражения можно тут.

Ответ 2



Ну например как-то так: var digits = "0123456789".ToArray(); var lines = File.ReadLines(path); var linesWithBreakingIndices = lines.Select(line => new { line, index = line.IndexOfAny(digits) }).ToList(); var justWords = string.Join(" ", linesWithBreakingIndices.Select(li => li.line.Substring(0, li.index))); var justDigits = string.Join(" ", linesWithBreakingIndices.Select(li => li.line.Substring(li.index))); Вариант без LINQ: var digits = "0123456789".ToArray(); var lines = File.ReadLines(path); StringBuilder justWordsBuilder = new StringBuilder(), justDigitsBuilder = new StringBuilder(); var first = true; foreach (var line in lines) { var index = line.IndexOfAny(digits); if (!first) { justWordsBuilder.Append(' '); justDigitsBuilder.Append(' '); } justWordsBuilder.Append(line, 0, index); justDigitsBuilder.Append(line, index, line.Length - index); first = false; } var justWords = justWordsBuilder.ToString(); var justDigits = justDigitsBuilder.ToString();

Обработка строки даты

#cpp #строки


Пользователь вводит дату в формате 01/02/17, нужно сохранить дату в трёх переменных
int соответственно-day,month,year. Я разбивал строку с датой на 3 подстроки и переводил
в каждую в int. Мне кажется-не самый лучший способ. Есть ли како-то более удачное решение
для такой обработки?
    


Ответы

Ответ 1



Можно и удобно регэкспами: #include #include std::vector GetDigitDate(const std::string Date) { std::regex Rx("^(\\d{1,2})/(\\d{1,2})/(\\d{2}|\\d{4})$"); std::smatch Match; if(!(std::regex_match(Date, Match, Rx) && (Match.size()==4))) throw std::runtime_error(""); return {std::stoi(Match[1]),std::stoi(Match[2]),std::stoi(Match[3])}; } int main() { try { std::vector T = GetDigitDate("1/07/2011"); for(const auto &i:T) std::cout << i << std::endl; } catch(...) { std::cout << "Что-то не так!" << std::endl; } return 0; } Естественно, при желании, можно дополнить проверку корректности дней, месяцев и годов. В коде - простейшая проверка просто на числа. ADD: Если не нравится возврат вектора, в качестве результата, небольшая модификация кода, но для C++1z #include #include std::tuple GetDigitDate(const std::string Date) { std::regex Rx("^(\\d{1,2})/(\\d{1,2})/(\\d{2}|\\d{4})$"); std::smatch Match; if(!(std::regex_match(Date, Match, Rx) && (Match.size()==4))) throw std::runtime_error(""); return {std::stoi(Match[1]),std::stoi(Match[2]),std::stoi(Match[3])}; } int main() { try { auto [d,m,y] = GetDigitDate("1/07/2011"); std::cout << "d: " << d << " m: " << m << " y: " << y << std::endl; } catch(...) { std::cout << "Что-то не так!" << std::endl; } return 0; }

Ответ 2



Вариант, который использует QDate::fromString() из Qt: #include #include int main(int argc, char* argv[]) { const char* date_string = (argc == 2) ? argv[argc-1] : "01/02/17"; QDate d = QDate::fromString(date_string, "dd/MM/yy"); d = d.addYears(100); // 19yy -> 20yy int year, month, day; d.getDate(&year, &month, &day); qDebug() << year << month << day; return !year; // if the year is zero; the date is invalid } Код автоматически проверяет, что введённая дата является корректной (кол-во дней в месяце, високосные годы, итд). Пример: $ ./parse-date 5/10/14 2014 10 5 Двузначный год интерпретируется всегда как 19yy, поэтому 00 (2000) не распознаётся как високосный год (важно для 2000-02-29).

Ответ 3



А почему не воспользоваться просто scanf? Эта функция и в C++ работает: int day, month, year; if (sscanf("01/02/17","%d/%d/%d",&month,&day,&year) == 3) { printf("Date is %02d.%02d.%d\n",day,month,year+2000); }

суббота, 7 марта 2020 г.

Регулярное выражение для возврата первого (до пробела) слова строки

#c_sharp #регулярные_выражения #строки


Пробовал сделать вот так:

string pattern = @"^\s+";
Regex regex = new Regex(pattern, RegexOptions.Singleline);


но когда пытаюсь выполнить

 Match match = regex.Match("list command");


мне возвращает "".
    


Ответы

Ответ 1



Скорее всего, вы просто перепутали большую и маленькую S \s - это пробельный символ \S - это любой символ кроме пробельного, нужно написать так: ^\S+ или для верности: ^\S+\s

Как задать значение для переменной типа string от пользователя

#c_sharp #строки


Как в C# можно задать значение для string, что бы пользователь при работе с программой
ввел к примеру свое имя в эту переменную.
В С++ у меня получалось так.

string name;
getline(std::cin, name);
cout << name;


В С# все иначе как я понимаю.
Пробовал вот так:

string name;
name = Convert.ToString(Console.ReadLine());
Console.Write(name);


и так

string name;
Console.ReadLine(name);
Console.Write(name);


Ничего не получается. На MSDN примеры все указаны с учетом того, что я заранее уже
что то записал в строку. Как тогда в С# работать с словами? Мне элементарно надо в
программе, что бы пользователь ввел свое имя по запросу и потом уже вывести приветствие
и имя.
    


Ответы

Ответ 1



Функция ReadLine считывает строку с консоли и возвращает ее пользователю функции. Поэтому достаточно написать, например, string name; name = Console.ReadLine(); Console.WriteLine( name );

Ответ 2



метод Console.ReadLine() не принимает аргументов. Он возвращает строку, считанную с консоли после нажатия клавиши Enter: string name = Console.ReadLine();

понедельник, 2 марта 2020 г.

Удаление из строки служебных частей речи(союзы, предлоги частицы, междометия и др.) Python 3

#python #python_3x #строки #обработка #морфология


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

Пример:
Строка до применения: "Однако я так и не смог закончить"
Строка после применения: "я не смог закончить"
    


Ответы

Ответ 1



Если вы хотите удалить избранные части речи из строки, то можно части речи определить [к примеру] используя pymorphy2: import pymorphy2 # $ pip install pymorphy2 def pos(word, morth=pymorphy2.MorphAnalyzer()): "Return a likely part of speech for the *word*.""" return morth.parse(word)[0].tag.POS words = "Однако я так и не смог закончить".split() functors_pos = {'INTJ', 'PRCL', 'CONJ', 'PREP'} # function words print(*[word for word in words if pos(word) not in functors_pos]) # -> я смог закончить Часть речи по одному только слову может быть неверно определена. В частном случае, вы можете просто свой набор слов для удаления поддерживать. Можно разобрать части речи, используя averaged_perceptron_tagger_ru из nltk: import nltk # $ pip install nltk # nltk.download('averaged_perceptron_tagger_ru') words = nltk.word_tokenize("Однако я так и не смог закончить") functors_pos = {'CONJ', 'ADV-PRO', 'CONJ', 'PART'} # function words print(*[word for word, pos in nltk.pos_tag(words, lang='rus') if pos not in functors_pos]) # -> я смог закончить

пятница, 28 февраля 2020 г.

Как получить числа из строки и корректно отсортировать?

#python #строки #list


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

import re

try:
    file_path = open(input('Введите путь к файлу: '))
except IOError:
    print('File not found')
file_value = file_path.read()
file_numbers = re.findall('\d+', file_value)
# print(file_numbers)
# print(type(file_numbers))
sorted(file_numbers, key=int)
print(file_numbers)
sorted(file_numbers, key=int, reverse=True)
print(file_numbers)


Собственно результат:


['6', '2', '3', '13', '5', '1', '7', '9', '18', '20', '16', '12', '15', '14', '10',
'11', '17', '9', '19']
['6', '2', '3', '13', '5', '1', '7', '9', '18', '20', '16', '12', '15', '14', '10',
'11', '17', '9', '19']



В чем ошибка и как поправить? :(

Так же были попытки сделать вот так:

try:
    file_path = open(input('Введите путь к файлу: '))
except IOError:
    print('File not found')
file_value = file_path.read()
# file_numbers = re.findall('\d+', file_value)
file_numbers = []
for i in file_value:
    try:
        num = int(i)
        file_numbers.append(num)
    except ValueError:
        continue
# print(file_numbers)
# print(type(file_numbers))
sorted(file_numbers, key=int)
print(file_numbers)
sorted(file_numbers, key=int, reverse=True)
print(file_numbers)


И на выходе получил вообще бред:


[6, 2, 3, 1, 3, 5, 1, 7, 9, 1, 8, 2, 0, 1, 6, 1, 2, 1, 5, 1, 4, 1, 0, 1, 1, 1, 7,
9, 1, 9]
[6, 2, 3, 1, 3, 5, 1, 7, 9, 1, 8, 2, 0, 1, 6, 1, 2, 1, 5, 1, 4, 1, 0, 1, 1, 1, 7,
9, 1, 9]


    


Ответы

Ответ 1



И на выходе получил вообще бред: Ваш код sorted(file_numbers, key=int) правильно был написан, но sorted возвращает новый отсортированный список, не изменяя исходный, поэтому вам нужно было сделать так: file_numbers = sorted(file_numbers, key=int) Можно отсортировать "на месте", как вы и хотели, но для этого нужно будет использовать sort: file_numbers.sort(key=int)

Ответ 2



Прежде всего, после получения списка строк, превратите его в список чисел: file_numbers = [int(number) for number in file_numbers] Затем - чтобы максимально сохранить ваш код - используйте вместо функции sorted() метод списка sort() (для прямой сортировки списка на месте): file_numbers.sort() print(file_numbers) file_numbers.sort(reverse=True) # или - более ефективно - file_numbers.reverse() print(file_numbers) Вывод: [1, 2, 3, 5, 6, 7, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 9, 7, 6, 5, 3, 2, 1]

четверг, 27 февраля 2020 г.

Как заменить повторяющиеся группы элементов с помощью replaceAll?

#java #строки


Вопрос относительно метода replaceAll в String.

Допустим, есть строка, содержащая строковое представление xml, где повторяются элементы:


 
  Alex
  Gazprom
 
 
  Irina
  Lukoil
 
.*", "Rosneft");


То получится так:


 
  Alex
  Rosneft
 


Ответы

Ответ 1



Для отключения "жадности" поиска используется квантификатор ?: line.replaceAll(".*?", "Rosneft"); Описание работы квантификаторов, например, есть здесь и здесь

среда, 26 февраля 2020 г.

Заменить %-string на f-string

#python #python_3x #строки #print


Как правильно написать выражение

"%(a)03d%(b)029d" % {"a": 1, "b": 2}, 

используя f-string
    


Ответы

Ответ 1



In [3]: a,b = 1,2 In [4]: print(f"{a:03d}{b:029d}") 00100000000000000000000000000002 или In [5]: d = {"a": 1, "b": 2} In [6]: print(f"{d['a']:03d}{d['b']:029d}") 00100000000000000000000000000002 Пример использования переменных для задания формата: In [9]: fmt1,fmt2 = "03d", "029d" In [10]: print(f"{d['a']:{fmt1}}{d['b']:{fmt2}}") 00100000000000000000000000000002

Решение строкового математического выражения

#java #строки #package


Есть ли в java нативный метод для такого рода вещей, чтобы самому не писать?
Вроде  

String expr = "1 + 2 * 3";
Double result = WonderClass.wonderMethod(expr);
System.out.println(result);




7.0

    


Ответы

Ответ 1



Да, можно использовать Java Scripting API Вполне подойдет JavaScript (его движок входит в состав JDK): ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine engine = scriptEngineManager.getEngineByName("JavaScript"); String expr = "1 + 2 * 3"; System.out.println(engine.eval(expr));

Не понимаю принцип переворота строки

#java #алгоритм #строки #reverse #substring


public class StringReverseAlgorithm {
    public static void main(String[] args) {
        System.out.println(reverseStringWithRecursion("Как это работает?"));
    }
    public static String reverseStringWithRecursion(String inputString) {
        String rightPart;
        String leftPart;

        int length = inputString.length();

        // заканчиваем рекурсивный обход
        if (length <= 1) {
            return inputString;
        }


Что происходит в следующих 2 строках? Почему мы доходим до среднего символа в leftPart,
начинаем с того же среднего символа в rightPart, но символ не дублируется?

        leftPart = inputString.substring(0, length / 2);

        rightPart = inputString.substring(length / 2, length);


Почему, если мы меняем местами только правую и левую часть, переворачивается вся
строка, то есть все символы записываются в обратном порядке?

 return reverseStringWithRecursion(rightPart) + reverseStringWithRecursion(leftPart);
    }
}

    


Ответы

Ответ 1



Если вы пишете str.substring(a, b), то вы берёте подстроку с символа с номером a, до символа с номером b - 1, в терминах математики вы указываете полуинтервал [a, b), то есть левый конец включается, а правый нет. В строках leftPart = inputString.substring(0, length / 2); rightPart = inputString.substring(length / 2, length); вы берёт строку [1 .. n] (это написаны индексы символов) и разваливаете её в две подстроки: [1 .. n/2 - 1] и [n/2 .. n], затем каждую из них переворачиваете рекурсивным вызовом, получаются строки [n/2 - 1 .. 1] и [n .. n/2], и, меняя местами, склеиваете обратно, получается: [n .. n/2] + [n/2 - 1 .. 1] = [n .. n/2 n/2 - 1 .. 1] = [n .. 1], строка в обратном порядке, что и было заявлено.

Ответ 2



Дополню ответ zcorvid: В конце мы передаём строку в принимаемое значение, что приводит к тому, что метод выполняется заново и это происходит до тех пор, пока половины строк больше одного символа

Ответ 3



Почему мы доходим до среднего символа в leftPart, начинаем с того же среднего символа в rightPart, но символ не дублируется? Читайте документацию. В классе String метод substring принимает на вход полуоткрытый интервал [а, b). То есть правый край интервала не входит в возвращаемую подстроку. Таким образом, никакого "дублирования символа" тут нет и не должно быть. Символ с индексом length / 2 попадет только в правую подстроку, но не в левую. Почему, если мы меняем местами только правую и левую часть, переворачивается вся строка, то есть все символы записываются в обратном порядке? Мы не просто меняем местами правую и левую часть. Мы еще предварительно выполняем рекурсивный вызов той же самой функции reverseStringWithRecursion для правой и левой части в отдельности. В результате правая и левая части переворачиваются. Несложно убедиться, что это приведет к перевороту исходной строки.

вторник, 25 февраля 2020 г.

Java: конкатенация строк и Integer.getInteger

#строки #java


Здравствуйте! Столкнулся с проблемой парснига int, объясните, пожалуйста, как думает
компилятор в этот момент и почему он не хочет выдавать мне правильное значение.
String s = "task_123";
String[] paths = s.split("_");
int type = 1;
int i = Integer.getInteger(Integer.toString(type) + paths[1], 0);
int j = Integer.getInteger(type + paths[1], 0);
System.out.println(i);
System.out.println(j);

Выводится 0, 0, а должен 1123, 1123
Как так?
Код на ideone.com    


Ответы

Ответ 1



Компилятор здесь не при чем. Вы используете не тот метод (см. javadoc Integer.getInteger). Вы пытаетесь получить значение типа Integer, которое соответствует имени системного свойства. Т.к. это свойство не определено, то возвращается значение по умолчанию 0, которое вы сами и указали в вызове метода getIneteger. Замените вызов getInteger на parseInt.

понедельник, 24 февраля 2020 г.

PHP: Вставить пробел каждые N символов но начиная с конца

#php #строки


Как вставить пробел на РНР каждые N символов но начиная отсчет не с начала строки
а с конца. Например чтобы с 1234567 получить 1 234 567 (если каждые три символа). chunk_split
и wordwrap работают лишь со значениями больше 0

Можно в принципе вот так:

$reverse = strrev("1234567");
$withSpaces = chunk_split($reverse, 3, ' ');
echo strrev($withSpaces);


Но может есть что то проще
    


Ответы

Ответ 1



number_format Если вкратце: Вводимое число Сколько символов после "точки" Разделитель "точки" Разделитель тысячных (каждый третий с конца) Пример: echo number_format(1000000, 0, '.', ' '); // 1 000 000 echo number_format(1000000, 2, '.', ','); // 1,000,000.00

Python, разделение строки по символам через метод re.split

#python #python_3x #строки #split


Необходимо разделить входящую строку по числам и буквам, например:

s = "k10Z18i13Q19u"
a = re.split("(\d*)", s)


На выходе получим:

['k', '10', 'Z', '18', 'i', '13', 'Q', '19', 'u']


Но так же получим ошибку:

FutureWarning: split() requires a non-empty pattern match.
  return _compile(pattern, flags).split(string, maxsplit)


Данный метод очень подходит для решения моей задачи, но не пойму, отчего ошибки.
Именно шаблон для разделения строки (\d*) взял из чужого решения, но не знаю как именно
он работает, не смог найти описания.
Можете подсказать, что делаю не так или каким методом лучше решить данную задачу?
    


Ответы

Ответ 1



Замените (\d*) на (\d+) Поясню что не так: (\d*) подразумевает ноль или более цифр. То есть пустым разделитель тоже может быть. Если это учитывать, то ваш результат мог быть и таким: ['', 'k', '10', 'Z', '18', 'i', '13', 'Q', '19', 'u', ''] Также если бы у вас были две буквы подряд, то между ними тоже могла бы "найтись" пустая строка. Текущая реализация этого метода не находит пустые подстроки, которые могут подходить под регулярное выражение. Однако в будущем планируется это реализовать, поэтому вы получаете FutureWarning. Вас предупреждают, что если вы ничего не измените, после обновления вас может ожидать сюрприз. См. также re.split

Режем строку, сохраняя разделители

#java #строки


Как можно строку формата: "-99/9" разбить на массив подстрок {"-","99","/","9"}?
    


Ответы

Ответ 1



Зачем усложнять? Есть числа и что-то между ними. Выделяем числа с двух сторон пробелами, нормализуем строку, чтобы после разбиения не появилось пустых элементов и готово. import java.util.Arrays; public class Main { public static void main(String[] args) { String str = "2+2*24-78"; str = str.replaceAll("(\\d+)"," $1 "); str = str.trim(); String[] stack = str.split(" "); System.out.println(Arrays.toString(stack)); } } В вопросе ничего не говорилось про десятичный разделитель, функции и скобки. Правильным подходом по решению задачи это не сразу разбивать строку на отдельные лексемы, а считывая ее последовательно обрабатывать конечным автоматом. За основу можно взять алгоритм из статьи про обратную польскую нотацию.

Ответ 2



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

Ответ 3



На вскидку - регуляркой. Или что-то упускаю? Получится что-то вроде такого: (regex) /^(-|+)?(\d+)(\/)(\d+)$/