LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-22-2023, 06:07 PM   #1
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Rep: Reputation: 4
Why infinite loop for input elements, bigger than single digit.


In the below code, want to display the elements in an array, in a format that there are two rows, and the first row is the element index; while the second row has the actual element. But, the second row elements are spaced by their size.

Issue arises of infinite loop, if the array elements are more than single digit big.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    int *intvals = NULL; //array of integers
    int **vals= NULL;//array of pointers
    int total_elements;

    if (isatty(fileno(stdin))) {
        printf("How many elements in the array: ");
    }
    scanf("%d", &total_elements);

    intvals = malloc(total_elements*sizeof(int));
    vals = malloc(total_elements*sizeof(int *));
    for(int i= 0; i<total_elements; ++i) {
        vals[i]= &intvals[i];
        scanf("%d", vals[i]);
    }
    for (int i=0; i<total_elements; ++i)
                    printf(" %d ", i); 
    printf("\n");
    for (int i=0, j=0, no_of_spaces=0; i<total_elements; ++i){
                //printf("%d:", i);
                while((*(int *) vals[i])/10 >0) no_of_spaces++; 
                //printf("for %d, number of spaces : %d", *(int *) vals[i], no_of_spaces);
                while(no_of_spaces)
                {
                       printf(" "); 
                       no_of_spaces--;
                }
                printf("%d", *(int *)vals[i]);
    }
}
 
Old 07-22-2023, 07:34 PM   #2
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,226

Rep: Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320
You should gdb it both as-is and with hardcoded values.

Last edited by dugan; 07-22-2023 at 07:48 PM.
 
Old 07-22-2023, 08:44 PM   #3
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,266
Blog Entries: 24

Rep: Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195
Why an infinite loop? Because you have written an infinite loop of this form:

Code:
while( int_value>=10 )
    do something;
Why only when the value is >=10? Fairly obvious.
 
Old 07-23-2023, 12:17 AM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Sample:
Code:
static int decimal_digits(long n, char *buff) {
    int ndig= 0;
    char *p;
    char sign= 0;
    unsigned long ntmp;

    p= buff;
    if (n>=0) {
        ntmp= n;
    } else {
        ntmp= (ULONG_MAX - (unsigned long)n) + 1;
        ndig += 1; /* only if you count '-' as a digit */
        sign= '-';
    }

    do {
        ndig += 1;
        *p++ = '0' + ntmp%10;
        ntmp /= 10;
    } while (ntmp!=0);
    if (sign) *p++ = sign;
    *p= '\0';
    strrev (buff);
    return ndig;
}
This version not only counts the decimal digits, but also stores them into 'buff'. (Negative numbers are a bit problematic, make sure to test your code with -1 as well as LONG_MIN.)

Last edited by NevemTeve; 07-23-2023 at 06:34 AM.
 
Old 07-23-2023, 09:53 AM   #5
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by astrogeek View Post
Why an infinite loop? Because you have written an infinite loop of this form:

Code:
while( int_value>=10 )
    do something;
Why only when the value is >=10? Fairly obvious.
Unable to understand that why only first inputted string is printed, though (before some trivial changes to the code) earlier all elements were printed.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    int *intvals = NULL; //array of integers
    int **vals= NULL;//array of pointers
    int total_elements;
    int spacing[total_elements];
    
    if (isatty(fileno(stdin))) printf("How many elements in the array: "); 
    scanf("%d", &total_elements);
    intvals = malloc(total_elements*sizeof(int));
    vals = malloc(total_elements*sizeof(int *));
    for(int i= 0; i<total_elements; ++i) {
        vals[i]= &intvals[i];
        scanf("%d", vals[i]);
    }
    for (int i=0, j=0, no_of_spaces=0; i<total_elements; i++, no_of_spaces=0){
                j = *(int *) vals[i];
                while(j) { no_of_spaces++; j = j/10; }
                spacing[i]= no_of_spaces-1;
   }
    for (int i=0; i<total_elements; printf(" %d ", i), i++ )  
               for (int j =0; j<spacing[i]; j++) 
                        printf(" ");  
    printf("\n");
    for (int i=0; i<total_elements; ++i)  printf(" %d ", *(int *) vals[i]);
}
The output is:
Code:
How many elements in the array: 3
1235
123
12
    0 
 1235

Last edited by ajiten; 07-23-2023 at 09:56 AM.
 
