Упражнение 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".
Вот, что вышло:
В текущем примере в s2 записывается только
первыми будут выполняться проверки в скобках, ибо приоритет выше. Соответственно s1[i+1] и s1[i+2] могу дать фигню, если символ последний.
#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);
}-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)
)Решение задачи: «Упражнение 3.3 из книги Кернигана и Ритчи (строки)»
textual
Листинг программы
for(i=0;i<sizeof(s1);i++)
{
Объяснение кода листинга программы
- Переменная
iинициализируется значением 0. - Условие цикла for проверяет, что значение переменной
iменьше, чем размер строкиs1(возможно, это означает, чтоs1является массивом символов). - Если условие истинно, то выполняется тело цикла.
- Внутри цикла переменная
iувеличивается на 1. - Цикл продолжается до тех пор, пока условие не станет ложным.
- Если условие ложно, то выполнение программы продолжается после тела цикла.
- В данном случае, в теле цикла ничего не написано, поэтому цикл выполняется без каких-либо действий.
- Если в теле цикла были бы написаны действия, они бы выполнялись при каждой итерации цикла.
- Значение переменной
iизменяется от 0 до sizeof(s1)-1. - sizeof(s1) возвращает количество байтов в строке
s1. - Размер строки в байтах может отличаться от количества символов в строке (если символы занимают больше одного байта).
- В данном случае, количество итераций цикла будет равно количеству байтов в строке
s1. - Если строка
s1является массивом символов, то каждая итерация цикла будет проходить по каждому символу в этом массиве. - В теле цикла можно было бы написать действия, которые бы выполнялись для каждого символа в строке
s1. - В данном случае, никаких действий в теле цикла не написано, поэтому цикл выполняется без каких-либо действий.
- Если в теле цикла были бы написаны действия, они бы выполнялись при каждой итерации цикла.
- Значение переменной
iизменяется от 0 до sizeof(s1)-1. - sizeof(s1) возвращает количество байтов в строке
s1. - Размер строки в байтах может отличаться от количества символов в строке (если символы занимают больше одного байта).
- В данном случае, количество итераций цикла будет равно количеству байтов в строке
s1.