Thread: get_string code error

  1. #1
    Registered User
    Join Date
    Apr 2020
    Posts
    7

    get_string code error

    I am still learning and went across the usage of libraries and said I should create the function myself. I created this function in another file and I don't know why it's not working. I think it has something to do with defining a string as a pointer and defining it with arrays? I really don't understand the difference, if someone can help it'd be awesome and tell me what I did wrong with my code.

    Code:
    char *get_string(char *s)
    {
        char *temp;
        printf("%s\n", s);
        scanf("%s", &temp);
        printf("%p\n", temp);
        printf("%s\n", temp);
        return temp;
    }
    EDIT: I used many printf's to keep track of the address

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    There are several things wrong with that function.

    First temp is a pointer to a char, not a pointer to an array of char, so it can not be a C-string and it is also not initialized.

    Second because temp is a pointer to a single character using the "%s" format specifier in your scanf() call produces undefined behaviour, and will probably cause the program to crash.

    Third the "%p" format specifier expects a void* as the variable type.

    Fourth you can not return a pointer to a local variable because that variable will go out of scope when the function returns.

    Fifth never use a method that doesn't limit the number of characters it will try to retrieve into a C-string to help prevent buffer overflow errors.

    Sixth as already pointed out a pointer is not the same thing as an array. A string in C is an array of char.

    Edit:

    Also in future please describe the problem more thoroughly, "I don't know why it's not working" doesn't tell us anything about the problem. Is the program failing to compile, or does it crash upon running, producing unexpected results, etc.

    If you have compile warnings/errors post the complete warning/error listing, all of them exactly as they appear in your development environment.

    Also it would be helpful to see how you are trying to call this function, so providing a small main() that shows how the variables are defined and showing how you are calling the function would be helpful.
    Last edited by jimblumberg; 05-03-2020 at 07:27 AM.

  3. #3
    Registered User
    Join Date
    Apr 2020
    Posts
    7
    Quote Originally Posted by jimblumberg View Post
    There are several things wrong with that function.

    First temp is a pointer to a char, not a pointer to an array of char, so it can not be a C-string and it is also not initialized.

    Second because temp is a pointer to a single character using the "%s" format specifier in your scanf() call produces undefined behaviour, and will probably cause the program to crash.

    Third the "%p" format specifier expects a void* as the variable type.

    Fourth you can not return a pointer to a local variable because that variable will go out of scope when the function returns.

    Fifth never use a method that doesn't limit the number of characters it will try to retrieve into a C-string to help prevent buffer overflow errors.

    Sixth as already pointed out a pointer is not the same thing as an array. A string in C is an array of char.

    Edit:

    Also in future please describe the problem more thoroughly, "I don't know why it's not working" doesn't tell us anything about the problem. Is the program failing to compile, or does it crash upon running, producing unexpected results, etc.

    If you have compile warnings/errors post the complete warning/error listing, all of them exactly as they appear in your development environment.

    Also it would be helpful to see how you are trying to call this function, so providing a small main() that shows how the variables are defined and showing how you are calling the function would be helpful.
    I highlighted in green the points that I understood, thank you. And as a response to them, I want to know how libraries would have a get_string without any boundaries in the input because I never know what the user wants to type down.

    As for the first blue part, "%p" returns the address and it does return the address successfully.
    For the second blue part, how are there some software applications that do not limit ur input or am I having a wrong perspective.

    I didn't understand the fourth part, do you mean the pointer temp or the function itself, thats my only question.

    Sorry, It's still my first thread and it doesn't give me the expected results in main. An example would be like this.
    Code:
    int main()
    {
        char *name = get_string("Insert your name: ");
        printf("Your name is %s\n", name);
        return 0;
    }
    I am only writing this simple code to understand the difference between arrays and pointers and how strings are just pointers.

    Thank you.

  4. #4
    Registered User catacombs's Avatar
    Join Date
    May 2019
    Location
    /home/
    Posts
    81
    Quote Originally Posted by jimblumberg View Post

    First temp is a pointer to a char, not a pointer to an array of char, so it can not be a C-string and it is also not initialized.
    What's the best way to declare a pointer to a character array?

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by catacombs View Post
    What's the best way to declare a pointer to a character array?
    Step 1. You need an character array.
    Step 2. You assign the starting address to the pointer.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by 7usseiny
    strings are just pointers
    In C, strings are not "just pointers". Rather, a string is a contiguous sequence of characters terminated by a null character. This implies that you need an array of some kind to store a string, and once you have an array, you can have a pointer to the first character of the array.
    Last edited by laserlight; 05-03-2020 at 03:58 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Apr 2020
    Posts
    7
    I still didn't get the best way to make my function and no one answered my reply to Tim.

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    As for the first blue part, "%p" returns the address and it does return the address successfully.
    Okay, so you're getting lucky. How long do you think you will continue to be lucky?

    From some documentation for printf() since it is referenced above:
    p
    The void * pointer argument is printed in hexadecimal (as if by %#x or %#lx).
    So notice that printf() is expecting a void*, not a char*. The reason you are probably being lucky is because you're dealing with a char pointer.

    For the second blue part, how are there some software applications that do not limit ur input or am I having a wrong perspective.
    I'm not talking about "software applications", I'm talking about functions/methods. In this case scanf(). When processing a string scanf() will continue processing the string until it encounters some whitespace character no matter how big the the array actually is. So to eliminate the problem, always use a method that stops the processing before overflowing the bounds of the array.

    The scanf() function uses the optional width format specifier as the limit:

    Code:
    char my_strting[10];
    scanf("%9s", my_string); // Notice the width specifier, and see below.
    Notice that the width specifier is one less than the actual size of the array, this is because you must reserve room for the end of string character that will be added to the string by scanf().

    I didn't understand the fourth part, do you mean the pointer temp or the function itself, thats my only question.
    In this case I meant the pointer temp, that is local to that function. You can return a pointer from the function but it must be either a pointer that has been declared as static, a dynamically allocated pointer, or you can return a pointer that is a parameter.

    I am only writing this simple code to understand the difference between arrays and pointers and how strings are just pointers.
    Don't get yourself confused by thinking strings are "just pointers", they are not "just pointers", nor are they just arrays. In C a string is an array of char that is terminated by the end of string character ('\0'). Without this terminator you just have an array of char. Also an array is subtly different than a pointer, but an array decays very easily into a pointer to the first element of the array.

    Be careful with that "array" you are passing into that function. It is actually a pointer to a constant array of char.

    That function should really be defined as:

    Code:
    char *get_string(const char *s);
    // But IMO the following would be better:
    char *get_string(const char s[]);
    Both the above declarations would be treated the same by the compiler, but IMO the second strongly hints that you're passing a string not a pointer to a single character.


    By the way your original code gives these messages when I try to compile it:
    main.c||In function ‘get_string’:|
    main.c|11|warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]|
    If you're not getting any warnings you should see about increasing your compiler warning levels.

    Remember that the name of the array is a pointer so you don't need the ampersand.

    When you fix that issue you should then get this warning:

    main.c||In function ‘get_string’:|
    main.c|14|warning: ‘temp’ is used uninitialized in this function [-Wuninitialized]|
    Now making temp a local array:
    Code:
        char temp[100];
        scanf("%99s", temp);
    Produces this error:
    main.c||In function ‘get_string’:
    main.c|17|warning: function returns address of local variable [-Wreturn-local-addr]|
    Now one way to fix this problem:

    Code:
    char *get_string(const char *s)
    {
        printf("%s\n", s);
    
        static char temp[100];
        scanf("%99s", temp);
    
        return temp;
    }
    But be careful if you call the function multiple times the values pointed to will change.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You need to understand jimblumberg's point and code concerning the field width for %s when reading with scanf, but once you do, what I had in mind was something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    char *get_string(const char prompt[], char input[], size_t input_maxlen)
    {
        char format[23]; // account for "%s" and the range of size_t for the field width
        sprintf(format, "%%%zus", input_maxlen);
        printf("%s", prompt);
        return (scanf(format, input) == 1) ? input : NULL;
    }
    
    int main(void)
    {
        char name[100];
        if (!get_string("Insert your name: ", name, sizeof(name) - 1))
        {
            fprintf(stderr, "Sorry, there was an error when reading your name.\n");
            return EXIT_FAILURE;
        }
        printf("Your name is %s\n", name);
        return 0;
    }
    The idea here is that you create the array to store the name in main, and then get_string just works according to whatever you pass to it, whether it be a name of up to a length of 99, or some other length. Since the maximum length is variable, you need to build the format string accordingly. As you originally chose to have get_string return a pointer rather than void, I have changed it to return a null pointer to indicate a read failure; in practice you should not see a read failure as you're just reading a string rather than doing any parsing, but it can be a useful pattern to follow when you do want to parse for say, a number.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Apr 2020
    Posts
    7
    Thanks a lot!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code Blocks showing error in code! Don't know what's it.
    By kdushyant297 in forum C Programming
    Replies: 2
    Last Post: 09-08-2017, 09:59 AM
  2. error in code
    By zeybek258388 in forum C Programming
    Replies: 3
    Last Post: 12-31-2011, 03:34 PM
  3. An error in my c code
    By Amera in forum C Programming
    Replies: 9
    Last Post: 12-23-2009, 12:38 AM
  4. error in my code, please help
    By Leeman_s in forum C++ Programming
    Replies: 4
    Last Post: 05-25-2003, 04:10 PM
  5. error with code
    By duffy in forum C Programming
    Replies: 8
    Last Post: 10-22-2002, 09:45 PM

Tags for this Thread