Old 07-23-2023, 09:57 AM   #6
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
Sample:
Code:
static int decimal_digits(long n, char *buff) {
    int ndig= 0;
    char *p;
    char sign= 0;
    unsigned long ntmp;

    p= buff;
    if (n>=0) {
        ntmp= n;
    } else {
        ntmp= (ULONG_MAX - (unsigned long)n) + 1;
        ndig += 1; /* only if you count '-' as a digit */
        sign= '-';
    }

    do {
        ndig += 1;
        *p++ = '0' + ntmp%10;
        ntmp /= 10;
    } while (ntmp!=0);
    if (sign) *p++ = sign;
    *p= '\0';
    strrev (buff);
    return ndig;
}
This version not only counts the decimal digits, but also stores them into 'buff'. (Negative numbers are a bit problematic, make sure to test your code with -1 as well as LONG_MIN.)
Please elaborate your code a bit more, else it would take much more time.
 
Old 07-23-2023, 10:14 AM   #7
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
I suppose you want to count the number of decimal digits. The core of it is simply:
Code:
int ndig= 0;
do {
    ++ndig;
    num /= 10;
} while (num!=0);
 
Old 07-23-2023, 10:41 AM   #8
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
I suppose you want to count the number of decimal digits. The core of it is simply:
Code:
int ndig= 0;
do {
    ++ndig;
    num /= 10;
} while (num!=0);
Please tell the purpose of your code line:
Code:
*p++ = '0' + ntmp%10;
My code intends for display purposes (will use a separate function, to be called whenever needed), a row of index, and the second row of array contents.
This would be used in conjunction with your earlier provided (& slightly embellished, by me) quicksort program, to display the first row of index, with spacing as prefix, so as to properly align with the second row, which is showing the contents.
This would be used to display the contents after each iteration.

Last edited by ajiten; 07-23-2023 at 10:42 AM.
 
Old 07-23-2023, 11:16 AM   #9
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
That bit is not needed for digit-counting, it stores a '0'..'9' character into the buffer depending on the last decimal digit of the number.
Back to the formatting, you should check the 'width' part in 'printf(3)' manual, eg.
Code:
printf("[%16d]", number);
 
Old 07-23-2023, 02:20 PM   #10
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,266
Blog Entries: 24

Rep: Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195
Quote:
Originally Posted by ajiten View Post
Unable to understand that why only first inputted string is printed, though (before some trivial changes to the code) earlier all elements were printed.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    int *intvals = NULL; //array of integers
    int **vals= NULL;//array of pointers
    int total_elements;
    int spacing[total_elements];
    
    if (isatty(fileno(stdin))) printf("How many elements in the array: "); 
    scanf("%d", &total_elements);
    intvals = malloc(total_elements*sizeof(int));
    vals = malloc(total_elements*sizeof(int *));
    for(int i= 0; i<total_elements; ++i) {
        vals[i]= &intvals[i];
        scanf("%d", vals[i]);
    }
    for (int i=0, j=0, no_of_spaces=0; i<total_elements; i++, no_of_spaces=0){
                j = *(int *) vals[i];
                while(j) { no_of_spaces++; j = j/10; }
                spacing[i]= no_of_spaces-1;
   }
    for (int i=0; i<total_elements; printf(" %d ", i), i++ )  
               for (int j =0; j<spacing[i]; j++) 
                        printf(" ");  
    printf("\n");
    for (int i=0; i<total_elements; ++i)  printf(" %d ", *(int *) vals[i]);
}
The output is:
Code:
How many elements in the array: 3
1235
123
12
    0 
 1235
You need to compile with -Wall... again. You are using at least one uninitialized value which I have hilighted, so there is little point looking further until that is fixed.

No code change is so trivial that it does not need to be tested.

It seems to me that you tend to see only the overall program context, such as the original code and question, "Why infinite loop for input elements, bigger than single digit?", but do not expend much effort to look at the individual pieces inside (i.e. the actual loop code which is obviously incorrect).

I would suggest that you not try to write the whole program up front, then try to debug it.

Instead, think of each little function separately, write the code for each and test it in isolation so that you know what it must do and whether or not it does the desired thing correctly. Then put those pieces together into a more complete program.

For example, you want to print formatted output with aligned columns, so try to write a simplest function or code block to perform that specific task using fixed or constant data for testing. When you understand it and it works as desired, move on to the data input code using the same approach. When each piece is understood and working, put them together into an application.
 
Old 07-24-2023, 01:22 AM   #11
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by astrogeek View Post
You need to compile with -Wall... again. You are using at least one uninitialized value which I have hilighted, so there is little point looking further until that is fixed.

No code change is so trivial that it does not need to be tested.

It seems to me that you tend to see only the overall program context, such as the original code and question, "Why infinite loop for input elements, bigger than single digit?", but do not expend much effort to look at the individual pieces inside (i.e. the actual loop code which is obviously incorrect).

I would suggest that you not try to write the whole program up front, then try to debug it.

Instead, think of each little function separately, write the code for each and test it in isolation so that you know what it must do and whether or not it does the desired thing correctly. Then put those pieces together into a more complete program.

