#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    6
    Rep Power
    0

    Receiving string from keyboard in array of pointers to string


    void main()
    {
    char *names[6];
    int i;
    for(i=0;i<6;i++)
    {
    scanf("%s",names[i]);
    }
    getch();
    }

    i am writing this code and compiler is not giving any error.i am using dev c++.but at runtime its is not executing.why ?
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    You have an array of six char pointers which are pointing nowhere. The more official name of the error you are committing is "using an uninitialized pointer". Extremely bad idea as I shall explain.

    No, that's not entirely correct, those unintialized pointers are not actually pointing nowhere. That array is filled with garbage, which means that all six of those pointers could be pointing anywhere at all, most likely to memory that doesn't belong to you and hence that you have not been granted access to. You are overwriting random memory locations, AKA clobbering, which can cause unpredictable damage.

    What is the maximum size of one of those strings? Add one to that (for the null-terminator, which is like Lenin in an old Soviet joke, it's always with us). Then declare names as a two-dimensional array. Or else read in each name individually into a large-enough buffer, then use malloc to allocate strlen(input_string)+1 bytes of memory to one of the pointers in your array.


    Also, use code tags when you post code listing here. It keeps them readable; eg:
    Code:
    #include <stdio.h>
    #include <conio.h>
    
    void main()
    {
        char *names[6];
        int i;
    
        for(i=0;i<6;i++)
        {
            scanf("%s",names[i]); 
        } 
        getch();
    }
    Also, you should use standard I/O functions instead of conio, which is old and not portable.

    And main should return int, not void, as your compiler should have warned you:
    C:\otros\dcw>gcc -Wall borkut.c conio.c
    borkut.c:5: warning: return type of `main' is not `int'

    C:\otros\dcw>
    We are using the same compiler, MinGW gcc, which was used by and distributed with Dev-C++. That is how I got my copy of it, which I continue to use even though I almost immediately gave up on that buggy Dev-C++ IDE, which hasn't been supported for years, you should know.

    Oh, and also, never ignore warnings! Warnings are much more important than error messages are.
    Last edited by dwise1_aol; March 22nd, 2013 at 04:03 PM.
  4. #3
  5. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,841
    Rep Power
    480
    This reminds me of the time I used my login script to turn off unaligned access warnings.
    set uac 0 # or similar
    Boy was that a mistake!
    [code]Code tags[/code] are essential for python code and Makefiles!
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    6
    Rep Power
    0
    thank you dwise1_aol.thankyou very much.your answer is very clear. i was trying for that from last 3 or 4 days.

    one more thing I want to tell you is thai i am very new to programming.I am learning c from last 3 months that to only with self study.so I was unable to understand what you were telling about standard I/O functions and conio.

    and I know that nowdays everybody is using int as the return type of main rather than void but I want know why they are using it and why the compiler is giving warning.

    So kindly elaborate more on that .
    thank you
    borkut
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    The reason why main returns an int instead of being void is because it needs to report its exit status back to its parent process. For a more complete explanation, the Wikipedia article is at http://en.wikipedia.org/wiki/Exit_code.

    Programmers will normally only see this returned status code when writing perl scripts, shell scripts, or batch files. When called, your program might work normally or it might not be able to because of some error condition; eg, it couldn't find a file it was supposed to open and process, it received the number and types of command-line arguments. The script that called that program needs to know whether it did what it was supposed to or if it failed, so that the script can then decide what to do next. Conceptually, that is no different from having a function return a special value to indicate failure (eg, if fopen succeeds in opening the file, it returns the FILE pointer, but if it fails then it returns NULL; other functions that return an int will customarily return -1 in case of failure).

    The convention that is followed in scripts is that if the program returns zero, then it succeeded. Any non-zero value means failure and the abundance of choices allows the programmer to define a set of error codes to specify exactly what kind of error caused the abnormal termination of the program. There is no standard for specific error code values, so every program is free to define its own, which means that the script writer will need to read the function's documentation if he wants to detect and handle specific types of errors.

    The convention is for the last statement in the main function to be return 0;. Within main, you can return error conditions with other return statements (eg, return 2;), but if you are in another function when you decide to terminate abnormally then return would only take you back to the calling function, not terminate the program. For that, we have the exit(int status); function, which can be called from anywhere in the program and does not return because it immediate terminates the program with the status code that you pass to it. Common practice is to use return 0 to terminate normally at the end of main and exit everywhere else for abnormal termination.


    As for conio, that is more a judgement call that touches on a goal in C programming: portability. If a C program is portable, that means that you can take the source code and compile and run it on any other system. Most high-level programs can be portable, but any program that uses features specific to the operating system loses its portability.

    That's not completely black-and-white in that some non-portable programs are more non-portable than others and this can affect how a programmer will organize his program. One programming task is to take a program on one platform (refering to the computer itself and the operating system) and porting it to another platform -- read Wikipedia at http://en.wikipedia.org/wiki/Porting. Porting involves finding the non-portable elements of the code and rewriting them to do the same thing on the target platform. Of course, some programs are harder to port than others because of how the original programmer had organized his code. If he sprinkled the non-portable elements throughout the code, then it can be a nightmare for the programmer who has to port it. But if he collected all the non-portable elements in one or a few places, usually within wrapper functions (http://en.wikipedia.org/wiki/Wrapper_function) to be called from the standard parts of the code, then that makes the porting process much easier and more fool-proof, since the porting programmer would only need to change those few files. One of the more famous stories of successful porting is UNIX, which was co-developed with C circa 1970. Traditionally, operating systems were written in assembly, which is most highly non-portable, so porting an operating system meant having to rewrite it completely almost from scratch. But the UNIX kernel was written in C, so almost all you needed to do to port it was to install a C compiler on the target system and recompile the kernel. The most non-portable part, the low-level code that dealt with the hardware, was contained mainly in the drivers which the kernel would call, so most of the work in porting UNIX was in rewriting the drivers, a much easier task than rewriting the entire kernel. And in porting the C compiler, which I would assume was organized to facilitate porting.

    conio ("Console I/O") is an MS-DOS library (read http://en.wikipedia.org/wiki/Conio). It was written for MS-DOS compilers and used either MS-DOS system and BIOS calls or intimate knowledge of BIOS and RAM usage. It is highly specific to MS-DOS and does not exist in any other operating system except as a port. As such, it is not portable. Though to be fair, what it does is also not portable, with different operating systems handling those low-level functions differently.

    So it becomes a judgement call. conio is there for quick-and-dirty applications and to get started, but there are other ways that you also need to learn, so you mustn't become overly dependent on conio.

    But more specific to your program, instead of getch you should use getchar, which is in the standard library.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    6
    Rep Power
    0
    thank u very much again.right now i was unable to understand some parts. so i will try to read all that again in depth. and if any doubt emerges i will come back to u.
    thank u
    borkut.

IMN logo majestic logo threadwatch logo seochat tools logo