Thread: how to count integers in string? "1" = 1 int "17" = 1 int "1a7" = 0 int ?

  1. #1
    cnoob()
    Join Date
    Mar 2015
    Posts
    28

    Question how to count integers in string? "1" = 1 int "17" = 1 int "1a7" = 0 int ?

    Trying to figure out how to read a string that's been input in a scanf (using iteration to deal with spaces) and use isdigit to count the number of digits in the string.

    One of the problems I'm running up against is that the rules for what is to be considered an integer is as follows.

    1 (singe digit surrounded by spaces) will be considered 1 integer
    127 (multiple digits surrounded by spaces) will be considered 1 integer
    1a89 (anything alphanumeric) will not be considered an integer

    whenever I use isdigit to point to a particular place it of course only looks at a single character in the array. How would I have it look at "blocks" of information instead?

    thanks for any help or education

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I would suggest a state machine and a loop to do the task.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    cnoob()
    Join Date
    Mar 2015
    Posts
    28
    Quote Originally Posted by stahta01 View Post
    I would suggest a state machine and a loop to do the task.

    Tim S.
    thank you I'll do some research on state machines

  4. #4
    Registered User
    Join Date
    Apr 2015
    Location
    Perth Western Australia
    Posts
    2
    Is this what you are looking for?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    char * getstring(char *string)
    {
     int index = 0;
     char ch;
     string = calloc(1 , sizeof(char));
     while ((ch = getchar()) != '\n')
     {
      string[index] = ch;
      index++;
      string = (char *) realloc(string, ((index + 1) * sizeof(char))); 
     }
     string[index] = '\0';
     return string;
    }
    
    
    int length(char *string)
    {
     int amount = 0;
     while (string[amount] != '\0')
     {
      amount++;
     }
     return amount;
    }
    
    
    int countnumbers(char *string)
    {
     int index, count = 0;
     for (index = 0; index < length(string) - 1; index++)
     {
      if (string[index] >  47 && string[index] < 58)
      {
       if (index > 0 && string[index - 1] > 47 && string[index - 1] < 58)
       {
        /*pass*/
       }
       else
       {
        count += 1;
       }
      }
     }
     return count;
    }
    
    
    int main()
    {
     char *string = NULL;
     int total;
     printf("\nInput a series of numbers with spaces and without then count the individual numbers such as \"1\" = 1 and \"17\" = 1\nEnter your number series now: ");
     string = getstring(string);
     total = countnumbers(string);
     printf("\nYou had %d individual numbers in your string.\n", total);
     free(string);
    }

  5. #5
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    You know, @wigglehead, the problems with giving someone an almost complete solution to their programming problem are more than one.

    For one, you don't know if the OP will be able to comprehend your code, since you don't know their knowledge level. Thus, you probably wasted your time, not to mention maybe confused the OP even more.

    Giving away code teaches them nothing, it won't make them better programmers or help them understand the problem.

    Lastly, you make everyone else look bad, like when the permissive grandpa gives the child more candy, although the parents object because they know what's best for them. The grandpa is seen as the good guy by the child, while the parents as bad ones.

    Get it?
    Devoted my life to programming...

  6. #6
    cnoob()
    Join Date
    Mar 2015
    Posts
    28
    Wigglehead: yea it definitely is and thank you for the time you put into your response. Though it does point out to me the glaring problem that I think the approach I'm trying to take is beyond the scope of my experience with C. HOWEVER, thanks for giving me something fun I can piece apart and make sense of, it'll definitely help my understanding. I found it very difficult to find complete code online and with a beginners knowledge of C having huge gaps in the code makes it really difficult to understand what's going on.
    PS: the code is solid except the return still gives the following

    Enter your number series now: 17 1 1b2 hello


    You had 4 individual numbers in your string.

    there should only be 2 numbers reported in that string for the project. Regardless... thank you for the help



    GReaper, right you are for the unscrupulous student however in this case though I won't use the code in the end I will certainly learn something by piecing it apart and seeing how he made it work. I certainly can see where you're coming from though.
    Last edited by SandyMan; 04-11-2015 at 10:36 PM.

  7. #7
    Registered User
    Join Date
    Apr 2015
    Location
    Perth Western Australia
    Posts
    2
    Hey

    @GReaper -- yep didn't realise this was a teaching forum.
    @SandyMan -- The code was a bit rough, but should keep you busy. If you want to become super good at C then a book called "C for Programmers" by Paul Deitel and Harvey Deitel would be awesome for your skills. It starts easy and covers lots of great stuff.

    Regards
    Wigglehead

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by wigglehead
    Is this what you are looking for?
    There are several problems with your code:
    • In the getstring function:
      • You declared string to be a parameter, but you neither use its value nor use it properly as an output parameter. It should either be a non-parameter local variable, or it should be a pointer to a pointer so as to function as an output parameter for a pointer.
      • You declared ch to be of type char, but you assigned the return value of getchar() to it. However, getchar() returns an int, therefore ch should be an int. This can matter when checking for EOF.
      • calloc can return a null pointer, so you should check for that before proceeding. Admittedly, this is not important here because you are only allocating space for a single char, but it is general good practice.
      • sizeof(char) is guaranteed to be 1, so should either omit it or write sizeof(string[0]) instead.
      • realloc can return a null pointer, so you should store its value into a separate char* variable, and then only assign to the variable named string after the check for a null pointer.
      • There is no need to cast the return value of realloc; you rightly did not cast the return value of calloc after all.
      • You incremented index and then realloc (index + 1) characters just before the next iteration. This presumably was to account for the null character, except that the increment already accounts for it on the last iteration, hence there will always be one extra element of the dynamic array left unused for no good reason.
      • That said, the algorithm to expand the string character by character is rather inefficient. It would be better to keep track of the capacity and expand it by some larger buffer size (in which case perhaps fgets could be used instead of getchar), or to keep track of the capacity and expand it by some factor (e.g., doubling it). (Which is better tends to depend on the current capacity and expected range of the size of the input.) Granted, in either case you could end up with more than one unused element, but at least there's a good reason
    • The length function appears to duplicate functionality already provided by strlen from <string.h>. If you really do want to define it instead of using strlen, its parameter should be a pointer const char.
    • In the countnumbers function:
      • The parameter should be a pointer to const char.
      • There is no need to call the length function repeatedly since the length presumably does not change: call it once and save the result in a variable.
      • You used the magic numbers: 47 and 58. It would be better to check against '0' and '9' instead (modifying the comparison to >= and <= respectively), or use isdigit as mentioned in post #1.
      • Instead of having an empty body with a "pass" comment, you could negate the condition then do away with the else branch.
    • Consider an indent level of more than a single space. Generally, people choose an indent level of between two to eight spaces, or a single tab. (My personal preference is four spaces, both as a compromise between stylistic extremes and because it was later reinforced by convention in a programming language I regularly use that happens to depend a great deal on indentation.)
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    cnoob()
    Join Date
    Mar 2015
    Posts
    28
    Quote Originally Posted by laserlight View Post
    There are several problems with your code:
    • In the getstring function:
      • You declared string to be a parameter, but you neither use its value nor use it properly as an output parameter. It should either be a non-parameter local variable, or it should be a pointer to a pointer so as to function as an output parameter for a pointer.
      • You declared ch to be of type char, but you assigned the return value of getchar() to it. However, getchar() returns an int, therefore ch should be an int. This can matter when checking for EOF.
      • calloc can return a null pointer, so you should check for that before proceeding. Admittedly, this is not important here because you are only allocating space for a single char, but it is general good practice.
      • sizeof(char) is guaranteed to be 1, so should either omit it or write sizeof(string[0]) instead.
      • realloc can return a null pointer, so you should store its value into a separate char* variable, and then only assign to the variable named string after the check for a null pointer.
      • There is no need to cast the return value of realloc; you rightly did not cast the return value of calloc after all.
      • You incremented index and then realloc (index + 1) characters just before the next iteration. This presumably was to account for the null character, except that the increment already accounts for it on the last iteration, hence there will always be one extra element of the dynamic array left unused for no good reason.
      • That said, the algorithm to expand the string character by character is rather inefficient. It would be better to keep track of the capacity and expand it by some larger buffer size (in which case perhaps fgets could be used instead of getchar), or to keep track of the capacity and expand it by some factor (e.g., doubling it). (Which is better tends to depend on the current capacity and expected range of the size of the input.) Granted, in either case you could end up with more than one unused element, but at least there's a good reason

    • The length function appears to duplicate functionality already provided by strlen from <string.h>. If you really do want to define it instead of using strlen, its parameter should be a pointer const char.
    • In the countnumbers function:
      • The parameter should be a pointer to const char.
      • There is no need to call the length function repeatedly since the length presumably does not change: call it once and save the result in a variable.
      • You used the magic numbers: 47 and 58. It would be better to check against '0' and '9' instead (modifying the comparison to >= and <= respectively), or use isdigit as mentioned in post #1.
      • Instead of having an empty body with a "pass" comment, you could negate the condition then do away with the else branch.

    • Consider an indent level of more than a single space. Generally, people choose an indent level of between two to eight spaces, or a single tab. (My personal preference is four spaces, both as a compromise between stylistic extremes and because it was later reinforced by convention in a programming language I regularly use that happens to depend a great deal on indentation.)
    yea... what she said... i was just about to point out the same things... beat me to it again laserlight

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 12-08-2014, 08:12 PM
  2. Replies: 46
    Last Post: 08-24-2007, 04:52 PM
  3. "itoa"-"_itoa" , "inp"-"_inp", Why some functions have "
    By L.O.K. in forum Windows Programming
    Replies: 5
    Last Post: 12-08-2002, 08:25 AM
  4. "CWnd"-"HWnd","CBitmap"-"HBitmap"...., What is mean by "
    By L.O.K. in forum Windows Programming
    Replies: 2
    Last Post: 12-04-2002, 07:59 AM