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

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2

    Printf() function won't print...


    Hi guys.

    for some reason, the printf function just won't print!

    here's the code:

    Code:
    #include<stdio.h>
    #include"functions.h"
    
    int main()
    {
    	char input[100];
    	char substrings[10][10];
    	char delimiter;
    	int test;
    
    
    	printf("Enter a string\n");
    	scanf("%s", input);
    	printf("Enter a delimiter\n");
    	scanf(" %c", delimiter);
    	test=Split(input[100],delimiter,substrings[10][10]);
    	printf("%d", test);
    }
    when i run this code, it skips the printf() command at the end of the code (the last line).
    what am i missing here?

    thanks in advanced!
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    Are you running this from the command line as you're supposed to?

    Or are you instead launching it from a GUI (eg, from a GUI development environment or from a GUI Windows Explorer), thus creating a console (AKA sub-shell) on-the-fly in which to run it and which closes automatically the instant that the program terminates, such that even though the printf had worked its output didn't display long enough for you to see it?

    If it is the latter case, then why didn't you tell us up-front exactly what it was that you saw?

    BTW:
    test=Split(input[100],delimiter,substrings[10][10]);
    This is no input[100] element, but rather only input[0] through input[99].
    Same goes for substrings[10][10]. And if that function calls for arrays instead of individual char values, then I'm surprised that your compiler didn't complain about that line.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi dwise1_aol. thanks for the help.

    i'm running it from Eclipse, where there's console window at the bottom.
    when the program terminates, the window stays open and the last output is displayed there until next launch,

    about that last remark:
    yes, the function calls for arrays:

    Code:
    int Split(char input[100], char delimiter, char substrings[10][10]);
    it's supposed to split each array in "input[]" to several substrings.
    it's only my first attempt so i didn't have the chance to see how or if it works (because printf() won't print).

    and what did you mean about "This is no input[100] element, but rather only input[0] through input[99]."?
    that i can only store upto 99 chars?
    i know that, but as i was saying - that's just a test to check that the function works.
    i wanna handle with array's limitation later.
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    Originally Posted by so.very.tired
    about that last remark:
    yes, the function calls for arrays:

    Code:
    int Split(char input[100], char delimiter, char substrings[10][10]);
    And yet you are passing it individual char values, not arrays. Didn't Eclipse complain about that? Do you have warnings turned on?

    I would think that line should have been something more like:
    test=Split(input,delimiter,substrings);
    Though it's been a very long time since I've tried passing a 2-D array. But try that change and see whether any of the warnings go away.

    Never ignore warnings! They are much more important than error messages.

    Originally Posted by so.very.tired
    and what did you mean about "This is no input[100] element, but rather only input[0] through input[99]."?
    that i can only store upto 99 chars?
    As declared, the input array does indeed have 100 elements, which are indexed zero through 99. Count 0 through 99 and you will find that that adds up to 100. So input[99] is the 100th and last element; there is no input[100] element and trying to access it is exceeding the range limit of that array.

    Though for a different reason, that character string will have a maximum length of 99, because with C-style strings you always need to allocate one more char for the null-terminator ('\0') which marks the end of the string. If you want to be able to hold a string with a length of 100 characters, then you need to declare input for 101.

    Originally Posted by so.very.tired
    it's supposed to split each array in "input[]" to several substrings.
    it's only my first attempt so i didn't have the chance to see how or if it works (because printf() won't print).
    Does Eclipse indicate whether the program has terminated? If it crashed (possible with those bogus values you passed that function, since by misinterpreting those char values as pointers that function would have undoubtedly triggered a segfault or access violation), does Eclipse tell you that? Can you tell the difference in Eclipse between a program that has completed and one that is hung up in an infinite loop? I'm asking, because Eclipse really should tell you those things, so that you shouldn't need to depend on a print statement.

    Even better, does Eclipse come with a debugger? If so, then step through your program.
    Last edited by dwise1_aol; December 11th, 2012 at 02:46 PM.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi dwise1_aol, and thanks again for helping.

    i found the problem...
    the function Split() had an infinite loop in it, so the program never made it to the main() again...
    for some reason Eclipse terminated the program instead of keeping the program running so i can notice that something is wrong.

    anyway, as long as we're on that subject:
    i'll try to send to the function only arrays' addresses, like you suggested, and will report back.
    but about the null-terminator '\0', a few questions:
    1. does the function gets() (i.e. (gets(array)) also allocate '\0' at the end of the string? or just scanf() does that?
    because from what i've been reading, i understand that gets() does not limit the string length and therfore kinda dangerous to use.
    2. can i use it as an indicator? for example:

    Code:
    for (i=0; array[i]!='\0' ;i++)
    {
       code
     }
    or

    Code:
    while (array[i]!='\0')
    {
       code
       i++;
    }
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    OK, i had the chance to test it.

    Originally Posted by so.very.tired
    anyway, as long as we're on that subject:
    i'll try to send to the function only arrays' addresses, like you suggested, and will report back.
    yes. compiling without any warnings.
    i wasn't aware that i'm passing single char instead of array's address...
    thanks for that.

    Originally Posted by so.very.tired
    but about the null-terminator '\0', a few questions:
    1. does the function gets() (i.e. (gets(array)) also allocate '\0' at the end of the string? or just scanf() does that?
    because from what i've been reading, i understand that gets() does not limit the string length and therfore kinda dangerous to use.
    yes, it also allocate '\0' at the ent of the string.
    so that raise the question: what is the problem with gets(), really?
    even Eclipse is warning me from using it...
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    Originally Posted by so.very.tired
    i'll try to send to the function only arrays' addresses, like you suggested, and will report back.
    but about the null-terminator '\0', a few questions:
    1. does the function gets() (i.e. (gets(array)) also allocate '\0' at the end of the string? or just scanf() does that?
    because from what i've been reading, i understand that gets() does not limit the string length and therfore kinda dangerous to use.
    C-style strings are defined as being terminated by a byte of zero ('\0'), so every library function will terminate a string with a null-terminator. There are a couple exceptions, though, but those are very special cases. For example, there's a version of strcpy, the string-copy function, called strncpy, which allows you to limit the number of characters being copied as a way to avoid overflowing the destination char array. strncpy copies at most the number of characters that you specify, but:
    The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
    The main point here is that you need to be aware of how that library function will behave under all conditions, so you should read the help file or man page on each function that you use.

    Back to the matter of ensuring that you declare char arrays to be big enough, consider this function call:
    strcpy(greet, "Hello");
    If you do a strlen("Hello"), the return value would be 5, because strlen does not count the null-terminator. But if you declare greet thus:
    char greet[5];
    then the result of that strcpy would be a buffer-overflow, such that the next byte after the greet array would be overwritten by the '\0'. This might pass unnoticed or it might cause the value clobbered by the null-terminator to mysteriously lose its value, causing unexpected results. Or if that location is part of the function's housekeeping information, which includes where to return to, then that buffer-overflow could result in your program crashing when it attempts to return from that function or when it uses a clobbered pointer which now points outside of your program's memory space.

    I'll specifically address gets below.

    Originally Posted by so.very.tired
    2. can i use it as an indicator? for example: ...
    The answer is "yes, most definitely." Though a lot of code that you find will make use of the fact that a zero value is false while a non-zero is true. Since a printable character is always non-zero and a null-terminator is always zero, your examples would more often show up as:
    Code:
    for (i=0; array[i]; i++)
    {
       code
     }
    and
    Code:
    while (array[i])
    {
       code
       i++;
    }
    And along those same lines, from off the top of my head, here is how a simple re-invention of strcpy would look:
    Code:
    char *StrCpy(char *dest, char *src)
    {
        char  *sp = src;
        char  *dp = dest;
        
        // as long as the source character is not null-terminator
        while (*sp)
            *dp++ = *sp++;
            
        // *sp was null-terminator, so terminate the dest string    
        *dp = '\0';
        
        // return dest string in case function called 
        //    in an expression
        return dest;    
    }
    Whenever you work with strings, always keep that null-terminator in mind and allow for it. It requires discipline, the rewards of which is avoiding horrible problems.

    Originally Posted by so.very.tired
    so that raise the question: what is the problem with gets(), really?
    even Eclipse is warning me from using it...

    because from what i've been reading, i understand that gets() does not limit the string length and therfore kinda dangerous to use.
    Yes, that is true. As I described briefly, the danger comes from buffer overflow. At best, it's a nuisance that will cause your program to crash easily. At worst, it's a gaping security hole that any script-kiddy could use to commandeer your computer. BTW, to my knowledge scanf has the same problem when it's used to read in a string (since I work mainly in embedded programming, I don't have much personal experience with scanf).

    Many C library functions come in related families. For example, scanf reads from the terminal, fscanf reads from a file, and sscanf reads from a string. Similarly, printf, fprintf, and sprintf deal with the terminal, a file, and a string, respectively. The functionality of the functions in each such grouping is the same, though there might be some slight differences.

    gets is the function that reads in an entire line of input from the terminal and fgets is its cousin that reads in an entire line of input from a file. Both copy that input to a char buffer that you specify and both, of course, terminate that string with a null-terminator. However, they have two differences:
    1. gets discards the newline character while fgets copies the newline character into the string.
    2. fgets specifies the maximum number of characters to be copied in, while gets does not.

    Because of that second difference, it is recommended to use fgets instead of gets. The standard files for the terminal are standard input (stdin), standard output (stdout), and standard error (stderr). The standard files are automatically opened when you start your program, so you do not need to do anything. You should substitute your gets calls with fgets(stdin) with a buffer size that takes into account your char array's size, the null-terminator, and the newline character.


    Also, one of our goals in writing a program is robustness. We don't want it to crash every time it encounters a problem. That is why we protect against dividing by zero or using an uninitialized pointer. We also want our program to be able to handle anything the user might enter without crashing; as one experienced forum member would frequently tell a new member, "With just a few keystrokes I can send your program running off to the weeds puking all over its own shoes." It is not a trivial task to make your program robust, but it is absolutely necessary when you program professionally. Avoiding gets in favor of fgets is good first step in the direction of making your program more robust.

IMN logo majestic logo threadwatch logo seochat tools logo