Программа для подсчета длины каждого слова в строке в C - PullRequest
0 голосов
/ 21 ноября 2018

Я пишу программу для подсчета длины каждого слова в массиве символов.Мне было интересно, если вы, ребята, могли бы помочь мне, потому что я борюсь с этим по крайней мере два часа, и я не знаю, как это сделать правильно.Это должно выглядеть так:

(количество букв) - (количество слов с таким количеством букв)2 - 13 - 45 - 1и т.п.

char tab[1000];
int k = 0, x = 0;

printf("Enter text: ");
fgets(tab, 1000, stdin);

for (int i = 2; i < (int)strlen(tab); i++)
{


    for (int j = 0; j < (int)strlen(tab); j++)
    {
        if (tab[j] == '\0' || tab[j]=='\n')
            break;
        if (tab[j] == ' ')
            k = 0;
        else k++;

        if (k == i)
        {
            x++;
            k = 0;
        }
    }
    if (x != 0)
    {
        printf("%d - %d\n", i, x);
        x = 0;
        k = 0;
    }

}



return 0;

1 Ответ

0 голосов
/ 21 ноября 2018

Используя два for цикла, вы выполняете len**2 символьное сканирование.(например) Для буфера длиной 1000 вместо 1000 символьных сравнений вы выполняете 1 000 000 сравнений.

Это можно сделать в цикле single for, если мы используеммассив гистограмм длины слова.

Базовый алгоритм такой же, как у вашего внутреннего цикла.

Когда у нас есть непробельный символ, мы увеличиваем текущее значение длины.Когда мы видим пробел, мы увеличиваем ячейку гистограммы (индексируемую по значению длины) на 1. Затем устанавливаем значение длины равным 0.

Вот код, который работает:

#include <stdio.h>

int
main(void)
{
    int hist[100] = { 0 };
    char buf[1000];
    char *bp;
    int chr;
    int curlen = 0;

    printf("Enter text: ");
    fflush(stdout);

    fgets(buf,sizeof(buf),stdin);
    bp = buf;

    for (chr = *bp++;  chr != 0;  chr = *bp++) {
        if (chr == '\n')
            break;

        // end of word -- increment the histogram cell
        if (chr == ' ') {
            hist[curlen] += 1;
            curlen = 0;
        }

        // got an alpha char -- increment the length of the word
        else
            curlen += 1;
    }

    // catch the final word on the line
    hist[curlen] += 1;

    for (curlen = 1;  curlen < sizeof(hist) / sizeof(hist[0]);  ++curlen) {
        int count = hist[curlen];
        if (count > 0)
            printf("%d - %d\n",curlen,count);
    }

    return 0;
}

ОБНОВЛЕНИЕ:

и я не очень понимаю указатели.Есть ли какой-нибудь более простой способ сделать это?

Указатели - очень важный [необходимый] инструмент в арсенале С, поэтому я надеюсь, что вы скоро доберетесь до них.

Однако, этодостаточно просто преобразовать цикл for (удаление char *bp; и bp = buf;):

Изменить:

for (chr = *bp++;  chr != 0;  chr = *bp++) {

В:

for (int bufidx = 0;  ;  ++bufidx) {
    chr = buf[bufidx];
    if (chr == 0)
        break;

Остальная часть цикла for остается прежней.

Вот еще один цикл [но без оптимизации компилятором], дважды выбирающий char:

for (int bufidx = 0;  buf[bufidx] != 0;  ++bufidx) {
    chr = buf[bufidx];

Вот однострочная версия,Обратите внимание, что это не рекомендуемая практика из-за встроенного назначения из chr внутри условия условия цикла, но для целей иллюстрации:

for (int bufidx = 0;  (chr = buf[bufidx]) != 0;  ++bufidx) {
...