For example, you want to print formatted output with aligned columns, so try to write a simplest function or code block to perform that specific task using fixed or constant data for testing. When you understand it and it works as desired, move on to the data input code using the same approach. When each piece is understood and working, put them together into an application.
Thanks, but had no idea that only the first element of the array (i.e., spacing) would be picked up; if not specified the dimension of the array. Seems due to one pass compilation, C-language has this constraint. But, wouldn't there be garbage value for the variable: total_elements, rather than just containing the value = 1, each time the code is compiled & run (or might be it is specific to the www.onlinegdb.com compiler only); or is it that if the static array's dimension is un-specified, then only the first element is taken? Confused about that part.

Also, if the last line of the code below is changed to the one shown below, then the array contents are not displayed. The ordering of the two statements (i.e., '++i', & 'printf(" %d ", *(int *) vals[i])') in the 3rd part of the for-loop is important, but unclear as why that matters?:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    int *intvals = NULL; //array of integers
    int **vals= NULL;//array of pointers
    int total_elements;
    //int spacing[total_elements];
    
    if (isatty(fileno(stdin))) printf("How many elements in the array: "); 
    scanf("%d", &total_elements);
    int spacing[total_elements];
    intvals = malloc(total_elements*sizeof(int));
    vals = malloc(total_elements*sizeof(int *));
    for(int i= 0; i<total_elements; ++i) {
        vals[i]= &intvals[i];
        scanf("%d", vals[i]);
    }
    for (int i=0, j=0, no_of_spaces=0; i<total_elements; i++, no_of_spaces=0){
                j = *(int *) vals[i];
                while(j) { no_of_spaces++; j = j/10; }
                spacing[i]= no_of_spaces-1;
   }
    for (int i=0; i<total_elements; printf(" %d ", i), i++ )  
               for (int j =0; j<spacing[i]; j++) 
                        printf(" ");  
    printf("\n");
    for (int i=0; i<total_elements; ++i, printf(" %d ", *(int *) vals[i]))  ; //the array contents are not printed out, but if the statement is changed to: 
                                                                              //for (int i=0; i<total_elements; ++i, printf(" %d ", *(int *) vals[i])); then correct (expected) 
                                                                              //output is obtained.
}

Last edited by ajiten; 07-24-2023 at 01:27 AM.
 
Old 07-24-2023, 02:25 AM   #12
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Be careful when making random changes in the code.
Code:
- for (int i=0; i<total_elements; ++i, printf(" %d ", *(int *) vals[i]));
+ for (int i=0; i<total_elements; ++i) printf(" %d ", *(int *) vals[i]);
 
Old 07-24-2023, 06:13 AM   #13
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
Be careful when making random changes in the code.
Code:
- for (int i=0; i<total_elements; ++i, printf(" %d ", *(int *) vals[i]));
+ for (int i=0; i<total_elements; ++i) printf(" %d ", *(int *) vals[i]);
But, if have to print in each iteration of the for-loop, what is the error in including the printf() inside the 3rd part of the for loop?
If that is clear, then would understand.
 
Old 07-24-2023, 06:44 AM   #14
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,863

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
this is to understand the comma operator: https://en.wikipedia.org/wiki/Comma_operator
Actually I think in this case:
Code:
for (int i=0; i<total_elements; ++i, printf(" %d ", *(int *) vals[i]));
that printf is not invoked at all, because the comma operator cannot invoke functions, just evaluate expressions.
https://stackoverflow.com/questions/...comma-operator
 
Old 07-24-2023, 07:59 AM   #15
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Quote:
Originally Posted by ajiten View Post
But, if have to print in each iteration of the for-loop, what is the error in including the printf() inside the 3rd part of the for loop?
If that is clear, then would understand.
That's possible if unusual. But you have to listen to the order of the bits:
Code:
-    for (int i=0; i<total_elements; ++i, printf(" %d ", *(int *) vals[i]));
+    for (int i=0; i<total_elements; printf(" %d ", *(int *) vals[i]), ++i);
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: 'This was bigger than GNOME and bigger than just this case.' GNOME Foundation exec director talks patent trolls and much, much more LXer Syndicated Linux News 0 10-24-2020 04:21 AM
[SOLVED] Read digit by digit in variable pedropt Programming 6 12-25-2017 04:24 AM
In Javascript How to replace elements in one object with elements from another object pizzipie Linux - Software 1 05-08-2014 02:28 AM
[SOLVED] infinite loop that isnt infinite? frieza Programming 2 10-27-2010 02:16 PM
Substitue single-digit, two-digit, and 3-digit numbers with text using sed dmason165 Programming 13 08-07-2009 10:38 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:07 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration