1

this small program basically should get user input, read if it has any a's or A's and store those counts into Array[]. then print out that count of Array[].

#include<stdio.h>

main()
{
    int Array[100] = {0};

    int i;

    char input[100];

    printf("Enter a message:...");
    gets(input);

    for(i=0; input[i]!='\0'; i++)
    {
        if (input[i]=='a' || input[i]=='A') {Array[i]++;}   
    }

    printf("Total A's:%d\n",Array[i]);
}

example input/output from console:

 Enter a message:...harry 

 Total A's:0

clearly there is an 'a' in the input, but its not being considered. now i tried putting the printf in the for loop, but its would output this:

Enter a message:...harry 

 Total A's:0 

 Total A's:1 

 Total A's:0 

 Total A's:0 

 Total A's:0

what's happening is its apparently reading how many chars is the message, and checking for each index if it has a, which is supposed to do, but it's also printing out at each index this output.

Its supposed to only printf ONCE.so putting printf in loop does work, but generates this "bug" with it.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 2
    [DO NOT use `gets()`, it is dangerous](http://stackoverflow.com/q/1694036/2173917). use [`fgets()`](https://linux.die.net/man/3/fgets) instead. – Sourav Ghosh Apr 10 '17 at 05:24
  • @Sourav Ghosh i realize that its not recommended, but fgets apparently requires more parameters, and for this short program, i dont really want to expand it more than needed. you can say im using it temporarily for now – masterofcatastrophe Apr 10 '17 at 05:27
  • 2
    @masterofcatastrophe - One thing you learn when doing software is that there is no such thing as "temporarily". I've seen many a comment like *"Terrible hack - will remove soon - May 2 2000"* on code that hasn't been touched since June of 2000. Do it right to start with, or you'll carry technical debt for ages. – StoryTeller - Unslander Monica Apr 10 '17 at 05:32
  • @StoryTeller true lol, and i plan to change it no worries :) just for now though i needed to get past this small issue quick – masterofcatastrophe Apr 10 '17 at 05:34
  • 2
    @StoryTeller __[...and don't forget the maintainer](http://stackoverflow.com/q/876089/2173917)__ – Sourav Ghosh Apr 10 '17 at 05:53

4 Answers4

0

The problem is

 printf("Total A's:%d\n",Array[i]);

does not do what you think it does. The value you're trying to print is useless, from the point of logic.

Instead of incrementing the count for each occurrence of 'A' or 'a', you're just incrementing the initial value of the particular index ( of the Array ) for which you've found a match in the input. After that, you're printing the value of the variable of the index, for which the value has not been altered, in any way (hint: check the value of i after the loop).

Apparently, you don't need an array to hold the count of a single variable. Just use a normal variable, initialize it to 0 and keep on incrementing it.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

At the last iteration i equals 99. Then i is incremented to 100 so the loop ends and then you want to print Array[100]. That index is out of bounds so it is undefined behavior.

As you say in the comment, you want to store the count of all characters in the array. Then calculate the letter to an index in the array based on its position in the alphabet.

#include <ctype.h>

for(i=0; input[i]!='\0'; i++)
{
  char c = tolower(input[i]);
  if (isalpha(c))
   Array[c - 'a']++;
}

This way 'a' will be index 0, 'b' 1 etc

'a' is an integer value (97 in the ascii table). 'b' is 98, c = '99' etc. So when you have 'a' in a variable and you subtract a literal 'a' the result = 0. 'b' - 'a' = 1 'c' - 'a' = 2 etc

Check here for ascii table values:

http://www.asciitable.com/

Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
  • while in this case it would be easy then to just printf count variable, the issue lies in the fact that i have to count vowels from the input. A, E, I, O, U. so here what im trying to do is A[i]++ if there is an a or A. or E[i]++ if there is e or E, etc... so you can see, i would need to have then count1, count2, count3, etc...which im trying to avoid if possible. i mean it works if i put the printf statement is the loop, its just that its printf statement as many times as there are chars from input – masterofcatastrophe Apr 10 '17 at 05:39
  • ah you should rephrase your question – Serve Laurijssen Apr 10 '17 at 05:42
  • 2 questions: ive seen this similar type of recommendation on other threads about something - 'a', but what does that mean exactly? i didnt understand it yet. so in the case of doing the other arrays, would it be like E[c - 'e']++; U[c - 'u']++; etc? – masterofcatastrophe Apr 10 '17 at 06:04
  • also im not getting any count of a's yet. even though i tried your solution – masterofcatastrophe Apr 10 '17 at 06:06
  • I'll try this again – masterofcatastrophe Apr 10 '17 at 12:40
0

apparently, i just needed to use another variable j and change index in printf to 0.

#include<stdio.h>

main()
{
    int Array[100] = {0};

    int i;

    char input[100];

    printf("Enter a message:...");
    gets(input);

    for(i=0; input[i]!='\0'; i++)
    {   int j = 0;
        if (input[i]=='a' || input[i]=='A') {Array[j]++;}   
    }

    printf("Total A's:%d\n",Array[0]);
}

SOLVED :)

  • Good deal, but remember, `main` is type `int` and **returns** a value (regardless of ancient compilers that allowed such nonsense, and excepting current hardware specific ones that require it). So the proper invocation of `main` is either `int main (void)` with no arguments or `int main (int argc, char **argv)` (or with the equivalent `char *argv[]`). All will `return 0;` at minimum (or whatever positive `byte` value you desire -- there is slight variation in acceptable returns `0-127` or `0-254` OS dependent). Also do ***NOT*** use `gets`. If you prof wants `gets` get a new prof. – David C. Rankin Apr 10 '17 at 07:18
  • Seriously, see the very first comment under you original question posted by @Sourav Ghosh and take it seriously -- it is that important for security reasons. Otherwise you are leaving yourself, and anyone that uses your code, open to buffer overflow exploits. Not good... Correctly using `fgets` takes minimal additional effort. If you show up to an interview with `gets` anywhere in your code -- the best you can hope for is a job where you will ask "Would you like fries with that Sir?" – David C. Rankin Apr 10 '17 at 07:22
  • also i don't really think that's what your prof meant when he said that you need to use an array. It doesn't seem right to create an array of size 100 just to use the first element (position 0) to count how many As you have – John Doe Apr 10 '17 at 07:31
  • @John Smith I had this done using just variables, the professor said it's good, but instead variable make it array. So literally convert variable to array. Unless of course there is a way I could store a count of the different chars I wanna store, in just a single array, then somehow output each unique char count stored to its appropriate line – masterofcatastrophe Apr 10 '17 at 12:35
  • @David C. Rankin loool some professors don't really care about the useages, as long as program does wat they want. Thts reality :/ btw, wat does int argc, char **argv mean? I always wondered about this...also it always worked for me with just int main (). Why do I need void for instance or the other parameters as arguments? – masterofcatastrophe Apr 10 '17 at 12:38
  • @masterofcatastrophe if you execute your program passing it some arguments they get stored inside argv and their count inside argc. With this you can know how many arguments you have by reading argc and know which one they are with argv[0],argv[1],... (remember that argv[0] is the name of the program you are running so the "real" arguments start from 1). main(void) is used in C because creating a function with (void) means it has no arguments while creating it with just () means that the function could take any number of parameters of any value. In C++ function() == function(void) – John Doe Apr 11 '17 at 13:37
  • @masterofcatastrophe creating a function with function() could lead to problems if that function is then called passing some parameters to it. Usually that causes undefined behavior but in some cases it could lead to more severe problems. – John Doe Apr 11 '17 at 13:46
