Thread: How to do this

  1. #1
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804

    How to do this

    Halo all,

    I've made a simple code in which i'm trying to read a string and compare it with another string. The problem is that i'm not able to get the string from the user neither from scanf nor from fgets. I get run time error. One more thing how can i assign the array size in the second argument of fgets when i'm using pointer format of a string.

    Code:
    #include<stdio.h>
    #include<string.h>
    #include<conio.h>
    int main(void)
    {
    	char *p="hello",*q;
    	int x;
    	printf("Enter the string");
    	//scanf("%s",*q); I did this one time
    	fgets(q,10,stdin);// At the other time i did this
    	x=strcmp(p,q);
    	if(x==0)
    	{
    		printf("YES");
    	}
    	else
    	{
    		printf("NO");
    	}
    	getch();
    }
    Also what are the advantages of declaring a string as "char *s" rather than "char s[20]" with respect to memory? I mean if the string is of 10 chars then in the latter form 10 bytes will get wasted, does the same happens in the former also?
    Last edited by BEN10; 05-24-2009 at 06:49 AM.
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by BEN10 View Post
    Also what are the advantages of declaring a string as "char *s" rather than "char s[20]" with respect to memory?
    Char *s is a pointer with no memory.

    Char s[20] can hold 20 bytes.

    So there is not an advantage, and using using *q as you do in your program will probably cause an overflow/overwrite (= segmentation fault, your runtime error).
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > Also what are the advantages of declaring a string as "char *s" rather than "char s[20]" with respect to memory?
    The latter points to something you can use :-)

    "q" doesn't point to anything meaningful (most certainly an area of memory you're not allowed to access).

    Don't be worried about "wasting" 10 bytes. Unless you're on some super-memory-restricted-machine, which I doubt.

    Perhaps a more compliant example:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
       const char * p = "hello";
       char q[32];
       int x = 0;
    
       printf("Enter the string");
       fflush(stdout);
    
       fgets(q, sizeof q, stdin);
    
       x = strcmp(p, q);
    
       if(x == 0)
          printf("Yes");
       else
          printf("No");
       
       fflush(stdout);
    
       getchar();
       return 0;
    }

  4. #4
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by zacs7 View Post
    > Also what are the advantages of declaring a string as "char *s" rather than "char s[20]" with respect to memory?
    The latter points to something you can use :-)

    "q" doesn't point to anything meaningful (most certainly an area of memory you're not allowed to access).

    Don't be worried about "wasting" 10 bytes. Unless you're on some super-memory-restricted-machine, which I doubt.

    Perhaps a more compliant example:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
       const char * p = "hello";
       char q[32];
       int x = 0;
    
       printf("Enter the string");
       fflush(stdout);
    
       fgets(q, sizeof q, stdin);
    
       x = strcmp(p, q);
    
       if(x == 0)
          printf("Yes");
       else
          printf("No");
       
       fflush(stdout);
    
       getchar();
       return 0;
    }
    My question is how can I input a string using char *q format? Or is it that char *q is helpful only while initializing the string, in case of inputting I should use char q[32]? And why did you use fflush(stdout)?
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    I realise that a lot of people will have told you a pointer is an array. They are wrong. Problem is: you have believed them, and that is the underlying reason for your runtime error.

    You need to understand that a pointer is not the same thing as an array. The problem is, in some contexts, they seem to be the same but they really are not.

    A pointer is simply a variable that stores a memory address. It points to an area of memory that the programmer has to explicitly obtain (eg as the address of the first element of an array, via a call to malloc(), etc).

    Declaring a pointer does not magically create something (eg an array) that is pointed at.

    The problem with the "first form" in your code (which I've simplified here)
    Code:
           char *q;
    	printf("Enter the string");
    	fgets(q,10,stdin);// At the other time i did this
    is that q is never initialised to point at anything. fgets() assumes it points to the first element of a character array, in this case of length 10 characters. However your code does not make that happen. The result is undefined behaviour.

    In practice, a common result (but not a guaranteed result) is a runtime error - which is what you're seeing. That is the primary disadvantage of using a pointer as you have in your code.

    fgets(), in your code, does not magically allocate memory to hold the data it reads from standard input. q is uninitialised, so it points at some random area of memory. fgets() simply overwrites that area of memory (up to ten characters of it, due to the value of the second argument).

    To avoid that, you need to make q point at something. For example;
    Code:
         char *buffer[10];
         char *q = buffer;   /*  or equivalently  char *q = &buffer[0]; */
    or
    Code:
        /*   Assume stdlib.h is included */
        char *q = malloc(10);
    
         /*  Do your work with it  */
    
        free(q);
    Note for purists: I've deliberately glossed over some details in the above because explaining those details is more likely to confuse beginners like BEN10 than to help them.

  6. #6
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    So it means it'll be better to use the array form i.e char a[10] when I want to input the string from the user and when I want to initialize the string then i may use char *a form.
    Why you have done this
    Code:
    char *buffer[10];//shouldn't it be char buffer[10]
         char *q = buffer;   /*  or equivalently  char *q = &buffer[0]; */
    Last edited by BEN10; 05-26-2009 at 10:44 PM.
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I think grumpy was just trying to provide an example. *buffer[10] would be an array of pointers -- in your program, you don't want that.

    You can create a variable to fit the exact size of the input if you want, but you cannot do it in the actual fgets statement; you still have to use a buffer there of a predetermined size. Afterword, you can call strlen() on the buffer, and then malloc() a separate variable of that size and strcpy() into it. Of course, there is no point in doing that in main to save memory, since "buffer" will never die. But if you wrote it into a separate function, you could save memory, because once the function is finished it's local variables will be freed/recycled. Just to let you know.

    But in the case of user input, where we are talking about < a single kb, there is not much of a point to that.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    I modified my code and still not getting the correct output.
    Code:
    #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    int main(void)
    {
    	char *p="hello";
    	char q[10];
    	int x;
    	printf("Enter the string");
    	fgets(q,10,stdin);
    	x=strcmp(p,q);
    	if(x==0)
    	{
    		printf("YES");
    	}
    	else
    	{
    		printf("NO");
    	}
    	getch();
    }
    I'm inputting hello but still getting printed NO. I printed x and it shows me a value of 1, why x not getting equal to 0?
    And finally what is the need of fflush(stdout) in zac7's code?
    Last edited by BEN10; 05-26-2009 at 11:08 PM.
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    An easy way to test this would be with a printf:
    Code:
    printf("->%s<-",q); fflush(stdout);
    Notice I enclosed the ->string<-. If you add this into your program, you will probably see:

    ->hello
    <-

    Because fgets includes the newline, so q is "hello\n" (which does not match).

    The purpose of fflush(stdout) is to force the output to be "flushed" immediately, since output is actually held until it reaches a certain size or some other circumstance (like, the program is over). Generally, fflush is not necessary. However, it is important when using printf to debug (like above) because is you are trying to (eg) locate the source of a segmentation fault, the output buffer may not be flushed, so you will be misled as to where the fault is.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Registered User
    Join Date
    Apr 2009
    Location
    Russia
    Posts
    116
    BEN10,
    Code:
        char *p="hello";
    you know, all strings write to read-only memory, all strings like printf("one two three\n"); - "one two three\n" literal constant it goes to read-only memory and have address, that address then pass to function printf, it reads it and print then, so your "hello" is string literal too, it goes to read-only memory and every it's charachter has an adress (six characters), address of first character assigns to p pointer; that is why you can't change it, when you try to change it, you try to change read-only memory
    in K&R 5.5

  11. #11
    and the hat of copycat stevesmithx's Avatar
    Join Date
    Sep 2007
    Posts
    587
    Quote Originally Posted by c.user View Post
    BEN10,
    Code:
        char *p="hello";
    you know, all strings write to read-only memory, all strings like printf("one two three\n"); - "one two three\n" literal constant it goes to read-only memory and have address, that address then pass to function printf, it reads it and print then, so your "hello" is string literal too, it goes to read-only memory and every it's charachter has an adress (six characters), address of first character assigns to p pointer; that is why you can't change it, when you try to change it, you try to change read-only memory
    in K&R 5.5
    ZOMG, lolz , if it is a "read only memory" in the first place, how on earth would you put your string there?.
    Last edited by stevesmithx; 05-27-2009 at 01:29 AM.
    Not everything that can be counted counts, and not everything that counts can be counted
    - Albert Einstein.


    No programming language is perfect. There is not even a single best language; there are only languages well suited or perhaps poorly suited for particular purposes.
    - Herbert Mayer

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Steve, it's a string literal, and you can't change those strings, (until the program ends, of course).

    Not every compiler uses that part of memory, in that way, but most do, I believe.

    Ben, MK answered your question, you could test it by adding a '\n' char to the end of your "hello" string ==> "hello\n", and see if it compares as equal.

    fgets retains the newline at the end of s, but fgets puts an end of string char at the end of the string you enter, if there is room for it. So it could be: "hello\0" if the buffer has enough room for this extra char (it should).

    One of those two will solve your problem.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by stevesmithx View Post
    ZOMG, lolz , if it is a "read only memory" in the first place, how on earth would you put your string there?.
    Because it is set to read-only by the OS _AFTER_ the OS has stored it there in the first place.

    The technical details of this is that the OS has control of the page-table which determines what process has what access-rights to which bits of memory. The OS itself can change the attributes, and it can also bypass the attributes by using a secondary mapping of the same memory, with a different set of attributes.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    and the hat of copycat stevesmithx's Avatar
    Join Date
    Sep 2007
    Posts
    587
    Thanks for the clarification, guys.
    "write to read-only memory" sounded a bit like an oxymoron to me.
    A term like "protected memory" instead of "read-only memory" which might refer to the ROM of the machine would be less ambiguous i guess.
    Not everything that can be counted counts, and not everything that counts can be counted
    - Albert Einstein.


    No programming language is perfect. There is not even a single best language; there are only languages well suited or perhaps poorly suited for particular purposes.
    - Herbert Mayer

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    But read-only memory is a common term for "non-writable" memory in modern systems. It is in RAM, but the OS has marked it to be "non-writable". And it can not be written BY THE APPLICATION, but it CAN be written to by the OS (if the OS decides that it wants to).

    The code itself is almost always read-only, but if you use a debugger, the OS will write breakpoint instruction(s) into the code itself [and store away the previous instruction so that it can be put back in again when the breakpoint is no longer in use].

    Like most things, you have to get used to the nomenclature, whether it actually makes sense or not.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed