-2

I need to write a program in C that gets a char array (sentence) and returns an array that each index contains the first letter of each word in the sentence. I wrote an algorithm for it (which I hope is correct) but for some reason, when I activate the functions printf() and gets(), and run the program, the program runs without even printing or getting any input, and ends.

can you tell me the problem? I couldn't find it even with debugger:

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

char *FirstLetters(char *sent)
{
    int i = 0, counter = 1, *firstchar, *p = sent, *q;
    while (*p != '\0')
    {
        if (*p == ' ')
            counter++; 
        p++;
    }
    firstchar = (char *)malloc(counter);
    q = firstchar;
    *q = sent[0];

    for (p = sent + 1, q = firstchar + 1; *p != '\0'; p++, q++)
    {
        if (*p == ' ')
        {
            *q = *p + 1;
            q++;
        }
    }
    return firstchar;
}

void main()
{
    char sentence[SIZE], *firstletter, *p;
    printf("Enter a sentence: ");
    gets(sentence);  
    firstletter = FirstLetters(sentence);
    printf("The result is: \n\n");
    puts(firstletter);
}

I tried getting the input for the sentence using for loop with scanf_s, but still, the program runs and ends without doing anything

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Ryan
  • 1
  • 1
  • 4
    [Why is the gets function so dangerous that it should not be used?](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) – Retired Ninja Sep 01 '23 at 12:32
  • 1
    Turn up the warnings in your compiler and pay attention to them. https://godbolt.org/z/xdKczaEsd – Retired Ninja Sep 01 '23 at 12:36
  • *I tried using `scanf_s`* ... how did you try? It is not a drop-in replacement for `scanf`. Also MSVC reports 5 warnings and 3 errors from the posted code, i.e. the posted code cannot be run. – Weather Vane Sep 01 '23 at 12:48
  • In C, you do not need and also you should not cast `void*` to another pointer type. It could hide errors. Or in your case, introduce new errors. – Gerhardh Sep 01 '23 at 12:53
  • 1
    With `int i = 0, counter = 1, *firstchar` `firstchar = (char *)malloc(counter);` will not compile. You cannot assign a `char *` to an `int *`. Also, the whole pointer arithmetic on the `int *`s will go out of bounds quite fast. – mch Sep 01 '23 at 12:53
  • @WeatherVane i know these functions are dangerous, but i am not speaking currently on the safety of the functions, just why the code as itself doesn't runs correctly? – Ryan Sep 01 '23 at 12:53
  • As remarked, the posted code won't run at all. It's not the code you describe. Please post a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example), the shortest *complete* code that shows the problem. The best way to do that is by copy/paste the exact, whole program. – Weather Vane Sep 01 '23 at 12:54
  • 1
    What is `SIZE`? – Gerhardh Sep 01 '23 at 12:55
  • @mch I am not assigning char to an int, the (char *) tells the function to create an array of chars, and the (counter) tells the function malloc to set (counter) number of bytes in the array since the sizeof(char)=1, i don't need to declare that in the function. – Ryan Sep 01 '23 at 12:56
  • @WeatherVane but what is the reason it won't run? – Ryan Sep 01 '23 at 12:57
  • You assign `char*` to `int*`. Not `char` to `int`. You explicitely cast the result of `malloc` to a `(char*)` and then assign to `firstchar` which is `int*`. – Gerhardh Sep 01 '23 at 12:59
  • Did you read the man page for `gets`? It tells you never to use it. Use `fgets` instead. `gets` is considered unsafe and is deprecated. – Tom Karzes Sep 01 '23 at 13:01
  • BTW: Do you remember, that strings are nul-terminated character sequences? You don't reserve any memory for a terminating 0 byte in `firstchar` and you also do not add a 0 byte. (Not to mention that your word counter fails if you have multiple spaces in a row.) – Gerhardh Sep 01 '23 at 13:02
  • The reason it won't run is because the code does not compile, and there is no executable to run. Until we know what `SIZE` is, and what string you are entering, it's all supposition. But the compiler is *telling* you what is wrong. Don't even run the code until you have fixed all the warnings. – Weather Vane Sep 01 '23 at 13:03

1 Answers1

0

There are multiple problems in your code:

  • the function gets() is deprecated because it cannot be used safely. Use fgets() instead.
  • void main() should be int main(void)
  • FirstLetters does not compute the number of words correctly: if words are separated by more than one space, the count should not be incremented
  • firstchar, p and q should be defined as char * variables, not int *.
  • firstchar = (char *)malloc(counter); does not allocate space for the null terminator at the end of the firstchar string.
  • *q = *p + 1; stores a '!' in the destination string, not the initial of the next word. You should write *q = p[1]; for this, but the next character might also be a space.
  • the null terminator is not stored.

Here is a modified version:

#include <stdio.h>
#include <stdlib.h>

char *FirstLetters(const char *sent) {
    size_t counter = 0;
    char last = ' ';

    for (const char *p = sent; *p != '\0'; p++) {
        char c = *p;
        if (last == ' ' && c != ' ' && c != '\n')
            counter++;
        last = c;
    }
    char *firstchar = malloc(counter + 1);
    if (firstchar != NULL) {
        char *q = firstchar;
        last = ' ';
        for (const char *p = sent; *p != '\0'; p++) {
            char c = *p;
            if (last == ' ' && c != ' ' && c != '\n')
                *q++ = c;
            last = c;
        }
        *q = '\0';
    }
    return firstchar;
}

int main(void) {
    char sentence[SIZE];

    printf("Enter a sentence: ");
    if (fgets(sentence, sizeof sentence, stdin)) {
        char *firstletter = FirstLetters(sentence);
        printf("The result is: %s\n", firstletter);
        free(firstletter);
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189