Что нужно изменить в функции на assembler-е, чтобы удаляло пробелы в начале и в конце строки

Узнай цену своей работы

Формулировка задачи:

изменить в функции assembler,чтобы удаляло пробелы в начале и в конце строки,а то удаляет только повторяющиеся пробелы
#include "stdafx.h"
#include  <stdio.h>
#include <locale.h>
#include <string.h>
#include <time.h>
#include <iostream>
using namespace std;
char* si(char* str, char* res)
{
    int j = 0;
    int i;
    for (i = 0; i < strlen(str); i++) {
        if (str[i] == ' ')
        {
            if (j == 0) continue;
            if (str[i + 1] == ' ') continue;
        }
        res[j] = str[i];
        j++;
    }
    i = strlen(res); // подсчет длины строки
    if (res[i - 2] == ' ')
        res[i - 2] = '\0';
    return res;
}
char* assembler(char* str, char* res)
{
    int str_len = strlen(str);
    _asm
    {
        mov ecx, str_len //Заносим длину первой строки
            mov edi, str //Заносим первую строку
            mov esi, res //Заносим вторую строку
        m1 :
           
        mov al, byte ptr[edi] //Первый символ первой строки
            inc edi // увеличиваем значение на 1
            mov byte ptr[esi], al  //Первый символ второй строки
            inc esi // увеличиваем значение на 1
            dec ecx // уменьшаем счетчик
            cmp al, ' ' // сравниваем
            jne m2   // переход если(al) = ' '
            repe scasb // поиск пробелов
            je m2 // переход к m2
            dec edi // уменьшаем счетчик
            inc ecx // увеличиваем значение на 1
        m2 :
        test ecx, ecx
            jnz m1 // переход если ecx=ecx
            mov byte ptr[esi], 0 // хранение в 8 бит
    }
    return res;
}
int main() {
    setlocale(LC_ALL, "");
    char str[101] = ""; // ввод строки
    char res[101] = ""; // вывод строки
    printf("Введите строку:");
    fgets(str, 101, stdin);
    long int time1 = 0, time2 = 0;
    // c++
    time1 = clock();
    for (int k = 1; k < 1000000; k++)
        si(str, res);
        time2 = clock();
        cout << "Время выполнения 1000000 итераций на Си: " << time2 - time1 << "ms" << endl;
        cout << res << endl;
        // assembler
    time1 = clock();
    for (int k = 1; k<1000000; k++)
        assembler(str,res);
    time2 = clock();
    cout << "Время выполнения 1000000 итераций на ассемблере: " << time2 - time1 << "ms" << endl;
    cout << res << endl;
    system("pause");
    return 0;
}

Решение задачи: «Что нужно изменить в функции на assembler-е, чтобы удаляло пробелы в начале и в конце строки»

textual
Листинг программы
//#include "stdafx.h"
#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <time.h>
//#include <iostream>
//using namespace std;
char* si(char* str, char* res)
{
int j = 0;
int i;
for (i = 0; i < strlen(str); i++) {
if (str[i] == ' ')
{
if (j == 0) continue;
if (str[i + 1] == ' ') continue;
}
res[j] = str[i];
j++;
}
i = strlen(res); // подсчет длины строки
if (res[i - 2] == ' ')
res[i - 2] = '\0';
return res;
};
char* trim(char* _str, char* _res)
{
__asm
{
    xor ecx,ecx
    mov al,cl
    mov edi, dword ptr [_str]
    mov esi, edi    // ещё пригодится
    dec ecx     // ECX = -1
    repne   scasb
    not ecx
    sub edi,2
// в ECX - длина str, EDI->на последний символ в строке
    std
    mov al, 0x20    // пробел
    repe    scasb
// в ECX длина str без хвостовых пробелов
    mov edi, esi
// EDI-> на начало _str
    cld
    repe    scasb
    inc ecx
//в ECX длина str без начальных и хвостовых пробелов
    mov esi, edi
    dec esi
//ESI->на первый непобельный символ
    mov edi, dword ptr [_res]
    rep movsb
    xor al,al
    stosb
};
return _res;
};
int main() {
//setlocale(LC_ALL, "");
char str[101]; // ввод строки
char res[101]; // вывод строки
long int time1 = 0, time2 = 0;
int k;
printf("Введите строку:");
gets(str);
// c++
time1 = clock();
for (k = 1; k < 1000000; k++)
si(str, res);
time2 = clock();
printf("Время выполнения 1000000 итераций на Си: %d ms\n\r%s|\n\r", time2 - time1,res);
// assembler
time1 = clock();
for (k = 1; k<1000000; k++)
trim(str,res);
time2 = clock();
printf("Время выполнения 1000000 итераций на ассемблере: %d ms\n\r%s|\n\r", time2 - time1,res);
getch();
return 0;
};

Объяснение кода листинга программы

  1. Функция si принимает два аргумента: указатель на исходную строку str и указатель на результирующую строку res.
  2. В функции используется цикл for, который проходит по всем символам строки str.
  3. Если текущий символ является пробелом и предыдущий символ также является пробелом, то текущий символ пропускается.
  4. Если текущий символ не является пробелом, он копируется в результирующую строку res.
  5. После цикла for подсчитывается длина результирующей строки res.
  6. Если последний символ результирующей строки является пробелом, он заменяется на символ конца строки \0.
  7. Функция trim принимает два аргумента: указатель на исходную строку _str и указатель на результирующую строку _res.
  8. В функции используется ассемблерный блок, который выполняет следующие действия:
    • Используется операция xor ecx,ecx, чтобы установить начальное значение регистра ecx равным 0.
    • Регистр al устанавливается равным значению регистра cl, чтобы обеспечить корректную работу операции repne scasb.
    • Устанавливается начальное значение указателя на строку _str в регистре edi.
    • Регистр ecx уменьшается на 1, чтобы обеспечить корректную работу операции repne scasb.
    • Операция repne scasb используется для поиска первого непобедимого символа в строке _str.
    • Регистр ecx инвертируется, чтобы обеспечить корректную работу операции sub edi,2.
    • Устанавливается начальное значение указателя на результирующую строку _res в регистре edi.
    • Регистр ecx увеличивается на 1, чтобы обеспечить корректную работу операции rep movsb.
    • Регистр al устанавливается равным символу пробела 0x20, чтобы обеспечить корректную работу операции rep stosb.
    • Операция rep stosb используется для удаления начальных и хвостовых пробелов в результирующей строке _res.
    • Устанавливается начальное значение указателя на первый непобедимый символ в строке _str в регистре esi.
    • Регистр ecx уменьшается на 1, чтобы обеспечить корректную работу операции rep movsb.
    • Операция rep movsb используется для копирования оставшейся части строки _str в результирующую строку _res.
    • Регистр al устанавливается равным символу конца строки \0, чтобы обеспечить корректную работу операции stosb.
    • Операция stosb используется для добавления символа конца строки \0 в конец результирующей строки _res.
  9. В функции main используется функция gets для считывания строки от пользователя.
  10. Используется функция clock для измерения времени выполнения.
  11. В цикле for выполняется 1 000 000 итераций функции si или trim.
  12. После каждой итерации функции si или trim вызывается функция clock для измерения времени выполнения.
  13. Выводится время выполнения и результирующая строка.
  14. В конце программы вызывается функция getch для получения нажатия клавиши от пользователя.
  15. Программа возвращает 0, чтобы указать успешное выполнение.

Оцени полезность:

6   голосов , оценка 4 из 5
Похожие ответы