-1

I am trying to get 2 inputs from user with unknown length of char pointer.(Working on dynamically allocating memory) But after entering 1st input with a "space" it doesn't wait for user to enter second input, it only reads one word and then it allows second input.

          char *str1;
          char ch;
          printf("Enter a sentence:(Ex: Computer Engineer)");
          str1 = (char*)malloc(sizeof(char*));
          scanf(" %s", str1);
          printf("Enter a character to search(Ex: g):");
          scanf(" %c", &ch);
          char *result;
          result=mystrchr(str1,ch);
          if(result!=NULL)
            printf("%s",result);
          else
            printf("NULL");
bitsedegitsek
  • 87
  • 1
  • 10

2 Answers2

1

The second exact same statement of

str1 = (char*) malloc(sizeof(char*));

is redundant, inappropriate and useless. By doing so you allocate another memory space to which str1 is pointing to; leaving the previous allocated space because of no free()ing abandoned but existing in memory.


char *str1;
str1 = (char*) malloc(sizeof(char*));

With that call to malloc() you allocate memory of the size of a pointer to char, usually 4 bytes on most modern systems, not the space needed to store a string like "Computer Engineer". With this definition it is only be able to store a string of 3 characters plus the automatically appended string-terminating null character (4 characters for 4 bytes).

By putting in a string longer than 3 characters by the call to scanf():

scanf(" %s", str1);

the program will write beyond the bounds of the allocated memory, which invokes undefined behavior (like it was high-probably happened in your case).


You need to allocate enough space to hold the provided strings - in the case of f.e. "Computer Engineer" it needs to have at least 18 byte (Note that sizeof(char) == 1):

char *str1 = malloc((sizeof(char) * 18);

or alternatively:

char *str1 = malloc((sizeof(*str1) * 18);

Note that you can´t put in a white space separated word by using the %s format specifier. For achieve that, use %[ instead:

scanf("%[^\n]", str1);

Or even better use the more reliable and safer fgets():

fgets(str1,18,stdin);

If you want to allocate memory dependent upon the input of a user, you need to add another input request and variable before allocating:

int len;

printf("How many characters the string should have?");
scanf("%d",&len);

char *str1 = malloc((sizeof(*str1) * (len + 1));     // +1 element for null character.

printf("Enter a sentence:(Ex: Computer Engineer)");
fgets(str1,len,stdin);

Side note:

You do not need to cast the returned pointer of malloc -> Do I cast the result of malloc?

  • I mistakenly add redundant "str1 = (char*)malloc(sizeof(char*));" line, I don't want to specify the character size of the entered word. I want my program to create it is own memory according to entered input so dynamically. – bitsedegitsek May 02 '20 at 15:37
  • @NeverSAYnever I´ve added the user determinate size of the memory allocation requested by you to the answer. Check it out. – RobertS supports Monica Cellio May 02 '20 at 17:17
0

Programming is not just aligning lines of codes. Memory allocation in C is not very complex but it is very easy to write erroneous code with it (you did...).

This is just err... bad code:

  str1 = (char*)malloc(sizeof(char*));  // Wrong: you allocate a char array with
                                        //  the size of a char pointer: nonsense
  printf("Enter a sentence:(Ex: Computer Engineer)");  // no error here :-)
  str1 = (char*)malloc(sizeof(char*));  // Wrong: the previously allocated array is
                                        //  now leaked: you can no longer free it
  scanf(" %s", str1);                   // What if input is larger than sizeof(char*)?

Now for your question: scanf reads blank delimited tokens. It is a feature. If you want line oriented input, you should use fgets.

Code could be:

#define SIZE 16
size_t size = SIZE;         // initial size of the allocated array
char *str1 = malloc(size);  // sizeof(char) is by definition 1
char ch[2];                 // a trick to read next non blank character

printf("Enter a sentence:(Ex: Computer Engineer)");
char *str = str1;
for(;;) {                                // loop to accept arbitrary length input
    if (NULL == fgets(str, size, stdin)) {
        perror("Input error or end of file");
        return 1;
    }
    if (strchr(str, '\n') != -1) break;   // ok we have a full line
    str1 = realloc(str1, size * 2);
    if (NULL == str1) {
        perror("Could not allocate memory");
        return 1;
    str = str1 + size - 1;                // point after currently got data
    size = size * 2;
}
printf("Enter a character to search(Ex: g):");
scanf("%1s", ch);
char *result = mystrchr(str1,ch[0]);
...

Beware: code is untested and could contain typos...

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