Упражнение 3.3 из книги Кернигана и Ритчи (строки) - C (СИ)

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

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

Всем привет. Упражнение такое: Напишите функцию expand(s1, s2), заменяющую сокращенную запись наподобие a-z в строке s1 эквивалентной полной записью abc. . . xyz в s2. В s1 допускаются буквы (прописные и строчные) и цифры. Следует уметь справляться с такими случаями, как a-b-c, a-z0-9 и -а-b. Считайте знак - в начале или в конце s1 обычным символом минус. Решил немного усложнить себе задачу и понапихать проверок на такие случаи: "а- ", "а--", "---...-" и "z-a". В таких случаях все должно печататься как есть. То есть подстановка полной записи должна происходить только в случае "a-z" или "a-b-...-z". Вот, что вышло:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
 
void strExpand(char[],char*);
 
int main()
{
    char s1[]="-a-g0-9",s2[256];
    system("cls");
    strExpand(s1,s2);
    printf("After expanding:\ns1 = %s\ns2 = %s\n",s1,s2);
 
    return 0;
}
 
/*Идем посимвольно, проверяем, попадается ли х-у через s1[i+1] и s1[i+2],
т.е. проверяем последующие символы за текущим*/
void strExpand(char *s1,char s2[])
{
    int i,j,k=0,chain,chainLen;
    for(i=0;i<sizeof(s1);i++)
    {
        printf("Nachalo for\n%i\n",i);
        /*Печатаем текущий символ, если это:*/
        if(s1[i]=='-'                               //знак "-" (-)
           || isspace(s1[i])                        //"пробел" ( ),(\t)
           || s1[i+1]=='\0'                         //последняя буква (а\0)
           || s1[i+2]=='\0'                         //предпоследняя буква (аа\0)
           || s1[i+1]!='-'                          //следующий символ не "-" (аа)
           || (s1[i+1]=='-' && s1[i+2]=='-')        //следующие два символа "-" (а--)
           || (s1[i+1]=='-' && isspace(s1[i+2]))    //следующие два символа "- " (а- ),(а-\t)
           || s1[i]>=s1[i+2]                        //в "n1-n2" n2 меньше n1 (z-a),(9-0)
           )
            s2[k++]=s1[i];
        /*В противном случае, печатаем цепочку х-у-...-z с подставлением промежуточных символов*/
        else
        {
            /*Высчитываем длину цепочки a-b-...-z*/
            chain=1;
            j=i+3;
            chainLen=3;
            while(chain)
                if(s1[j]=='\0'
                   || s1[j]!='-'
                   || s1[j+1]=='\0'
                   || s1[j+1]=='-'
                   || isspace(s1[j+1])
                   || s1[j-1]>=s1[j+1]
                   )
                    chain=0;
                else
                {
                    j+=2;
                    chainLen+=2;
                }
            for(j=s1[i];j<=s1[i+chainLen-1];j++)
                s2[k++]=j;
            /*Пропускаем всю цепочку, вставая на следующий за ней символ; i++ в конце цикла*/
            i+=chainLen-1;
            printf("Konec for\n%i\n",i);
        }
    }
    s2[k]='\0';
    printf("EOFunc %i\n\n",i);
}
В текущем примере в s2 записывается только

-abcdegf

Вопрос следующий: почему не выполняется 3ий шаг цикла, хотя все условия соблюдаются (i равно 4, что есть меньше sizeof(s1), т.е. 8). Для этого в конце функции, в начале и конце цикла написал printf, чтобы видеть, когда и с какими значениями начинается и заканчивается шаг цикла. Проверял в CodeBlocks и в BorlandC. ПС Ессно только изучаю язык, многого не понимаю. Может это из-за "насильного" пропуска нескольких щагов цикла, когда i увеличиваем в теле цикла?
Хм, нашел косяк в коде уже. В проверках:
           if(s1[i]=='-'                               //знак "-" (-)
           || isspace(s1[i])                        //"пробел" ( ),(\t)
           || s1[i+1]=='\0'                         //последняя буква (а\0)
           || s1[i+2]=='\0'                         //предпоследняя буква (аа\0)
           || s1[i+1]!='-'                          //следующий символ не "-" (аа)
           || (s1[i+1]=='-' && s1[i+2]=='-')        //следующие два символа "-" (а--)
           || (s1[i+1]=='-' && isspace(s1[i+2]))    //следующие два символа "- " (а- ),(а-\t)
           || s1[i]>=s1[i+2]                        //в "n1-n2" n2 меньше n1 (z-a),(9-0)
           )
первыми будут выполняться проверки в скобках, ибо приоритет выше. Соответственно s1[i+1] и s1[i+2] могу дать фигню, если символ последний.

Решение задачи: «Упражнение 3.3 из книги Кернигана и Ритчи (строки)»

textual
Листинг программы
    for(i=0;i<sizeof(s1);i++)
    {

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

  1. Переменная i инициализируется значением 0.
  2. Условие цикла for проверяет, что значение переменной i меньше, чем размер строки s1 (возможно, это означает, что s1 является массивом символов).
  3. Если условие истинно, то выполняется тело цикла.
  4. Внутри цикла переменная i увеличивается на 1.
  5. Цикл продолжается до тех пор, пока условие не станет ложным.
  6. Если условие ложно, то выполнение программы продолжается после тела цикла.
  7. В данном случае, в теле цикла ничего не написано, поэтому цикл выполняется без каких-либо действий.
  8. Если в теле цикла были бы написаны действия, они бы выполнялись при каждой итерации цикла.
  9. Значение переменной i изменяется от 0 до sizeof(s1)-1.
  10. sizeof(s1) возвращает количество байтов в строке s1.
  11. Размер строки в байтах может отличаться от количества символов в строке (если символы занимают больше одного байта).
  12. В данном случае, количество итераций цикла будет равно количеству байтов в строке s1.
  13. Если строка s1 является массивом символов, то каждая итерация цикла будет проходить по каждому символу в этом массиве.
  14. В теле цикла можно было бы написать действия, которые бы выполнялись для каждого символа в строке s1.
  15. В данном случае, никаких действий в теле цикла не написано, поэтому цикл выполняется без каких-либо действий.
  16. Если в теле цикла были бы написаны действия, они бы выполнялись при каждой итерации цикла.
  17. Значение переменной i изменяется от 0 до sizeof(s1)-1.
  18. sizeof(s1) возвращает количество байтов в строке s1.
  19. Размер строки в байтах может отличаться от количества символов в строке (если символы занимают больше одного байта).
  20. В данном случае, количество итераций цикла будет равно количеству байтов в строке s1.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

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

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