0

Your problem is a classic frequency problem. Whenever you need to calculate the frequency of a set of values, you use an array capable of holding that number of values. In your case, you need to know the frequency of the occurrence of 'a's and 'A's for a total of 2 elements (initialized to zero).

As you execute your code and test for the occurrence of any one of the values, you simply increment the element that corresponds to that value, e.g.

a_array[0]++;   /* when an 'a' is encountered */
a_array[1]++;   /* when an 'A' is encountered */

After you scan the entire string, the number of 'a's are in a_array[0] and the number of 'A's in a_array[1].

Putting that together, along with replacing gets (which you NEVER, EVER USE AGAIN) with fgets, you can do something like:

#include <stdio.h>
#include <string.h>

#define MAXC 256

int main (void) {

    int a_array[2] = {0};   /* if you are counting 'a's and 'A's, you need 2 */
    char buf[MAXC] = "";

    while (fgets (buf, MAXC, stdin)) /* for each line of input */
    {
        char *p = buf;
        size_t len = strlen(p);     /* get the length */

        if (buf[len-1] == '\n')     /* remove the trailing '\n' */
            buf[--len] = 0;         /* by overwriting with '\0' */

        for (; *p; p++)             /* for each char in buf */
            if (*p == 'a')          /* is it an 'a'? */
                a_array[0]++;       /* if so increment the 'a' counter */
            else if (*p == 'A')     /* if it is an 'A' */
                a_array[1]++;       /* increment the 'A' counter */

        printf ("\nthere are '%d' a's and '%d' A's in\n'%s'\n",
                a_array[0], a_array[1], buf);

        a_array[0] = a_array[1] = 0;    /* zero for next line */
    }

    return 0;
}

