Hey all.
I'm fairly new to programming and I just have a little issue. I have a code that will read in a string of character and outut weather the character are alphabetical or not but i also need to use a counter to count how many time each character is used.
For example:
Hi my name is Jon.
would out put
h = 1
i = 2
m = 2 etc.

any help would be great.

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


void readin(char line[])
{

    printf("Enter string: ");
    scanf("%s", line);
    strlen(line);

    return;
}

void counter(char line[], int &count)
{

    while(line[count])
    {
        if(isalpha(line[count]))
            printf("Character %c is alphabetic\n",line[count]);
        else
            printf("character %c is not alphabetic\n",line[count]);
        count++;
    }

    return;
}

int main()
{

    const int MAXSIZE = 100;
    char line[MAXSIZE] = {'\0'};
    int count;

    count = 0;

    readin(line);
    counter(line,count);

    return(0);

}

int &count

That is not allowed in C. Reference parameters are C++, use a pointer instead.

const int MAXSIZE = 100;
char line[MAXSIZE] = {'\0'};

I think this falls under "variable length arrays" (VLA's) which is a C99 feature. I'm not entirely sure because of the const keyword though, but I think it's still one. Define MAXSIZE as a preprocessor macro instead.

void readin(char line[])

As a guideline always supply the capacity of an array as well. In this case I'll add one called 'max'.

scanf("%s", line);

This will not read the whole line. If the line contains spaces for example, it will stop earlier. Replace it with the following:

// fgets reads until a newline is encountered (which it
// will store in 'line' OR 'max-1' characters have been read.
fgets(line, max, stdin);

length = strlen(line);

// The whole string fit into our array, remove the newline
if (line[length - 1] == '\n')
{
    line[length - 1] = '\0';
}
// We couldn't fit all of the input into the array. Clear the input buffer.
else
{
    while (fgetc(stdin) != '\n');
}

As far as your counter function goes, I think you can figure that out yourself. A little addition that might help you on how to do it:

void counter(char line[], int count)
{
    int symbol_count[ALPHABET_SIZE] = {0};

    while(line[count])
    {
        if(isalpha(line[count]))
            printf("Character %c is alphabetic\n",line[count]);
        else
            printf("character %c is not alphabetic\n",line[count]);
        count++;
    }
    return;
}

Then you might create a function like this one:

void update_character_count(const char symbol, int occurrences[], const int size)
{
    assert(size >= ALPHABET_SIZE);

    char lower_symbol = tolower(symbol);

    if (lower_symbol >= 'a' && lower_symbol <= 'z')
    {
        occurrences[lower_symbol - 'a']++;
    }
}

Taking these changes into account your code would look like this:

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

#define MAXSIZE (100)
#define ALPHABET_SIZE (26)

void readin(char line[], const int max);
void counter(char line[], int count);
void update_character_count(const char symbol, int occurrences[], const int size);

void readin(char line[], const int max)
{
    int length = 0;

    printf("Enter string: ");

    // fgets reads until a newline is encountered (which it
    // will store in 'line' OR 'max-1' characters have been read.
    fgets(line, max, stdin);

    length = strlen(line);

    // The whole string fit into our array, remove the newline
    if (line[length - 1] == '\n')
    {
        line[length - 1] = '\0';
    }
    // We couldn't fit all of the input into the array. Clear the input buffer.
    else
    {
        while (fgetc(stdin) != '\n');
    }
}

void update_character_count(const char symbol, int occurrences[], const int size)
{
    assert(size >= ALPHABET_SIZE);

    char lower_symbol = tolower(symbol);

    if (lower_symbol >= 'a' && lower_symbol <= 'z')
    {
        occurrences[lower_symbol - 'a']++;
    }
}


void counter(char line[], int count)
{
    int symbol_count[ALPHABET_SIZE] = {0};

    while(line[count])
    {
        if(isalpha(line[count]))
            printf("Character %c is alphabetic\n",line[count]);
        else
            printf("character %c is not alphabetic\n",line[count]);
        count++;
    }
    return;
}

int main()
{
    char line[MAXSIZE] = {'\0'};

    int count;
    count = 0;
    readin(line, MAXSIZE);
    counter(line,count);
    return 0;
}

Try to solve it from here.

Thaks for that thats closer to what im after. I thouogh I would have needed a module in there to do the character count. Below is the code as it there is a coupke of issues though.
length = strlen(line); in the first module has an error "implicit conversion looses integer precision"
int symbol_count[ALPHABET_SIZE] = {0}; has an "unused variable" error
and finally my call for the update_character_count module is wrong :-(

I think im suffering from domestic blindness haha I cant see the soloution for looking too hard

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

#define MAXSIZE (100)
#define ALPHABET_SIZE (26)

void readin(char line[], const int max);
void counter(char line[], int count);
void update_character_count(const char symbol, int occurrences[], const int size);

char symbol;
int occurrences, size;

void readin(char line[], const int max)
{
    int length = 0;
    printf("Enter string: ");
    fgets(line, max, stdin);
    length = strlen(line);

    if (line[length - 1] == '\n')
    {
        line[length - 1] = '\0';
    }
    else
    {
        while (fgetc(stdin) != '\n');
    }
}
void update_character_count(const char symbol, int occurrences[], const int size)
{
    assert(size >= ALPHABET_SIZE);
    char lower_symbol = tolower(symbol);
    if (lower_symbol >= 'a' && lower_symbol <= 'z')
    {
        occurrences[lower_symbol - 'a']++;
    }
}
void counter(char line[], int count)
{
    int symbol_count[ALPHABET_SIZE] = {0};

    while(line[count])
    {
        if(isalpha(line[count]))
            printf("Character %c is alphabetic\n",line[count]);
        else
            printf("character %c is not alphabetic\n",line[count]);
        count++;
    }
    return;
}
int main()
{
    char line[MAXSIZE] = {'\0'};
    int count;
    count = 0;
    readin(line, MAXSIZE);
    update_character_count(symbol, occurrences, size);
    counter(line,count);

    return 0;
}

length = strlen(line); in the first module has an error "implicit conversion looses integer precision"

strlen returns a size_t officially which is generally an unsigned int. I attempt to store it into an int which could theoretically cause issues. You'd be best to change it yeah, my bad.

int symbol_count[ALPHABET_SIZE] = {0}; has an "unused variable" error

That's your compiler being strict. It's more of a warning.

readin(line, MAXSIZE);
update_character_count(symbol, occurrences, size);
counter(line,count);

This is indeed not what I had in mind when writing that function. Your "counter" function was used to process each individual character in the read string. It currently only prints if it's alpha or not, but this could easily be extended to count the occurrences for each character. That is where you could use the function I supplied, or could come up with your own solution.

The array that is currently unused just happens to have 26 counters, which is the amount of character in the alphabet.

The function I supplied wants a char, array of occurrences and the size of that array and it will update the counter for the supplied symbol if and only if that symbol is a-z or A-Z. I didn't knew your exact needs but I assumed that 'a' and 'A' should be considered as 2x'a' in your case.

Let me know how it works out.

P.S.

char symbol;
int occurrences, size;

I'm not sure why you added these global definitions, you probably shouldn't.

Ok cheers for that i think im chasing my tail a bit and im not 100% sure how to incorpoate the counter function you provided. Where does the "symbol" get its char, obviousl its the user entered char, I changed some stuff just to try get counter working right but i think i may have made it worse haha.
Does it have something to do with the "symbol_count" not being used??
Thanks again

void readin(char line[], const int max);
void counter(char line[], int occurrences[]);

void readin(char line[], const int max)
{
    int length = 0;
    printf("Enter string: ");
    fgets(line, max, stdin);
    length = strlen(line);


    if (line[length - 1] == '\n')
    {
        line[length - 1] = '\0';
    }

    {
        while (fgetc(stdin) != '\n');
    }
}

void counter(char line[], int occurrences[])
{
    char symbol;
    int size = 0;

    symbol = line[MAXSIZE];

    assert(size >= ALPHABET_SIZE);
    char lower_symbol = tolower(symbol);
    if (lower_symbol >= 'a' && lower_symbol <= 'z')
    {
        occurrences[lower_symbol - 'a']++;
    }
    return;
}

int main()
{
    char line[MAXSIZE] = {'\0'};
    int count;

    count = 0;

    readin(line, MAXSIZE);
    counter(line); /* this currently has an error in calling also i think because the "occurrences" isnt mentioned*/

    return 0;
}

Hmm no this doesn't quite work. Let's start with words. We a C-String (array of character termined by a '\0') that we obtained from the user. Now we want to count how often each character occurs in that string.

How would you attempt to do it? Explain it conceptually; how would you do it if you had to do it when the word was written down and you only had a pencil and a notepad? Don't get into programming terminology.

Once you have a clear view on that we can attempt to convert the idea into a working application.

well to do it on paper you would go through and take the frist letter, count how mant time that letter occurrs and record, then move on to the second letter count how many times it is used then record.
I kinda get what needs to be done im just not sure how to do it. Im thinking a "for" loop will be used to loop the array and everytime a character is done the loop moves onto the next in the string.

Edited 4 Years Ago by RAPTOR88

well to do it on paper you would go through and take the frist letter, count how mant time that letter occurrs and record, then move on to the second letter count how many times it is used then record.

What would you do on a string like "aaaaaa"? Would this be counted as 36 a's (6 times 6) by your algorithm?

I kinda get what needs to be done im just not sure how to do it. Im thinking a "for" loop will be used to loop the array and everytime a character is done the loop moves onto the next in the string.

That's a viable option. Looping over every character in the string is probably useful. Then what will you do? Considering what you described above, how do you plan on storing the count for each character? How are you going to record what characters you've already processed?

Edited 4 Years Ago by Gonbe

Hey Gonbe,
Thanks so much for your help. I went back to the drawing board and changed everythin haha. Now the program works which is good. I just have a quick question though. where I declared the array size i used a const of 20 for 20 characters within the string, however this only gave me 18 results ... WTF. I think one of them may be needed for the end stinf '\0' but what is the other for??

It's indeed true that 1 character is reserved for the '\0' character so when declaring an array of size 20 it is capable of storing a string of length 19 at most. I'm not sure why your stored one of length 18. Can you post a small code example that is representative of the issue?

Better yet i will post the whole thing, Let me know what you think and if you can work out there the extra element is haha

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

/* This function gets the string from the user and saves it to the array line. This function also gets the size of the array passed in from the main function */
void GetString (char line[], int size)
{
    printf("Enter a string no longer than 20 characters:\n");
    fgets(line, size, stdin);
    line[strlen(line) - 1] = '\0';

    printf("You Entered %s\n", line);

    return;
}

/* This function gets the line array passed in and an array for the counter that is set to 27, 26 for the alphabet and 1 for other */
void counter  (char line[], int counts[])
{
    int i;
    char c;

    for (i = 0; i < strlen(line); i++)
    {
        c = tolower (line [i]); /* Sets all the characters used to lower case */
        if (c >= 'a' && c <= 'z')
        {
            counts[c - 'a']++; /* counts and adds to the alphabetical characters. This will loop through the alphabet and when a haracter used matches 1 is addes to the count */
        }
        else /* this is used to apply a count to the non alphabetical characters */
        {
            counts[26]++;
        }
    }
    return;
}

/* This function calls the counts array and prints the values. It will loop and print all the alphabetical characters and there useage number. The loop will end with the printing of the non alphabetical character count */
void PrintCounts(int counts[])
{
    int i;
    for (i=0; i < 26; i++)
    {
        printf("There are %d occurrences of %c\n", counts[i], i + 'a');
    }
    printf("There are %d occurrences of non alphabetic\n", counts[26]);
    return;
}

int main()
{
    const int SIZE = 22;    /* Define the array size */
    char line[22] = {'\0'}; /* Define the array for the sotreage of the string */
    int counts[27] = { 0 }; /* Define the size of the count array */

    GetString(line, SIZE);
    counter(line, counts);
    PrintCounts(counts);

    return(0);
}

You were overwriting the last character in the string with a '\0' yourself. You didn't notice it on smaller input because fgets reads the newline character as well. So it overwrote that instead of a character of the line you entered.

Here's quick fix of the code. The problem was in your GetString function. I didn't look closely to the rest of the code but if you need help with anything just let me know. (Though it seems it does now what you want it to do!)

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

void GetString (char line[], int size);
void counter  (char line[], int counts[]);
void PrintCounts(int counts[]);

/* Define the array size */
#define MAX_WORD_LENGTH (20)

/* This function gets the string from the user and saves it to the array line. This function also gets the size of the array passed in from the main function */
void GetString (char line[], int size)
{
    size_t input_length = 0;

    printf("Enter a string no longer than %d characters:\n", MAX_WORD_LENGTH);
    fgets(line, size, stdin);

    // This isn't needed. if fgets reads 'size - 1' chars it automatically
    // terminates the array with a '\0'. Note that fgets also reads the '\n' though.
    // So i replaced this line:

    // line[strlen(line) - 1] = '\0';

    // with this:
    input_length = strlen(line);

    if (line[input_length - 1] == '\n')
    {
        line[input_length - 1] = '\0';
    }
    // Still things in the input buffer.
    else
    {
        while (fgetc(stdin) != '\n');
    }

    printf("You Entered %s\n", line);

    return;
}
/* This function gets the line array passed in and an array for the counter that is set to 27, 26 for the alphabet and 1 for other */
void counter  (char line[], int counts[])
{
    int i;
    char c;

    for (i = 0; i < (int)strlen(line); i++)
    {
        c = tolower (line [i]); /* Sets all the characters used to lower case */
        if (c >= 'a' && c <= 'z')
        {
            counts[c - 'a']++; /* counts and adds to the alphabetical characters. This will loop through the alphabet and when a haracter used matches 1 is addes to the count */
        }
        else /* this is used to apply a count to the non alphabetical characters */
        {
            counts[26]++;
        }
    }

    return;
}

/* This function calls the counts array and prints the values. It will loop and print all the alphabetical characters and there useage number. The loop will end with the printing of the non alphabetical character count */
void PrintCounts(int counts[])
{
    int i;

    for (i=0; i < 26; i++)
    {
        printf("There are %d occurrences of %c\n", counts[i], i + 'a');
    }
    printf("There are %d occurrences of non alphabetic\n", counts[26]);

    return;
}

int main()
{
    char line[MAX_WORD_LENGTH + 1] = {'\0'}; /* Define the array for the sotreage of the string */
    int counts[27] = { 0 }; /* Define the size of the count array */

    GetString(line, MAX_WORD_LENGTH + 1);
    counter(line, counts);
    PrintCounts(counts);

    return 0;
}

Edited 4 Years Ago by Gonbe

This article has been dead for over six months. Start a new discussion instead.