-3

Example of the input/output

Please see the code below. The user should enter a sentence and the code should return the acronyms of the sentence.

However, when I allocate *str and define N as 1.

"three letter acronym" >> should be >> "t"

In real time, "three letter acronym" >> is >> "tla"

This doesn't make sense. Please explain why this happens.

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

#define N 1
#define M 35

char *acronyms (char *st,  char *sentence);

int main()
{

char *str=(char*)(malloc(N*sizeof(char)));
char *sen=(char*)(malloc(M*sizeof(char)));

printf("enter... ");
gets(sen);
puts(acronyms(str, sen));

free(str);
free(sen);
    return 0;
}


char *acronyms (char *st,  char *sentence)
{
     char *p = st;
     char *q = sentence;

     if (*q !=' ') {
            *p =*q;
            p++;
     }

     while (*(q+1)) {
         if (*q==' '  &&  *(q+1)!= ' ') {
             *p = *(q+1);
             p++;
         }

        q++;
     }
     *p='\0';
     return st;
}
ChrisF
  • 134,786
  • 31
  • 255
  • 325
Shir K
  • 603
  • 5
  • 9
  • 5
    Do you have a better input/output sample? – Gaurav Sehgal Jan 15 '18 at 12:40
  • 3
    http://commadot.com/wp-content/uploads/2009/02/wtf.png – Lundin Jan 15 '18 at 12:41
  • Don't forget the `'\0'` when you `malloc()`. If you need space for a one character string, you must alloc 2 bytes. And never use `gets()` but `fgets()` – Ingo Leonhardt Jan 15 '18 at 12:47
  • and nowhere in `acronyms()` the number of words taken into account is limited to `N` – Ingo Leonhardt Jan 15 '18 at 12:49
  • but why does the program does not quit? or fail? – Shir K Jan 15 '18 at 12:51
  • 1
    Please show us your plain text as text instead of graphics. – Gerhardh Jan 15 '18 at 12:58
  • 2
    `char *str=(char*)(malloc(N*sizeof(char)));` allocates only one single byte. So the only string that can be stored there is the empty string. This is probably not what you want. – Jabberwocky Jan 15 '18 at 13:01
  • Ok, you're right. so why doesn't it show an empty string? – Shir K Jan 15 '18 at 13:06
  • _but why does the program does not quit or fail?_ and _so why doesn't it show an empty string?_ Because once you've written beyond allocated memory, you enter the realm "undefined behaviour" (google that term), and then anything can happen. – Jabberwocky Jan 15 '18 at 13:07
  • To write a string containing one ASCII character, allocate memory for 2 bytes, one for the character, the next for the NULL terminator. (or just create `char str[2];`) – ryyker Jan 15 '18 at 13:10
  • @ryyker as far as I understood he wants to enter e.g. _What the f@#k_ and get _Wtf_ as output. – Jabberwocky Jan 15 '18 at 13:11

4 Answers4

1

First of all, you should not use gets(). Why?? Check this.

You are allocating only 1 byte of memory to str:

char *str=(char*)(malloc(N*sizeof(char)));

and in function acronyms(), you are writing beyond the allocated memory. This is undefined behavior.

To get the acronym of input sentence, you can do:

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

#define STR_LEN 100

char *acronyms (char *pstr,  char *str_acronym);

int main(void) {

    char input_str[STR_LEN];
    char *sen = NULL;

    printf ("Enter:\n");
    fgets (input_str, STR_LEN, stdin);

    sen = malloc (strlen(input_str) + 1);
    if (sen == NULL) {
            perror ("Failed to allocate memory");
            return -1;
    }

    puts (acronyms(input_str, sen));

    free(sen);

    return 0;
}

char * acronyms(char *pstr,  char *str_acronym)
{
    int count = 0, add = 1;

    for (int i = 0; pstr[i] != '\0'; i++) {
            if (isspace(pstr[i])) {
                    add = 1;
                    continue;
            }
            if (add) {
                    str_acronym[count] = pstr[i];
                    count++;
                    add = 0;
            }
    }
    str_acronym[count] = '\0';

    return str_acronym;
}
H.S.
  • 11,654
  • 2
  • 15
  • 32
1

There are a few problems in the code:

1) allocating only one byte for the string str:

#define N 1
char *str=(char*)(malloc(N*sizeof(char)));

2) using gets(sen) instead of fgets(sen,M+1,stdin);

3) char *acronyms (char *st, char *sentence) has very problematic logic. The end of string is not recognized, the ' ' may or may not be present:

 if (*q !=' ') {
        *p =*q;
        p++;
 }
sg7
  • 6,108
  • 2
  • 32
  • 40
1

This may not seem very satisfying at first glance, but once you have an understanding of the underlying principles pointed to by these 5 concepts (each with example(s)),this, and other similar tasks will seem much simpler.

Necessary steps to do what you are trying:

1) Understand console user input techniques (Good example here)
2) Understand definition of string ( Good definition,explanation here. )
3) Understand usage of [c][m]alloc(...) (Good discussion here... ...)
3a) ...and when to use it. or not. ( heap vs. stack memory )
4) Understand string parsing techniques. ( ex 1 , ex 2, ex 3 )
5) Become aware of legal, but unwise techniques, such as using gets, or in general.

These are generally applicable techniques, useful for many tasks that include user input and string manipulation, but are not a good replacement for referring to a good C book to provide a necessary foundation in the basics.

ryyker
  • 22,849
  • 3
  • 43
  • 87
0

Wellcome in the world of Undefined Behaviour! When you use an array out of its bonds, anything can happen including expected result. That's what happens here: you allocate 1 single byte for str, and write 5 {'h', 'a, 'n', 'd', '\0'}. [Un]fortunately, at a lower level it looks like you only overwrite unused memory, and actually get your result.

Simply as it is UB, you cannot rely on that, and same source compiled in a different environement could SEGFAULT or print nothing with the exact same input.

And as you have been told in comment don't use gets

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252