Example Use/Output

$ printf "my dog has A lot of fleas\nA snake has none - Amen.\n" | \
./bin/num_aAs 

there are '2' a's and '1' A's in
'my dog has A lot of fleas'

there are '2' a's and '2' A's in
'A snake has none - Amen.'

Now typically, you will not hardcode a_array[0] and a_array[1], but will use a logical index to hold the values. For example, to calculate the frequency of each occurrence of each letter a-z (26 characters in all), you could use:

int c_array[26] = {0};

Then when testing for each character, you simply increment c_array[*p - 'a']++;, e.g.

while (fgets (buf, MAXC, stdin))     /* for each line of input */
{
    char *p = buf;
    /* trim '\n' */
    for (; *p; p++)                 /* for each char in buf */
        if ('a' <= *p && *p <= 'z')
            c_array[*p - 'a']++;
    ...

The resulting c_array will hold the number of 'a's in c_array[0] and each corresponding letter frequency in the subsequent element through c_array[25] which hold the frequency for all 'z's.

For example, if you wanted to experiment with a logical index scheme for your problem, you could use something on the order of:

    for (; *p; p++)                     /* for each char in buf */
        if (*p == 'a')                  /* is it an 'a'? */
            a_array[*p - 'a']++;        /* if so increment the 'a' counter */
        else if (*p == 'A')             /* if it is an 'A' */
            a_array[*p - 'A' + 1]++;    /* increment the 'A' counter */
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • wow this is...pretty complex lol. the problem im solving doesnt take into account capital or lower case and display each as frequency. it combines the two in 1 frequency. if i plan on expanding my program further though, ill consider this. .in the mean time, please see the solution i posted, one variable was all it needed – masterofcatastrophe Apr 10 '17 at 06:31
  • now that i look at this, shouldnt char buf[MAXC] = ""; be = ' ' instead of " "? isnt single quotation supposed to be for char and double for string? or char counts as a string too technically? – masterofcatastrophe Apr 10 '17 at 17:20
  • No, You are initializing the contents of `buf` to the *empty-string* which effectively `zeros` all element of the `buf` array (as with all array initializations - each element is set to the value given for initialization, all other elements not initialized are set to `zero`) – David C. Rankin Apr 10 '17 at 20:23
  • I see, since it's empty string it's like initialized to 0 – masterofcatastrophe Apr 10 '17 at 22:22
  • You got it. Actually, the *empty string* is `"\0"`, because all strings, even the *empty string* is *nul-terminated* (which is equivalent to initializing `char buf[MAX] = { 0 };`) because the first char in `buf` is initialized to `'\0'` (which is the same a decimal `0`). So you initialize the first char in `buf`, and all other elements (chars) are initialized to zero by default. – David C. Rankin Apr 10 '17 at 22:56