Thread: This runs..but why not this. Help me to understand, please

  1. #16
    Registered User
    Join Date
    Jul 2008
    Posts
    8
    valaris : thanks, but your suggestions didn't work for me.

    i don't know how to make this damn thing run using a pointer to a pointer, so i'm just gonna stick with returning the pointer at the end of the function (this now makes alot of sense to me).
    I've also updated a few coding faux pas (except 2):

    some serious
    Code:
    integers = malloc(*num1 * sizeof(int));  to  integers = malloc((*num1 + 1) * sizeof(int));
    Code:
    int   *integers = 0; // undefined behavior bad
    int   num1 = 0;
    some not so serious
    Code:
    main() to int main(void)
    Code:
    return 0;
    Code:
    int *allocate_memory(int *integers, int *num1); // not just the prototypes
    int average_of(int *integers, int *num1);
    int print_average(int *integers, int *num1);
    some just plain stupid (in an attempt to understand)
    Code:
     integers = ptr;
    But.....

    1)fflush(stdin) must stay, because the getchar() doesn't work if its not there...see for yourself, it doesn't wait for a character return.
    matsp: fflush(stdout) does not make sense to me. It flushes the standard output, after those scanfs i have to flush the standard input to do a getchar().

    2)Between copying a value in to a function (int num1) vs copying a pointer to a value in to a function (int *num1). I don't know whether one or the other is more efficient, or if they are equal. I know i'm not changing the value of num1 (except in the allocate_memory function), but do i really need to change all of the other int *num1's to int num1's... ?

    heres my code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int *allocate_memory(int *integers, int *num1);
    int average_of(int *integers, int *num1);
    int print_average(int *integers, int *num1);
    
    
    int *allocate_memory(int *integers, int *num1)
    {
    
                
        printf("How many numbers do you want to average: ");
        scanf("%d", num1);
        
        integers = malloc((*num1 + 1) * sizeof(int));
        
        if(integers == NULL)
          {
             printf("malloc has failed\n");
             exit(1);
          }
        
        return integers;
    }
    
    
    int average_of(int *integers, int *num1)
    {
       int    i;
    
       integers[*num1] = 0;
    
       for(i = 0; i < *num1; i++)
          {
             printf("#%d Please enter a number: ", i + 1);
             scanf("%d", &integers[i]);
             integers[*num1] += integers[i];
          }
       integers[*num1] /= *num1;
    }
    
    int print_average(int *integers, int *num1)
    {
       int    i;
       
       printf("The average of ");
       
       for(i = 0; i < *num1; i++)
          printf("%d ", integers[i]);
          
       printf("is : %d\n", integers[*num1]);
    }
    
    int main(void)
    {
       int   *integers = 0;
       int   num1 = 0;
        
       
      
       integers = allocate_memory(integers, &num1);
       average_of(integers, &num1);
       print_average(integers, &num1);
       
       free(integers);
       
       fflush(stdin);
       getchar();
       
       return 0;
    }
    Thanks again, to everyone who has posted so far.

  2. #17
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by polymatrix View Post
    But.....

    1)fflush(stdin) must stay, because the getchar() doesn't work if its not there...see for yourself, it doesn't wait for a character return.
    There is no "see for yourself" with undefined behavior. matsp can stick it in his code and it may crash the program, or it may delete the file, or it may start playing minesweeper on his computer. The idea of something being "undefined" means that the C standard allows anything to happen, which means your compiler and system may work the way you intended (ie. discard chars you don't want), but other compilers and systems may do something not-so-nice and unexpected (ie. crash or even mutilate or lose valid input). Either way, no matter what it does, the C standard says it's ok because calling fflush() on an input stream is not defined.

  3. #18
    Registered User
    Join Date
    Jul 2008
    Posts
    8
    Thanks Macgyver. What should i use to flush the standard input?

  4. #19
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    And how to solve it is in the FAQ How do I ... (Level 2):
    http://faq.cprogramming.com/cgi-bin/...&id=1043284392

    --
    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.

  5. #20
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by tabstop View Post
    You can change what is pointed to by a function parameter, but you can never change the thing itself. So in your example, integers was a pointer to some integers -- those integers could be changed, because they were pointed to, but the value of integers itself could not be changed -- integers could not be set to point to a new bunch of integers.

    Edit: That's a really confusing name, so maybe the typeface will help.
    of course you could always pass a pointer to the pointer as so -

    Code:
    void foo(int** integers , int num){
       *integers = (int*)malloc(num * sizeof(int));
       
       return;
       }
     
    void main(void){ // love you sweety
       
       int* integers;
       int num = 5;
     
       printf("integers* = &#37;d\n" , integers);
     
       foo(&integers , num);
     
       // integers now points to an array of integers
       printf("integers* = %d\n" , integers);
     
       return;
       }

  6. #21
    Registered User
    Join Date
    Jul 2008
    Posts
    8
    This is weird to me...but its pretty cool. I was not familiar with the ** operator.
    So, ** essentially means: a pointer to a pointer? Valaris, your previous post makes more sense to me now. You gave me the answer, thank you.

    Abachler: thanks... your code helped me see what i was doing wrong. I wasn't calling allocate_memory(&integers, &num1)... i was calling ( integers, &num1). I thought &integers would be redundant syntax (the address of the address of integers), its not. I'm kinda sorta starting to get it. **integers is a pointer to *integers address, so in the function the address of *integers is alterable...right?

    Macgyver and matsp: I only hope, one day i'll understand the language like you too do. From what i can gather the new version of fflush(stdin) is:

    Code:
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF);
    1)This creates an int variable called ch
    2)executes an infinite do nothing while loop if the condition ((ch = getchar()) != '\n' && ch != EOF); is met.
    3)((ch = getchar()) != '\n' && ch != EOF) means ch equals the return value of getchar . if this is not equal to a newline character and ch is not equal to EOF do nothing and evaluate the condition again.

    Is this right? because i don't get it.
    It works though.... just replaced fflush(stdin) with
    while ((ch = getchar()) != '\n' && ch != EOF); and it does the same thing.
    for me though, its more undefined than fflush(stdin) is to the compiler. I would really appreciate an explanation .

    here's my new code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int allocate_memory(int **integers, int *num1);
    int average_of(int *integers, int *num1);
    int print_average(int *integers, int *num1);
    
    
    int allocate_memory(int **integers, int *num1)
    {
    
                
        printf("How many numbers do you want to average: ");
        scanf("%d", num1);
        
        *integers = malloc((*num1 + 1) * sizeof(int));
        
        if(integers == NULL)
          {
             printf("malloc has failed\n");
             exit(1);
          }
        
    }
    
    
    int average_of(int *integers, int *num1)
    {
       int    i;
    
       integers[*num1] = 0;
    
       for(i = 0; i < *num1; i++)
          {
             printf("#%d Please enter a number: ", i + 1);
             scanf("%d", &integers[i]);
             integers[*num1] += integers[i];
          }
       integers[*num1] /= *num1;
    }
    
    int print_average(int *integers, int *num1)
    {
       int    i;
       
       printf("The average of ");
       
       for(i = 0; i < *num1; i++)
          printf("%d ", integers[i]);
          
       printf("is : %d\n", integers[*num1]);
    }
    
    int main(void)
    {
       int   *integers = 0;
       int   num1 = 0;
       int   ch; 
       
      
       allocate_memory(&integers, &num1);
       average_of(integers, &num1);
       print_average(integers, &num1);
       
       free(integers);
       
       while ((ch = getchar()) != '\n' && ch != EOF);
       getchar();
       
       return 0;
    }
    Is this better?
    Is this standard C?
    Thanks everybody.

  7. #22
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Definitely better.
    Is it standard - well, "gcc -Wall -ansi -pedantic -O2" gives no errors/warnings indicating non-standardness, so that's a good sign. You do have some warnings, but that's commented on below.

    Your understanding of the "remove input" (or fflush(stdin)) is correct - it reads one character at a time until it reaches either newline or end of file.

    In allocate_memory(): Whilst this line is syntactically correct, it is not what you want:
    Code:
        if(integers == NULL)
    You want to check if the value returned from malloc is NULL, not if the pointer you passed in from main is NULL, so check *integers [although, if you want to be really pedantic, yes, you should check that TOO - but that should be done BEFORE the call to malloc, and if we are that pedantic, you should also check if num1 is NULL].

    In average_of(): You do not need to pass num1 as a pointer. Same with print_average().

    I personally would not use the last element of the array to store the average, but instead return a value from the average_of function, and pass that value to the print_average() function.

    All of your functions have an integer return type, but besides main, all functions have no return statement. You may want to make those functions have a void return type.

    --
    Mats
    Last edited by matsp; 07-22-2008 at 02:18 AM.
    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

Similar Threads

  1. funcion runs 14 times, then program crashes
    By happyclown in forum C Programming
    Replies: 9
    Last Post: 03-03-2009, 11:58 PM
  2. prog runs on 64bit - seg faults on 32bit
    By hollie in forum C Programming
    Replies: 13
    Last Post: 12-08-2006, 01:59 AM
  3. windows installer for psp runs for vs6
    By iain in forum Tech Board
    Replies: 1
    Last Post: 06-27-2004, 09:21 AM
  4. Replies: 6
    Last Post: 10-24-2002, 08:58 AM
  5. Runs fine in IDE but crashes normally!
    By Hunter2 in forum Windows Programming
    Replies: 5
    Last Post: 05-07-2002, 03:47 PM

Tags for this Thread