Thread: Discuss Valarrays - Was:Using Strings with Functions

  1. #1
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    >> char temp[newlen];
    >>This isn't even valid 'C' - you can't declare arrays with variable >>length. To do this, you would need to call malloc.
    >
    >Not true, I have used this convention hundreds of times!
    >Perhaps I have a "smart" compiler, Salem!

    You have a compiler that will compile non-ANSI standard code.
    This implementation is compiler dependant. Much like:

    fflush( stdin );

    Sure, some compilers let you do it. Some of them even have it
    work right. However, it is not ANSI compatible. (Actually, if I
    recall correctly, they're considering adding it to the standard.)
    However, it is _not_ in the standard. As such, your code is not
    portable.

    Quzah.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Not true, I have used this convention hundreds of times! Perhaps I have a "smart" compiler,
    You have a compiler like this perhaps?
    http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_5.html#SEC80

    The ability to do something does not make it part of the standard - it's fflush(stdin) all over again.

    > If the string is 80 in length, that means 79 chars and a '\0' right?
    Yes.

    > So if fgets is recieving input from a user who enters 99 chars, it gets 80 of those and no room for the null terminator, right?
    No.

    To quote the manual
    -----
    fgets() reads in at most one less than size characters from stream and
    stores them into the buffer pointed to by s. Reading stops after an EOF
    or a newline. If a newline is read, it is stored into the buffer. A '\0'
    is stored after the last character in the buffer.
    -----
    The most chars you will ever get with fgets is n-1. It may be less, if a newline was found early on, but it will never be more.
    If there is no \n in the buffer fgets returns, then it means that a long line had been detected, and you must call fgets again to get the rest of the line (or the next part of the line at least).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User pinko_liberal's Avatar
    Join Date
    Oct 2001
    Posts
    284
    Originally posted by quzah
    >> char temp[newlen];
    >>This isn't even valid 'C' - you can't declare arrays with variable >>length. To do this, you would need to call malloc.
    >
    >Not true, I have used this convention hundreds of times!
    >Perhaps I have a "smart" compiler, Salem!

    You have a compiler that will compile non-ANSI standard code.
    This implementation is compiler dependant. Much like:

    fflush( stdin );

    Sure, some compilers let you do it. Some of them even have it
    work right. However, it is not ANSI compatible. (Actually, if I
    recall correctly, they're considering adding it to the standard.)
    However, it is _not_ in the standard. As such, your code is not
    portable.

    Quzah.

    Sorry , variable length arrays are permissable in C99 , they are known as valarrays , a sad consequence of this fact is that for a valarray a sizeof(a) may not be a compile time constant .
    Among all compilers gcc and the complier from comeau computing seems to support C99 the most .http://www.comeaucomputing.com/features.html#vla

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    > Sorry , variable length arrays are permissable in C99 , they are
    > known as valarrays , a sad consequence of this fact is that for
    > a valarray a sizeof(a) may not be a compile time constant .
    >
    > Among all compilers gcc and the complier from comeau
    > computing seems to support C99 the
    > most .http://www.comeaucomputing.com/features.html#vla

    Hmm... It was my understanding that C99 was jut a proposal
    and not a final addition. I seem to stand corrected.

    One down side to int array[b]; is the potential for negative
    sized arrays, which will generate runtime errors.

    I've personally used them before using GCC a year or so ago,
    but was told they were not ANSI and I honestly haven't paid
    attention to them since.

    Quzah.

  5. #5
    Unregistered
    Guest

    Exclamation

    That "variable length arrays" are non-standard is quite sad, and frankly an embarassing aspect that the creators of C decided to implement!

    For one, let us consider the actual creation of a string. If a variable is used, it is probably carefully selected as to not be changing values frequently, if at all, during program execution, and thus the "danger" of it changing into an unsafe value is unlikely if the programmer is careful to 1) initialize it 2) test it to be greater than say zero 3) otherwise use the variable for the specific task at hand- to determine the needed size!

    In fact, I see little use in the standard specification except to defang functional programming!

    >One down side to int array[b]; is the potential for negative
    >sized arrays, which will generate runtime errors.
    >I've personally used them before using GCC a year or so ago,
    >but was told they were not ANSI and I honestly haven't paid
    >attention to them since.

    The potential for any undesired value is always a concern of the programmer. Again, let him/her be the implementor of a "safe" system for utilizing this invaluable resource!

    How sad that you see no value in the variable-initialized array! Perhaps the only good argument to that is that it is better programming style to utilize dynamic allocation- or is it? Salem, even you stated to the affect that "free"ing a variable rarely means returning it directly to the operating system anyway! So that plus the fact that a variable passing out of scope is indeed no longer there only leads one to believe that the actual benifit- indeed neccesity- of dynamic allocation is 1) to promote better practices 2) to provide a means for the system to reclaim large chunks of memory if/when it so chooses to do so. Other than that,
    I propose that since most large chunks of memory are created from within functions and "soon" pass out of scope, the simplicity of non-dynamic allocation seems obvious.

    DJH-- One last thing. You might consider calling "strcpy" from WITHIN the function(though of course you would have to pass string#2 as the second paremeter of the function). Otherwise you are saying: "This funtions main purpose is to transform a single string into it's non-spaced equivalent" which you stated you are not intending, but to return a second string instead. So leave it to the function to take care of this so that you don't have to bother with this step in the future.

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    ^ ^ ^
    | | |
    Sebastian
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > and thus the "danger" of it changing into an unsafe value is unlikely if the programmer is careful to
    When was the last time you tried to dereference an uninitialised pointer?
    Programmers simply are not that careful.

    > How sad that you see no value in the variable-initialized array!
    Well I didn't consider the language broken without them.

    Apart from saving a call to free(), I see nothing advantageous in using these arrays compared to calling malloc.

    I do see a number of problems though.

    > Salem, even you stated to the affect that "free"ing a variable rarely means returning it directly to the operating system anyway!
    This is true - and guess what, it applies to the stack as well. Stacks are allocated/extended by the OS in big chunks as well - can you imagine how expensive a function call would be if the current stack frame was allocated and released (to the OS) for each function call?

    Simply putting the array on the stack doesn't change anything - its all the same memory to the OS, and if its not allocated to one, it will be allocated to the other.

    But it's worse than that - some implementations have a restricted stack size (much more than the heap say), so where
    &nbsp; int *arr = malloc( n * sizeof(int) );
    should always work
    &nbsp; int arr[n];
    might not work in all implementations.

    Since you can check the malloc call for failure (arr==NULL), how would you check the dynamic array for failure? At least with malloc, you can warn the user and back out - all you've got here is crash and burn.

    What's more, return arr; is valid if you call malloc, and invalid for a valarray (as it would be for a normal array).

    The normal way for making the return of an array valid is to make the array static
    &nbsp; static int arr[10]; ... return arr;
    But if its a valarray, you can't do this.

    Of course, both you and I are assuming that such arrays are created on the stack in the first place. For all I know, an implementation could just choose to wrap such arrays up in a malloc/free call.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    First off let me say that you have more real-life experience in software than I do for sure, so perhaps my approach is part laziness, part aesthetics ( who can argue that malloc is pretty?! ) and part indignance at the whole OS matter! If tommorrow you said "Sebastian, from now on, the OS will reclaim that memory as soon as it is freed" I'd immediately change my stand on the issue!

    But now that I think about it, your right. It's not enough to just verify that the variable != 0, since what we're wanting is to know if we have enough memory to create a new string, new array of structs, etc.

    I was looking at the problem from the angle of verifying the multiplyer variable( say len) while ignoring the memory!

    Anyway, I think I have destroyed my argument quite enough for the day, so I'll just step down from the pulpit (with my non-standard compiler in tow...).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I have to agree with Salem on this one. I have yet to find a place where it required a sized array. Sure, it makes it tidy if you only allocate enough blocks based on user input, but again, that's what malloc is for. After all:
    Code:
    int *array;
    int x,y;
    scanf("%d",x);
    array = malloc( sizeof(int)*x );
    for( y = 0; y<x; y++ )
    {
       printf("Enter a value for array[%y]: ");
       scanf("%d", &y[x] );
    }
    Now I've just done the same thing. Additionally, I have more
    flexability than you do:
    Code:
    printf("Enter a new value for x: ");
    scanf("%d",&x;
    free( array );
    array = malloc( sizeof(int)*x );
    Can you do that with a variable length array? Can you change its size once it is declared? I don't believe you can, though I could be wrong. (I don't think I'm wrong, but it's possible, after all, I've never needed such an arrray.)

    Quzah.
    [/code]

  10. #10
    Registered User pinko_liberal's Avatar
    Join Date
    Oct 2001
    Posts
    284

    Question

    I also do not see any need for it , I wonder they chose to it.
    What do you guys think about the support for complex numbers and macros with variable number of arguments ?

  11. #11
    Registered User
    Join Date
    Sep 2001
    Posts
    412
    Heck, *I* want to see matrices and vectors as primitive types, especially because many CPUs can now use optimized math routines for operations on matrices -- but if your matrix is implemented with integer math, you can't use the optimizations at all.

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Here's an example of how I use a "val-array" ( in psuedo code)


    void some_useful_function( )
    {

    do{

    //open a file

    //count the records, "num" is our variable

    person buddies[ num ]; //person is a struct type

    //read records into the array of structs

    //close file

    printf("What do you want to do? 1) Find someone 2) Change someones data 3) Delete someone");

    //get input

    switch(input)
    {
    case 1: find_function( buddies );
    break;
    case 2: edit_function( &buddies);
    break;
    case 3: delete_function( buddies );
    }

    printf("Do it again?);

    // get input

    }while( //user wants another go);

    }





    Then, in the delete function, it simply opens the file in the "write" mode and puts all records except for the one you don't want anymore. After Exiting this function, The user get's a " Do this again?" prompt. If yes, the array passes out of scope as the loop starts over and guess what? The array has shrunk by one!(of course). You can easily keep going till there are none left! So yes, in a nutshell, simply by utilizing the scope of the variable( since it is created in the loop) and a little IO, you have a reliable variable sizing routine.


    Incidentally, since there is little value for an array that is sized by the user, let me add that modifying the above routine, you can easily write one that takes in a string of numbers, and each time just feeding each one as a single variable into a file! Then when the user is done, the loop is exited, the file is closed, then reopened for reading, and voila!, a perfectly sized array is instantiated which can 1) find the total 2) find the average 3) apply calculations 4) count duplicates in the array, etc, and deliver that directly to the user in a seemless way, the bonus being that, looking at the code, there are no messy complications to be seen! In fact, unless you study the code, you might not even notice what you were staring at!

    Unconventional, yes, but elegant.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #13
    Registered User
    Join Date
    Sep 2001
    Posts
    412
    Well, the thing about this is:

    1) Variable sized arrays have ALWAYS been possible, just only as heap variables, not stack.

    2) Do you really want to add a large amount of data on the stack? Memory allocation for large structures is allocated from the heap for a reason.

    As I see it, this new "feature" really adds little practical benefit, and has many potential pitfalls.

  14. #14
    Registered User pinko_liberal's Avatar
    Join Date
    Oct 2001
    Posts
    284
    If the purpose is just saving calls to malloc and free , I am not excited , are there situations where they may lead to more efficienct code .

  15. #15
    Unregistered
    Guest
    Well here's a working example:



    Code:
    int main()
    {
    
    
    
    
    char choice[15];
    
    int num = 0;
    
    FILE *fp;
    
    char *file = "Data.dat";
    
    
    do{
    
    
    
    fp = opens(file,"wb","The File For Creation",1);
    
    fclose(fp);
    
    fp = opens(file,"ab+","The File For Appending",1);
    
    clrscr();
    
    carr(7);
    
    printf("Please Enter The First Number \nOf An Array Of Integers (\"Q\" Exits ) :    \n\n");
    fgets(choice,15,stdin);
    
    
    do{
    
    
    
    num = atoi(choice);
    
    fwrite(&num,sizeof(int),1,fp);
    
    num = 0;
    
    clrscr();
    
    carr(7);
    
    printf("Input The Next Integer (\"Enter\" To Total ) :    \n\n\n");
    
    fgets(choice,22,stdin);
    
    
    
    
    }while(atoi(choice));
    
    
    
    
    int num = ftell(fp) / sizeof(int);
    
    rewind(fp);
    
    int array[num];
    
    int i, total = 0, hi = 0, lo = 0, flag = 0;
    
    for(i=0; i<num; i++)
     {
      fread(&array[i],sizeof(int), num ,fp);
      total += array[i];
      if(flag == 0){ lo = array[i];}
      if(array[i] < lo){lo=array[i];}
      if(array[i] > hi){hi=array[i];}
      printf("Array[%i]: %i \n",i+1, array[i]);
      getch();
      flag++;
     }
    
    fclose(fp);
    
    int avg = total / num ;
    
    printf("Number of integers in array: %i .\n\n", num);
    printf("  Total: %5i.        Average: %5i \n\n",total,avg);
    printf("Highest: %5i.         Lowest: %5i \n",hi,lo);
    getch();
    
    
    clrscr();
    
    carr(7);
    
    printf("Do Another? (\"Q\" Exits)  :  \n\n");
    fgets(choice,15,stdin);
    
    }while(!strstr(choice,"Q") && !strstr(choice,"q"));
    
    
    
    
    return 0;
    
    }
    In my view, there are times when it is better to malloc and times when the simplicity of exploiting the natural virtues of a language (in this case, scope) is better.

    If nothing else, it is a good example of simplifying a simple program!

    Had this been a large, complex problem, malloc ( and probably linked-lists) would probably have been more suitable, I suppose.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. damn strings
    By jmzl666 in forum C Programming
    Replies: 10
    Last Post: 06-24-2002, 02:09 AM
  2. menus and strings
    By garycastillo in forum C Programming
    Replies: 3
    Last Post: 04-29-2002, 11:23 AM
  3. Passing & Returning Strings from Functions
    By nisaacs in forum C Programming
    Replies: 1
    Last Post: 01-30-2002, 05:34 AM
  4. Class accessor functions returning strings?
    By Shadow12345 in forum C++ Programming
    Replies: 6
    Last Post: 12-31-2001, 12:48 PM
  5. Using Strings with Functions
    By DJH in forum C Programming
    Replies: 10
    Last Post: 10-19-2001, 04:40 PM