Страницы

Translate

понедельник, 29 июля 2013 г.

Упражнение 2.5. Напишите функцию any(s1, s2)


Упражнение 2.5. Напишите функцию any(s1, s2), которая возвращает либо ту позицию в s1, где стоит первый символ, совпавший с любым из символов в s2, либо -1 (если ни один символ из s1 не совпадает с символами из s2). (Стандартная библиотечная функция strpbrk делает то же самое, но выдает не номер позиции символа, а указатель на символ.)

/*
 * Copyright 2013 Pavel <pavel@pavel-Ubuntu>
 */


#include <stdio.h>

int any(char s1[], char s2[]);

int main()
{
    char first[] = "Hello world!";
    char second[] = "plt";
    
    printf("first location: %d\n", any(first, second));
    return 0;
}

/*any(s1, s2)*/

int any(char s1[], char s2[])
{
    int i, j;
    for(j = 0; s2[j] != '\0'; j++)
    {
        for(i = 0; s1[i] != '\0'; i++)
            if(s1[i] == s2[j])
                return i;
    }
    return -1;
}

Результат:


Упражнение 2.4. Напишите версию функции squeeze(s1, s2), которая удаляет из s1 все символы, встречающиеся в строке s2.


Упражнение 2.4. Напишите версию функции squeeze(s1, s2), которая удаляет из s1 все символы, встречающиеся в строке s2.



/*
 * Copyright 2013 Pavel <pavel@pavel-Ubuntu>
 */

#include <stdio.h>

void squeeze(char s1[], char s2[]);

int main()
{
    char first[] = "afrfora";
    char second[] = "frodl";
    
    squeeze(first, second);
    printf("%s\n", first);
    return 0;
}

/*squeeze*/

void squeeze(char s1[], char s2[])
{
    int i, j, n, c;
    i=j=0; 
    
    while(s2[i] != '\0')
        if(s1[j] == s2[i]) //удаляем встречающиеся символы
        {
            for(n=c=j; s1[c] != '\0'; n++)
                s1[n] = s1[++c];
        }
        else if(s1[j] == '\0')
        {
            i++;
            j=0;
        }
        else
            j++;
}

Результат:



Упражнение 2.З. Напишите функцию htoi(s), которая преобразует последовательность шестнадцатеричных цифр


Упражнение  2.З.  Напишите  функцию  htoi(s),  которая  преобразует  последовательность шестнадцатеричных цифр, начинающуюся с 0х или 0Х, в соответствующее целое. Шестнадцатеричными цифрами являются символы 0…9, а…f, А…F.




#include <stdio.h>

#define IN 1
#define OUT 0;

int htoi(char s[]);

int main()
{
    char hox[4] = {'0', 'x', 'F', 'f'};
    printf("%d\n", htoi(hox));
    return 0;
}


/*htoi(s)*/

int htoi(char s[])
{
    int i, number, indigit, hexdig;
    i = 0;
    if(s[i] == '0')
    {
        i++;
        if(s[i] == 'x' || 'X')
            i++;
    }
    indigit = IN;//внутри числа
    number=0;//результат функции htoi
    for(;indigit == IN; i++)
    {
        if(s[i] >= '0' && s[i] <= '9')
            hexdig = s[i] - '0';//принимает значение между 0 и 15
        else if(s[i] >= 'a' && s[i] <= 'f')
            hexdig = s[i] - 'a'+ 10;
        else if(s[i] >= 'A' && s[i] <= 'F')
            hexdig = s[i] - 'A'+ 10;
        else
            indigit = OUT;//вне числа
        if(indigit == IN)
            number = number*16 + hexdig;
    }
    return number;
}

Результат:



Упражнение 2.2. Напишите цикл, эквивалентный приведенному выше fоr-циклу, не пользуясь операторами && и ||.


Упражнение 2.2. Напишите цикл, эквивалентный приведенному ниже fоr-циклу, не пользуясь операторами && и ||.

вот цикл:


for (i = 0; i < lim-1 && (с = getchar()) != EOF && с != '\n'; ++i)
    s[i] = c;




#include <stdio.h>

#define LIM 10

int main()
{
    char s[LIM];
    int i, c;
    
    for(i=0; (c=getchar()) != EOF; ++i)
    {
        if(i==LIM-1)
            break;
        if(c=='\n')
            break;
        s[i]=c;
    }
    s[i]='\0';
    printf("%s\n", s);
    return 0;
}

Результат:




