Вывести сколько и каких знаков препинания содержится в строке символов

Строка символов до точки, подсчитать, сколько и каких знаков препинания она содержит. Написал такой код. Помогите, пожалуйста, исправить код (на Си) на switch case и заменить все переменные хранящие количество каждого символа на массив, чтобы не было столько переменных. Буду очень признателен, если поможете исправить.

#include <stdio.h>

int main()
{
    char str_in[30];
    int i=0, dot=0, zap=0, dv=0, vos=0, vop=0, tir=0, dz=0;
    gets(str_in);
    for(;str_in[i]!='\0';i++)
    {
        if(str_in[i]=='.')
            {
                dot++;
                break;
            }
        if(str_in[i]==',')
            zap++;
        if(str_in[i]==':')
            dv++;
        if(str_in[i]=='!')
            vos++;
        if(str_in[i]=='?')
            vop++;
        if(str_in[i]=='-')
            tir++;
        if(str_in[i]==';')
            dz++;
    }
    printf(".=%d ,=%d :=%d !=%d ?=%d -=%d ;=%d\n", dot, zap, dv, vos, vop, tir, dz);
    return 0;
}

Ответы (2 шт):

Автор решения: Nowhere Man
  • определяешь константы для индексов знаков препинания в массиве
  • создаешь проинициализированный массив для подсчета частот знаков препинания
  • переписываешь условие выхода из цикла -- пока не обнаружена точка, так как в case отработает свой break, чтобы избежать ненужного goto
  • переписываешь вывод результатов

Также лучше заменить вызов небезопасной функции gets на более приличную fgets, в которую следует также передать допустимый размер строки ввода.

Вариант решения:

#include <stdio.h>


int main() {
    const int DOT = 0, COMMA = 1, COLON = 2, EXCL = 3, QUEST = 4, DASH = 5, SEMI = 6;
    char str_in[30];
    short stats[] = {0, 0, 0, 0, 0, 0, 0};
    fgets(str_in, sizeof(str_in), stdin);
    for (int i = 0; str_in[i] != '\0' && stats[DOT] == 0; i++) {
        switch (str_in[i]) {
            case '.': stats[DOT]++;   break;
            case ',': stats[COMMA]++; break;
            case ':': stats[COLON]++; break;
            case '!': stats[EXCL]++;  break;
            case '?': stats[QUEST]++; break;
            case '-': stats[DASH]++;  break;
            case ';': stats[SEMI]++;  break;
        }
    }
    printf(".=%d ,=%d :=%d !=%d ?=%d -=%d ;=%d\n", 
        stats[DOT], stats[COMMA], stats[COLON], stats[EXCL], 
        stats[QUEST], stats[DASH], stats[SEMI]
    );
    return 0;
}
→ Ссылка
Автор решения: Harry

Можно и короче:

int main()
{
    char str_in[30];
    const char punct[] = ".,:!?-;";
    int pcount[sizeof(punct)/sizeof(punct[0])] = {0};
    gets_s(str_in,30);  // или fgets(str_in,30,stdin); в зависимости от компилятора
    for(int i = 0;str_in[i];i++)
    {
        const char * c = strchr(punct,str_in[i]);
        if (c) pcount[c-punct]++;
    }
    for(int i = 0;punct[i];i++)
        printf("%c : %d\n",punct[i],pcount[i]);
}

См. https://ideone.com/vagZoT

Самое приятное — для расширения списка символов пунктуации не нужно ничего, кроме как добавить новый символ в строку punct...

→ Ссылка