0

hey guys i have looked around for a solution and tried everything i can think of im new to pointers and dynamic strings and i could really do with some help with problem. im currently learning c and i need to get the user to input a dynamic size for the string length . i need to make it so the users input can not be bigger then 100 . here's where i am at currently . i have the code booting but if i try set the size to let's say 5 i can still input way more chars into the string. cheers really appreciate any help .

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

int main () {
    int  maxSize = 100; 
    char *name = (char*) malloc (maxSize * sizeof (char));
    int n; 
    char text1[]= ("input string size\n");

    printf ("your string lenght is %d\n", strlen(name));

    //getting size 
    n=intPrintScanner(text1);
    printf ("your size is %d\n",n);

    name = realloc (name,  sizeof (char) * n);

    //printing results 
    printf ("your string lenght is %d\n",strlen (name));
    scanf("%s", name);
    printf("your string is %s",name);

    free(name);

    fflush(stdin);
    printf("press any key to close");
    getchar();
    return (0);
}
Bodo
  • 9,287
  • 1
  • 13
  • 29
  • Your use of `strlen()` is wrong. Thaf function does not return the size of the allocated buffer but the length of the string you've copied into it. You haven't copied any, so it invokes Undetined Behaviour. There's no way to determine the size of an allocated buffer afterwards so you have to stick to the values you've passed to `malloc()` and `realloc()` – Ingo Leonhardt Oct 21 '22 at 10:29
  • `fflush(stdin);` is undefined behavior, and `getchar()` reads a single character, but requires pressing the Enter/Return key, so "press any key to close" is misleading. Is your main question how to prevent `scanf("%s", name);` to read more characters than fit in the allocated memory? see https://stackoverflow.com/a/12908721/10622916 or https://stackoverflow.com/a/44663029/10622916 – Bodo Oct 21 '22 at 11:26
  • We can help you if you [edit](https://stackoverflow.com/posts/74152019/edit) your question with proper English capitalization. Then let us know if you can use POSIX `getline()`. – Costantino Grana Oct 21 '22 at 11:43
  • Does your C implementation of `scanf` allow for `%ms`? It's extremely convenient, albeit not standard. – Costantino Grana Oct 21 '22 at 11:46

2 Answers2

2

Bugs:

  • You never assign any data to name so it just contains garbage. You can't use strlen on it before you have stored valid data there either. You can store a string inside name by for example using strcpy.

  • When using realloc, there's no guarantee that the old pointer is the same as the returned pointer. Also, you need error handling. Implement it like this instead:

    char* tmp = realloc (name, n);
    if(tmp == NULL) 
    { 
      /* actual error handling here in case realloc fails */ }
    }
    name = tmp; // assign pointer to the new area only if allocation succeeded
    
    
  • fflush(stdin); is not well-defined, never use fflush on input streams. Instead you should discard unwanted line feed characters from stdin - which could be as trivial as an extra getchar() call just after reading something. Check out How to read / parse input in C? The FAQ for lots of general good advise regarding how to take input from stdin.

Cosmetic/style:

  • No need for parenthesis here: char text1[]= ("input string size\n");. All it achieves it to make the code look strange.

  • The correct form of main is int main (void). The int main() is obsolete style.

  • There is no need to wrap the expression passed to return in a parenthesis.

  • There is never a need to multiply something with sizeof (char), since sizeof (char) is by definition always 1 no matter system.

  • There is no need to cast the result of malloc.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

char* read_until(int fd, char end) {
      int i = 0, size;
      char c = '\0';
      char* string = (char*)malloc(sizeof(char));

     while (1) {
          size = read(fd, &c, sizeof(char));

          if (c != end && size > 0) {
              string = (char*)realloc(string, sizeof(char) * (i + 2));
              string[i++] = c;
          } else {
              break;
          }
      }

                string[i] = '\0';
        return string;
 }

int main()
{
        char *name;
        int correct=0;

        do{
                write(1,"Put a name: ",strlen("Put a name: "));
                name = read_until(STDIN_FILENO,'\n');

                if(strlen(name) > 99){
                        write(1,"Error\n",strlen("Error\n"));

                }else{
                        correct=1;
                }

        }while(correct != 1);

        write(1,name,strlen(name));
       
        free(name);

}

Try using write and read instead of printf and scanf, it is better for allocating dynamic memory, read and try to understand the read_until function, there are better ways to do main.

  • 1
    I think the OP would learn more by explaining and fixing the errors in the original code than by providing a completely different implementation without much explanation. Why is `read` better than `scanf` with a size limitation or `fgets` (or even `getchar`)? Why is `write` bettern than `printf` or `puts`? As far as I understand the question, the requirement is to enter the maximum size first, then making sure the string input does not exceed the size. – Bodo Oct 21 '22 at 11:26
  • 1
    `read` and `write` are not available in the C standard. – Costantino Grana Oct 21 '22 at 11:33
  • 1
    If `read` was available in the language proper, it is a terrible idea to suggest using it to read a single character at a time. Especially to a beginner. – William Pursell Oct 21 '22 at 11:35
  • You could produce this same code with `fread` and `fwrite` with minimal changes, but showing this with `getchar` would be more helpful to the OP – William Pursell Oct 21 '22 at 11:36