Упражнение 2.1. Напишите программу, которая будет выдавать диапазоны значений типов char, short, int и long, описанных как signed и как unsigned


Упражнение 2.1. Напишите программу, которая будет выдавать диапазоны значений типов char, short, int и long, описанных как signed и как unsigned, с помощью печати соответствующих значений из стандартных заголовочных файлов и путем прямого вычисления.

#include <stdio.h>
#include <limits.h>
#include <math.h>
#include <float.h>

int main()
{
    double c;
    c=UINT_MAX;

    printf("values from standard headers\n\n");
    printf("signed char: %d   %d\n", SCHAR_MIN, SCHAR_MAX);
    printf("unsigned char: %d   %d\n", 0, UCHAR_MAX);
    printf("signed int: %d   %d\n", INT_MIN, INT_MAX);
    printf("unsigned int: %d   %.lf\n", 0, c);
    printf("signed short: %d   %d\n", SHRT_MIN, SHRT_MAX);
    printf("unsigned short: %d   %d\n", 0, USHRT_MAX);
    printf("signed long: %ld   %ld\n", LONG_MIN, LONG_MAX);
    printf("unsigned long: %d   %lu\n\n", 0, ULONG_MAX);
    
    printf("values by direct computation\n\n");
    printf("signed char: -%g   %g\n", pow(2, sizeof(char)*8)/2, 
                                      pow(2, sizeof(char)*8)/2-1);
    printf("unsigned char: %d   %g\n", 0, pow(2, sizeof(char)*8)-1);
    printf("signed int: -%.lf   %.lf\n", pow(2, sizeof(int)*8)/2, 
                                         pow(2, sizeof(int)*8)/2-1);
    printf("usigned int: %d   %.lf\n", 0, pow(2, sizeof(int)*8)-1);
    printf("signed short: -%.lf   %.lf\n", pow(2, sizeof(short)*8)/2, 
                                           pow(2, sizeof(short)*8)/2-1);
    printf("unsigned short: %d   %.lf\n", 0, pow(2, sizeof(short)*8)-1);
    printf("signed long: -%.lf   %.lf\n", pow(2, sizeof(long)*8)/2, 
                                          pow(2, sizeof(long)*8)/2-1);
    printf("unsigned long: %d   %.lf\n\n", 0, pow(2, sizeof(long)*8)-1);
    return 0;


Результат:



воскресенье, 21 июля 2013 г.

Упражнение 1.24. Напишите программу, проверяющую Си-программы на элементарные синтаксические ошибки

Упражнение 1.24. Напишите программу, проверяющую Си-программы на элементарные синтаксические ошибки вроде несбалансированности скобок всех видов. Не забудьте о кавычках (одиночных и двойных), эскейп-последовательностях (\...) и комментариях. (Это сложная программа, если писать ее для общего случая.)


#include <stdio.h>

void in_comment(int c);
void search(int c);
void in_quotes(int c);

FILE *in, *out;
int rbrackets, sbrackets, braces, quotes1, quotes2;

int main()
{
    int c;
    char file_name[20];
    printf("Введите имя входного файла: ");
    gets(file_name);
    in=fopen(file_name,"rb");//Открыть файл для чтения
    if((in=fopen(file_name, "rb")) == NULL)
    {
        perror(file_name);
        return 1;
    }
    while((c=fgetc(in)) != EOF)
    {
        if(c == '/')
        {
            if((c = fgetc(in)) =='*')
                in_comment(c);//внутри комментария
            else
                search(c);
        }
        else if(c=='\'' || c=='"')
        {
            if(c=='\'')
                quotes1++;
            if(c=='"')
                quotes2++;
            in_quotes(c);
        }
        else
            search(c);
        if(quotes1 < 0)//вывод ошибок
        {
            printf("Непарные одинарные кавычки\n");
            quotes1=0;
        }
        if(quotes2 < 0)
        {
            printf("Непарные двойные кавычки\n");
            quotes2=0;
        }
        if(rbrackets < 0)
        {
            printf("Непарные круглые скобки\n");
            rbrackets = 0;
        }
        if(sbrackets < 0)
        {
            printf("Непарные квадратные скобки\n");
            sbrackets = 0;
        }
        if(braces < 0)
        {
            printf("Непарные фигурные скобки\n");
            braces = 0;
        }
    }
    if(quotes1 > 0)
    {
        printf("Непарные одинарные кавычки\n");
        quotes1=0;
    }
    if(quotes2 > 0)
    {
        printf("Непарные двойные кавычки\n");
        quotes2=0;
    }
    if(rbrackets > 0)
    {
        printf("Непарные круглые скобки\n");
        rbrackets = 0;
    }
    if(sbrackets > 0)
    {
        printf("Непарные квадратные скобки\n");
        sbrackets = 0;
    }
    if(braces > 0)
    {
        printf("Непарные фигурные скобки\n");
        braces = 0;
    }
    fclose(in);
    return 0;
}

/*поиск символов*/
void search(int c)
{
    if(c=='(')
        rbrackets++;
    if(c=='[')
        sbrackets++;
    if(c=='{')
        braces++;
    if(c==')')
        rbrackets--;
    if(c==']')
        sbrackets--;
    if(c=='}')
        braces--;
}

/*пропуск комментариев*/
void in_comment(int c)
{
    int d;
    c=fgetc(in);
    d=fgetc(in);
    while(c != '*' || d != '/')
    {
        c=d;
        d=fgetc(in);
    }
}

/*поиск кавычек*/
void in_quotes(int c)
{
    int d;
    while(d != ')' && d != ';' && d != ',' && d != '}' && d != ']')
    {
        d = fgetc(in);
        if(d=='\\')
            getchar();
        if(d=='\'')
            quotes1--;
        if(d=='"')
            quotes2--;
    }
    if(d==')')
        rbrackets--;
    if(d==']')
        sbrackets--;
    if(d=='}')
        braces--;
}

Результат:



Упражнение 1.23. Напишите программу, убирающую все комментарии из любой Си-программы.

Упражнение 1.23. Напишите программу, убирающую все комментарии из любой Си-программы. Не забудьте должным образом обработать строки символов и строковые константы. Комментарии в Си не могут быть вложены друг в друга.

/*удаление комментариев из Си файла*/

#include <stdio.h>

void find_comment(int c);
void in_comment(void);
void in_short_comment(void);
FILE *in, *out;


int main()
{
    int c;
    char file_name[20];
    char out_file_name[20];
    
    printf("Введите имя входного файла: ");
    gets(file_name);
    in = fopen(file_name,"rb");//Открыть файл для чтения
    if((in = fopen(file_name, "rb")) == NULL)
    {
        perror(file_name);
        return 1;
    }
    printf("Введите имя выходного файла: ");
    gets(out_file_name);
    out = fopen(out_file_name, "wb");//открыть файл для записи
    while((c = fgetc(in)) != EOF)
    {
        find_comment(c);
    }
    fclose(in);
    fclose(out);
    return 0;
}

/*поиск коментариев*/
void find_comment(int c)
{
    int d;
    if(c=='/')
        if((d = fgetc(in)) =='*')
            in_comment();
        else if(d=='/')
            in_short_comment();
        else
        {
            fputc(c, out);
            fputc(d, out);
        }
    else 
        fputc(c, out);
}

/*внутри длинного комментария*/
void in_comment(void)
{
    int c, d;
    c=fgetc(in);
    d=fgetc(in);
    while(c != '*' || d != '/')
    {
        c=d;
        d=fgetc(in);
    }
}

/*внутри короткого комментария*/
void in_short_comment(void)
{
    int c;
    c=fgetc(in);
    while(c != '\n')
        c=fgetc(in);
    fputc('\n', out);
}


Результат:







Файл до:

























Файл после:


Упражнение 1.22. Напишите программу, печатающую символы входного потока так, чтобы строки текста не выходили правее n-й позиции.

Упражнение 1.22. Напишите программу, печатающую символы входного потока так, чтобы строки текста не выходили правее n-й позиции. Это значит, что каждая строка, длина которой превышает n, должна печататься с переносом на следующие строки. Место переноса следует "искать" после последнего символа, отличного от символа-разделителя, расположенного левее n-й позиции. Позаботьтесь о том, чтобы ваша программа вела себя разумно в случае очень длинных строк, а также когда до n-й позиции не встречается ни одного символа пробела или табуляции.

#include <stdio.h>
#define TAB 8
#define LEN 10

void print_line(int symv);
int search_space(int symv);
int search_newsymv(int symv);
char line[LEN];

int main()
{
    int c, symv;
    
    symv=0;
    while((c=getchar()) != EOF)
    {
        line[symv]=c;
        if(c=='\t')
        {
            line[symv]=' ';
            for(symv++; symv<LEN && symv%TAB != 0; symv++)
                line[symv]=' ';
            if(symv>=LEN)
                print_line(symv);                
        }
        if(c=='\n')
        {
            print_line(symv);
            symv=0;
        }
        else
        {
            if(symv++>=LEN)
            {
                symv=search_space(symv);
                print_line(symv);
                symv=search_newsymv(symv);
            }
        }
    }
    return 0;
}

/*печать строки*/
void print_line(int symv)
{
    int i;
    for(i=0; i<symv; i++)
        putchar(line[i]);
    if(symv>0)
        putchar('\n');
}

/*поиск пробела*/
int search_space(int symv)
{
    while(line[symv] !=' ' && symv>0)
        symv--;
    if(symv==0)
        return LEN;
    else
        return symv++;
}

/*поиск места размещения симdола
 * в новой строке*/
int search_newsymv(int symv)
{
    int i, j;
    if(symv<=0 || symv>=LEN)
        return 0;
    else
    {
        i=0;
        for(j=symv++; j<LEN; j++)
        {
            line[i] = line[j];
            i++;
        }
        return i;
    }
}


Результат:


суббота, 20 июля 2013 г.

Упражнение 1.21. Напишите программу entab, заменяющую строки из пробелов минимальным числом табуляций и пробелов

Упражнение 1.21. Напишите программу entab, заменяющую строки из пробелов минимальным числом табуляций и пробелов таким образом, чтобы вид напечатанного текста не изменился. Используйте те же "стопы" табуляции, что и в detab. В случае, когда для выхода на очередной "стоп" годится один пробел, что лучше — пробел или табуляция?( Я думаю лучше пробел).


/*entab*/

#include <stdio.h>
#define TAB 8

int main()
{
    int c, ntab, nspace, symv;
    
    symv=1;
    ntab=0;//табуляции
    nspace=0;//пробелы
    while((c=getchar()) != EOF)
    {
        symv++;
        if(c==' ')
        {
            if(symv%TAB==0)
            {
                ntab++;
                nspace=0;
            }
            else
                nspace++;
        }
        else
        {
             while(ntab>0)
            {
                putchar('\t');
                ntab--;
            }
            if(c=='\t')
            {
                nspace=0;
                putchar('\t');
                symv=symv+(TAB-(symv%TAB));
            }
            else
            {
                while(nspace>0)
                {
                    putchar(' ');
                    nspace--;
                }
                putchar(c);
                if(c=='\n')
                {
                    symv=0;
                    ntab=0;
                    nspace=0;
                }
            }
        }
    }
    return 0;
}


Результат:




Упражнение 1.20. Напишите программу detab, заменяющую символы табуляции во вводимом тексте нужным числом пробелов

Упражнение 1.20. Напишите программу detab, заменяющую символы табуляции во вводимом тексте нужным числом пробелов (до следующего "стопа" табуляции). Предполагается, что "стопы" табуляции расставлены на фиксированном расстоянии друг от друга, скажем, через n позиций. Как лучше задавать n — в виде значения переменной или в виде именованной константы?

n лучше задать в виде именованной константы.

/*detab*/

#include <stdio.h>
#define TAB 8

int main()
{
int c, i, symvol, ntab;
    
symvol=1;//количество введённых символов до табуляци
while((c=getchar()) != EOF)
{
if(c=='\t')
{
//определяем количество пробелов
//нужных для вставки
ntab = TAB - (symvol-1);
for(i=0; i<ntab; i++)
putchar('|');//тут должен стоять пробел
symvol=0;
}
else if(c=='\n')
{
symvol=0;
printf("\n");
}
else
putchar(c);
symvol++;
            if(symvol==TAB)
                symvol=0;
}
return 0;
}

Для большей наглядности вместо пробелов использую символ ' | '
Результат:  


пятница, 12 июля 2013 г.

Упражнение 1.19. Напишите функцию reverse(s), размещающую символы в строке s в обратном порядке.


Упражнение 1.19. Напишите функцию reverse(s), размещающую символы в строке s в обратном порядке.
Примените ее при написании программы, которая каждую вводимую строку располагает в обратном порядке.


#include <stdio.h>
#define MAX 1000

void reverse(char s[], int n);
int main(int argc, char **argv)
{
    
    char line[MAX];
    int i, m;
    char c;
    i=0;
    while((c=getchar()) != EOF)
    {
        line[i]=c;
        i++;
        if(c=='\n')
        {
            line[i]='\0';
            m=i;//запоминаем длину введённой строки
            i=0;
            reverse(line, m);
            printf("%s\n", line);
        }
    }
    return 0;
}

void reverse(char s[], int n)
{
    char tmp[MAX];
    int i, j;
    for(i=0; i<n; i++)
        tmp[i]=s[i];
    i-=2;//отнимаем символ \0, и ещё один элемент 
    //из-за правил нумерации массива
    for(j=0; j<(n-1); j++, i--)
        s[j]=tmp[i];
}

Результат:



Упражнение 1.18. Напишите программу, которая будет в каждой вводимой строке заменять стоящие подряд символы пробелов и табуляций на один пробел и удалять пустые строки.


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


#include <stdio.h>
#define MAXLINE 1000 // максимальный размер вводимой строки

int getlin(char line[], int MAX);

int main()
{
    int len, i; //длина текущей строки, переменная
    char line[MAXLINE]; //текущая строка
    while((len=getlin(line, MAXLINE))>0)
    {
      len-=1;//отнимаем '\0'
      //уменьшаем строку, убирая пробелы и табуляции 
      for(i=len-1; i>=0; i--)
         if(line[i]=='0' || line[i]=='1')
            len--;
         else i=0;
       if (len!=0)//если строка не пустая выводим её
      {
         for(i=0; i<len; i++)
            printf("%c", line[i]);
         printf("\n");
      }
    }
    return 0;
}

/*getline читает строку в s, возвращает длину*/
int getlin(char s[], int lim)
{
    int c, i;
    for(i=0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; i++)
        s[i]=c;
    if(c=='\n')
    {
        s[i]=c;
        i++;
    }
    s[i] = '\0';
    return i;
}

Для наглядности вместо лишних пробелов будут нули, 1 вместо табуляции.
Результат:



Упражнение 1.17. Напишите программу печати всех вводимых строк, содержащих более 80 символов.

Упражнение 1.17. Напишите программу печати всех вводимых строк, содержащих более 80 символов. (Чтобы было легче - более 10 символов).


#include <stdio.h>
#define MAXLINE 1000 // максимальный размер вводимой строки

int getlin(char line[], int MAX);

/*печать строки длинной больше 10 символов*/
int main()
{
    int len; //длина текущей строки
    char line[MAXLINE]; //текущая строка
    while((len=getlin(line, MAXLINE))>0)
      if((len-1)>10)
         printf("Эта строка больше 10 символов: %s\n", line);
    return 0;
}

/*getline читает строку в s, возвращает длину*/
int getlin(char s[], int lim)
{
    int c, i;
    for(i=0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; i++)
        s[i]=c;
    if(c=='\n')
    {
        s[i]=c;
        i++;
    }
    s[i] = '\0';
    return i;
}


Результат:


Упражнение 1.16. Перепишите main предыдущей программы так, чтобы она могла печатать самую длинную строку без каких-либо ограничений на ее размер.

Упражнение 1.16.
В русском варианте перевод какой-то неточный, дословно перевод говорит, что надо определить длину вводимой строки, вывести её на экран и напечатать часть текста(которая входит в диапазон массива).


#include <stdio.h>
#define MAXLINE 10 // максимальный размер вводимой строки

int getlin(char line[], int MAX);
void copy(char to[], char from[]);


/*печать самой длинной строки*/
int main()
{
    int len; //длина текущей строки
    int max; //длина максимальной из просмотренных строк
    char line[MAXLINE]; //текущая строка
    char longest[MAXLINE]; //самая длинная строка
    int c;
    max=0;
    while((len=getlin(line, MAXLINE))>0)
    {
        if(line[len-1] != '\n')
            while((c=getchar())!=EOF && c!='\n')
            len++;
      if(len>max)
        {
            max=len;
            copy(longest, line);
        }
    }
    if(max<MAXLINE) // вычитаем нулевой символ вставленный в getlin
      max--;
   if(max>0)
   {
      printf("Самая длинная строка\n");
      if(max>MAXLINE)
         printf("%s...\n", longest);
      else
         printf("%s\n", longest);
    }
    printf("длинa строки - %d символов\n", max);
     return 0;
}

/*getlin читает строку в s, возвращает длину*/
int getlin(char s[], int lim)
{
    int c, i;
    for(i=0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; i++)
        s[i]=c;
    if(c=='\n')
    {
        s[i]=c;
        i++;
    }
    s[i] = '\0';
    return i;
}

void copy(char to[], char from[])
{
    int i;
    i=0;
    while((to[i] = from[i]) != '\0')
        i++;
}



Результат: