0

I am preapring for a test in programing and one of the tasks is making a program that will cout how many words start and end with the same latter and also subtract number of upper case latters with the number of numerical cacters. It must be done in a separate function and it must return two values. I know i am not the best at this but i think my code should work and for some reason it brakes at the while loop. What am I doing wrong?

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void calculation(char string[], int *n_words, int *n_numbers, int *n_uppercase) {
    char first_letter = ' ', last_letter = ' ';
    *n_words = 0;
    *n_numbers = 0;
    *n_uppercase = 0;

    for (int i = 0; i < strlen(string); i++) {
        first_letter = string[i];
        last_letter = string[i];
        while(last_letter != ' ')
        {
            if (isdigit(string[i])) (*n_numbers)++;
            else if (isupper(string[i])) (*n_uppercase)++;
            last_letter = string[i];
            i++;
        }
        if (last_letter == first_letter) (*n_words)++;


    }

}


int main() {
    char tekst[169];
    int n_numbers, n_uppercase, n_words;
    printf("Write a text: \n");
    gets_s(tekst);
    calculation(tekst, &n_words, &n_numbers, &n_uppercase);
    printf("Number of words with the same starting and ending letter: % d \n", n_words);
    printf("number of upper case characters - number of numbers :%d \n ", n_uppercase - n_numbers);

}

The program should proerly output number of words that have same starting and endig characters but insted of that it just gives me an error box with error

Expression: c -I c 255 and exit code 3

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Miloš
  • 1
  • Use a [debugger](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems). – Friedrich Jun 18 '23 at 16:27
  • There are lots of bugs in this code. Maybe start with something simpler? – Tom Karzes Jun 18 '23 at 16:46
  • Have you tried running your code line-by-line in a debugger while monitoring the control flow and the values of all variables, in order to determine in which line your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel Jun 18 '23 at 22:27

3 Answers3

0

The standard C function gets_s is declared like

char *gets_s(char *s, rsize_t n);

As you can see, it has two parameters but you call it with only one argument expression

gets_s(tekst);

This while loop

while(last_letter != ' ')

can access memory outside the character array that can result in undefined behavior.

And this if statement

if (last_letter == first_letter) (*n_words)++;

can incorrectly count words when the current character is a space character.

Also your function should take into account the tab character '\t'.

And as follows from the description of the task

It must be done in a separate function and it must return two values.

the function itself should calculate the difference between upper-case letters and digits. So the function should be declared like

void calculation( const char string[], size_t *n_words, int *n_uppercase_minus_n_numbers );

Pay attention to that according to the C Standard the function main without parameters shall be declared like

int main( void )

Your function can look the following way as shown in the demonstration program below

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void calculation( const char string[],
                  size_t *n_words,
                  int *n_uppercase_minus_n_digits )
{
    *n_words = 0;
    *n_uppercase_minus_n_digits = 0;

    const char *delim = " \t";

    while (*string)
    {
        string += strspn( string, delim );

        if (*string)
        {
            char c = *string;

            for (; *string && !isblank( ( unsigned char )*string ); ++string)
            {
                if (isupper( ( unsigned char )*string ))
                {
                    ++*n_uppercase_minus_n_digits;
                }
                else if (isdigit( ( unsigned char )*string ))
                {
                    --*n_uppercase_minus_n_digits;
                }
            }

            if (c == string[-1]) ++*n_words;
        }
    }
}

int main( void )
{
    enum { N = 100 };
    char tekst[N];

    size_t n_words;
    int n_uppercase_minus_n_digits;

    printf( "Write a text (no more then %d characters):\n", N );

    gets_s( tekst, N );

    calculation( tekst, &n_words, &n_uppercase_minus_n_digits );

    printf( "Number of words with the same starting and ending letter: % zu\n", n_words );
    printf( "number of upper case characters - number of numbers :%d\n", n_uppercase_minus_n_digits );
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

where the while expression is going though the last work that have not a " " after it, the i became more than the string size and it point to a out of your array in memory that cause an exception. you should check the i size before use it in array.

-1

The issue in your code lies within the while loop condition and the logic of tracking the first and last letters of a word.

Check this code

void calculation(char string[], int *n_words, int *n_numbers, int *n_uppercase) {
    char first_letter = ' ', last_letter = ' ';
    *n_words = 0;
    *n_numbers = 0;
    *n_uppercase = 0;

    int i = 0;
    while (i < strlen(string)) {
        // Skip leading whitespace
        while (isspace(string[i])) {
            i++;
        }
        first_letter = string[i];
        last_letter = string[i];
        while (!isspace(string[i]) && string[i] != '\0') {
            if (isdigit(string[i])) {
                (*n_numbers)++;
            } else if (isupper(string[i])) {
                (*n_uppercase)++;
            }
            last_letter = string[i];
            i++;
        }
        if (last_letter == first_letter) {
            (*n_words)++;
        }
    }
}
int main() {
    char tekst[169];
    int n_numbers, n_uppercase, n_words;

    printf("Write a text: \n");
    fgets(tekst, sizeof(tekst), stdin);

    calculation(tekst, &n_words, &n_numbers, &n_uppercase);

    printf("Number of words with the same starting and ending letter: %d\n", n_words);
    printf("Number of uppercase characters - number of numbers: %d\n", n_uppercase - n_numbers);

    return 0;
}

1- Replaced gets_s function with fgets. 2- initialize i outside 3- Added whitespace characters before processing each word. 4- Updated the condition for the inner while loop to check for both whitespace and the end of the string.