Как я могу перевернуть слова в предложении без использования встроенных функций?

Это был вопрос интервью:

Как конвертировать Dogs like cats в cats like Dogs ?

Мой код показывает: cats like cats. Где я делаю ошибки?

#include <iostream>
using namespace std;

int main()
{
char sentence[] = ("dogs like cats");
cout << sentence << endl;

int len = 0;

for (int i = 0; sentence[i] != '\0'; i++)
{
len++;
}
cout << len << endl;

char reverse[len];
int k = 0;

for (int j = len - 1; j >= 0; j--)
{
reverse[k] = sentence[j];
k++;
}

cout << reverse << endl;

int words = 0;
char str[len];

for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--)
{
str[words] = reverse[m];
words++;
}
}
}

cout << str;

return 0;
}

Я знаю, что вы можете сделать это, используя указатели, стек, векторы … но интервьюер не интересовался этим!

0

Решение

Это фиксированная версия вашего примера кода:

  • Ваша главная проблема в том, что каждый раз, когда вы находите и ' ' или же '\0' Вы копируете байты обратной строки от начала до этой точки. Пример в loop 5 вы копируете из индекса 0-5 (stac) от reverse в str в обратном порядке, но в loop 10 вы копируете из индекса 0-10 (stac ekil) от reverse в str в обратном порядке, пока здесь у вас уже не будет напечатана строка результата («кошки как кошки»), и то же самое в loop 15 все это увеличивает индекс str, в последнем цикле вы пишете передать конец действительной памяти str (и из-за этого не печатается как вывод).
  • Вам нужно отслеживать, когда конец последнего слова переворачивается, чтобы обратить только реальное слово, а не строку из начала в фактический индекс.
  • Вы не хотите считать специальный символ (» и ‘\ 0’) в обращении слов, вы должны закончить cats like\0dogs

Предоставлен модифицированный пример кода:

#include <iostream>
using namespace std;

int main() {
char sentence[] = ("dogs like cats");
cout << sentence << endl;

int len = 0;

for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;

char reverse[len];
int k = 0;

for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}

cout << reverse << endl;

int words = 0;
char str[len];

// change here added last_l to track the end of the last word reversed, moved
// the check of the end condition to the end of loop body for handling the \0
// case
for (int l = 0, last_l = 0; ; l++) {
if (reverse[l] == ' ' || reverse[l] == '\0')
{
for (int m = l - 1; m >= last_l; m--) { // change here, using last_t to
str[words] = reverse[m];            // only reverse the last word
words++;                            // without the split character
}
last_l = l + 1;                         // update the end of the last
// word reversed
str[words] = reverse[l];                // copy the split character
words++;
}
if (reverse[l] == '\0')                     // break the loop
break;
}

cout << str << endl;

return 0;
}

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

#include <iostream>

// reverse any block of text.
void reverse(char* left, char* right) {
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;

left++;
right--;
}
}

int main() {
char sentence[] = "dogs like cats";
std::cout << sentence << std::endl;

// The same length calculation as sample code.
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
std::cout << len << std::endl;

// reverse all the text (ex: 'stac ekil sgod')
reverse(sentence, sentence + len - 1);

// reverse word by word.
char* end = sentence;
char* begin = sentence;
while (end < sentence + len) {
if (*end != ' ')
end++;

if (end == sentence + len || *end == ' ') {
reverse(begin, end - 1);
begin = end + 1;
end = begin;
}
}

std::cout << sentence << std::endl;

return 0;
}
4

Другие решения

Рассекать ваш алгоритм по частям. Во-первых, вы найдете длину строки, не считая нулевого символьного терминатора. Это правильно, хотя может быть упрощено.

size_t len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;

Это можно легко записать просто как:

size_t len = 0;
while (sentence[len])
++len;

Затем вы переворачиваете всю строку, но появляется первый дефект. VLA (массив переменной длины), который вы объявляете здесь (который вам не нужен и не должен использоваться, поскольку он является расширением C ++ и нестандартным), не учитывает и не устанавливает завершающий нулевой символ.

char reverse[len]; // !! should be len+1
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
// !! Should have reverse[k] = 0; here.
cout << reverse << endl; // !! Undefined-behavior. no terminator.

Эта временная буферная строка совсем не нужен. Нет причины, по которой вы не можете выполнить всю эту операцию на месте. Как только мы рассчитаем len правильно, вы просто делаете что-то вроде следующего, чтобы полностью изменить последовательность, которая сохраняет нулевой символ-символ в правильном положении:

// reverse entire sequence
int i = 0, j = len;
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}

Далее мы переходим к тому месту, где вы пытаетесь изменить каждое внутреннее слово. Опять же, как и раньше, длина буфера не является правильной. Так должно быть len+1, Хуже (трудно представить), вы никогда не помните, где вы остановился при поиске конечной точки слова. Это место должно быть следующий точка, которую вы начинаете проверять и пропускаете пробелы. Не сохраняя, что вы копируете из текущей точки обратно в начало строки. который по существу взрывает cats над dogs,

int words = 0;
char str[len]; // !! should be len+1
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--) {
str[words] = reverse[m];
words++;
}
}
}
cout << str; //!! Undefined behavior. non-terminated string.

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

// walk again, reversing each word.
i = 0;
while (sentence[i])
{
// skip ws; root 'i' at beginning of word
while (sentence[i] == ' ') // or use std::isspace(sentence[i])
++i;

// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (sentence[j] && sentence[j] != ' ') // or use !std::isspace(sentence[j])
++j;

// remember the last position
size_t last = j;

// same reversal algorithm we had before
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}

// start at the termination point where we last stopped
i = last;
}

Собираем все вместе

Хотя использовать указатели значительно проще, чем все эти индексные переменные, следующее будет делать то, что вы пытаетесь, на месте.

#include <iostream>

int main()
{
char s[] = "dogs like cats";
std::cout << s << '\n';

size_t len = 0, i, j;
while (s[len])
++len;

// reverse entire sequence
i = 0, j = len;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}

// walk again, reversing each word.
i = 0;
while (s[i])
{
// skip ws; root 'i' at beginning of word
while (s[i] == ' ') // or use std::isspace
++i;

// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (s[j] && s[j] != ' ') // or use !std::isspace
++j;

// remember the last position
size_t last = j;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}

// start at last-left posiion
i = last;
}

std::cout << s << '\n';
return 0;
}

Выход

dogs like cats
cats like dogs
2

Я бы посоветовал разбить исходную строку на массив слов, перевернуть этот массив. Затем добавьте эти слова в обратное предложение с пробелом между ними.

0

Так как они попросили никаких библиотек, я предположил, что нет std::stringнет vectors, ничего вообще, и поэтому я написал это на C .. единственное, что используется printf, Все остальное с нуля: l

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

Пример: http://ideone.com/io6Bh9

Код:

#include <stdio.h>

int strlen(const char* s)
{
int l = 0;
while (*s++) ++l;
return l;
}void reverse(char* str)
{
int i = 0, j = strlen(str) - 1;

for(; i < j; ++i, --j)
{
str[i] ^= str[j];
str[j] ^= str[i];
str[i] ^= str[j];
}
}

void nulltok(char* str, char tok, int* parts)
{
int i = 0, len = strlen(str);
*parts = 1;

for (; i < len; ++i)
{
if (str[i] == tok)
{
str[i] = '\0';
++(*parts);
}
}
}

char* reverse_sentence(char* str)
{
char* tmp = str;
reverse(str);

int i = 0, parts = 0, len = strlen(str);
nulltok(str, 0x20, &parts);

while(parts--)
{
reverse(str);
str += strlen(str) + 1;
}

for(; i < len; ++i)
if (tmp[i] == '\0')
tmp[i] = 0x20;

return tmp;
}int main(void)
{
char str[] = "dogs like cats";
printf("%s", reverse_sentence(str));

return 0;
}
0

Мое решение

#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string str;
cout<<"enter the sentence"<<endl;
getline(cin,str);
char* pch;
pch = strtok((char*)str.c_str()," ");
string rev = "";

while(NULL != pch)
{
rev.insert(0,pch);
rev.insert(0," ");
pch = strtok(NULL," ");
}
cout<<"the reversed string is :"<<rev<<endl;
return 0;

}

0
По вопросам рекламы [email protected]