counting individual characters in c - c

I’m working on a project called readability. the user input a text and the code should then use the coleman-liau function to determine the reading level. But in order to use this fuktion you have to determine the number of words, letters and sentences. Right now I’m busy counting the letters. So I wanted to ask how to count individual characters in c. right now this is my code:
int count_letters (string text)
{
int count_letters = 0;
int numb = 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (text[i] != '')
{
count_letters++;
}
}
return count_letters;
}

You can either use isalpha() or "improvise".
This will work for the ASCII character set:
#include <stdio.h>
int count_letters(const char *str)
{
int count = 0, i = 0;
for (; str[i] != '\0'; i++)
{
if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z'))
{
/* any character within this range is either a lower or upper case letter */
count++;
}
}
return count;
}
int main(void)
{
char *str = "Hello\n world hello123#";
printf("%d\n", count_letters(str));
return 0;
}
or use isalpha(), also supports your current locale.
#include <ctype.h>
int count_letters(const char *str)
{
int count = 0, i = 0;
for (; str[i] != '\0'; i++)
{
if (isalpha((unsigned char)str[i]))
{
count++;
}
}
return count;
}
EDIT: As Andrew mentioned, to be pedantic, you better pass an unsigned char as argument to isalpha() to avoid any undefined behavior that might arise due to the signed type of str.

Related

Check whether a given substring is present in the given string

I should write a program in C to check whether a given substring is present in the given string. The code I wrote is below but it doesn't work. Can anyone tell me where the problem is?
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[30]="the test string";
char sbstr[30]="test";
char strcp[30];
int len = strlen(str);
int i=0;
int p=0;
while(i<len)
{
while (str[i] != '\0' && str[i] != ' ')
{
strcp[i] = str[i];
++i;
}
strcp[i] = '\0';
p = strcmp(sbstr, strcp);
if (p==0)
{
printf("exist");
break;
}
++i;
}
}
For the array strcp
char strcp[30];
you need to support a separate index.
Something like
int j = 0;
while (str[i] != '\0' && str[i] != ' ')
{
strcp[j++] = str[i++];
}
strcp[j] = '\0';
Pay attention to that there is standard C function strstr that can be used to perform the task.
I know you've already accepted an answer, but here's a slightly more efficient way to do a substring comparison that does not involve making a copy of the candidate substring to begin with in each iteration.
char str[30]="the test string";
char sbstr[30]="test";
int len = strlen(str);
int sublen = strlen(sbstr);
int found = 0;
int i = 0; // starting index in str to start comparing on
while (!found && sublen <= len) {
found = 1;
// found = !strncmp(str+i, sbstr, sublen);
for (int j = 0; j < sublen; j++) {
if (str[i+j] != sbstr[j]) {
found = 0;
break;
}
}
if (!found) {
i++;
len--;
}
}
if (found) {
printf("Exists starting at index %d\n", i);
}
And if you really want to get hardcore, there are well known algorithms such as the Boyer–Moore string-search algorithm which can search faster by using a table-lookup scheme IIRC.

C Code to count how many letters in a word

I made simple code to count how many letters in a word, for some reason the variables letters is not consistent, here is the code
#include <stdio.h>
int main()
{
char str;
int slen(char *str)
{
int i;
int letters=0;
for(i=0;i<30;i++)
{
if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
letters++;
}
return letters;
}
printf("%d \n", slen("Word"));
}
The variable letter here prints 22.
Because of the < 30 condition in your for loop, your program goes past the "Word" string boundaries and starts calculating whatever's in memory right after that string.
Replace < 30 with < strlen(str) (you're going to need to #include <string.h>).
UPDATE: (kudos to #J...S (seee comments)) alternatively you can rewrite
for (i=0; i < 30; i++)
{
if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
letters++;
}
with
while (str != '\0') {
if ((*str >= 'A' && *str <= 'Z') || (*str >= 'a' && *str <= 'z')) {
letters++;
}
++str;
}
You could also use something like isalpha() instead of your if condition.
And, by the way, please use spaces to separate different parts of a line. Otherwise it's really hard to read. Thanks :)
The function should be declared/defined outside main().
Change this:
for(i=0;i<30;i++)
to this:
for(i = 0; i < strlen(str); i++)
because you want to iterate over the length of the string, and not more or less than its actual length.
In your case, "Word" had just 4 letters, and you iterated until i < 30 evaluated to false, invoking Undefined Behavior, since you would access memory that is out of bounds.
Putting everything together, we get:
#include <stdio.h>
#include <string.h>
int slen(char *str)
{
int letters=0;
for(unsigned int i=0;i<strlen(str);i++)
{
if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
letters++;
}
return letters;
}
int main()
{
printf("%d \n", slen("Word"));
}
Output:
4
You want this:
#include <stdio.h>
#include <string.h>
// declaring slen outside main (not using non standard GNU extension)
int slen(char *str)
{
int i;
int letters = 0;
int length = strlen(str); // using strlen, in order not to go beyond the end
// of the string
for (i = 0; i < length; i++) {
if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z'))
letters++;
}
return letters;
}
int main()
{
printf("%d \n", slen("Word123"));
}
Expected output here is 4 (4 lettres of "Word", not counting digits 1,2, and 3).
Slighly optimized version:
int slen(char *str)
{
int letters = 0;
for (int i = 0; ; i++) {
char c = str[i];
if (c == 0)
break;
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
letters++;
}
return letters;
}
and even better using isalpha from ctype.h:
#include <ctype.h>
...
int slen(char *str)
{
int letters = 0;
for (int i = 0; ; i++) {
int c = str[i]; // yes, int is correct, isalpha wants an int
if (c == 0)
break;
if (isalpha(c))
letters++;
}
return letters;
}
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
Though some compilers can have their own language extensions nevertheless again according to the C Standard you may not define a function inside another function.
Also take into account that it is not necessary that Latin letters follow each other sequentially in a given character set. For example in the EBCDIC set some letters do not follow sequentially each other. There are embedded other symbols between letters.
So it is better to use standard C function isalpha declared in the header <ctype.h>.
Also the original string is not changed in the function. So it should be declared with the qualifier const.
And it is unclear why this magic number 30 is used in this loop within the function
for(i=0;i<30;i++)
Taking all this into account the program can look like
#include <stdio.h>
#include <ctype.h>
size_t letters_count( const char *s )
{
size_t count = 0;
for ( ; *s; ++s )
{
if ( isalpha( ( unsigned char )*s ) ) ++count;
}
return count;
}
#define N 100
int main(void)
{
char s[N];
printf( "Enter a statement: " );
fgets( s, sizeof( s ), stdin );
printf( "The statement contains %zu letters\n", letters_count( s ) );
return 0;
}
Its output might look like
Enter a statement: Hello TheErolley
The statement contains 15 letters

Segmentation fault when listing the words in a sentence

int getter2(char str[])
{
int len=0;
scanf("%100[^\n]s",str);
while (str[len++] != '\0');
return len-1;
}
int wordmaker(char str[],char word[15][15],int len)
{
int i,temp=0,j=0;
for (i=0;i<len;i++){
if (((str[i]>='a') && (str[i]<='z')) || ((str[i]>='A') && (str[i]<='Z'))){
word[j][temp++] = str[i];
}
else{
j++;
temp=0;
}
}
for (i=0;i<15;i++)
for (j=0;j<15;j++)
printf("%c",word[i][j]);
}
int main()
{
char line[max],word[15][15];
int len;
printf("%d\n%s\n",getter2(line),line);
wordmaker(line,word,len);
}
core dumped.segmentation fault.the wordmaker function is faulty.t does'nt end.when i run the program i get the sentence i put properly along with proper length.the wordmaker function seems to be the problem.
can someone help me debug it.
I fixed some of the problems in the code and got it working. There's problem a though: If you do not input 15 words, it will print garbage (because of the for (i = 0; i < 15; i++) loop in wordmaker).
General points:
You do not need the s in your format string for scanf().
Return type of wordmaker should be void.
Added zero terminating byte to each string.
Printing strings instead of individual characters.
Assigned the return value of getter2 to len inside main.
All that is in the code:
/* str.c
* gcc -o str str.c -Wall
*/
#include <stdio.h>
/* As pointed by #BLUEPIXY, this should be 101 because of the format
* string of scanf. It will read 100 characters from stdin into the
* string, but it doesn't take into account the terminating NULL byte.
*/
#define max 101
int getter2(char str[])
{
int len = 0;
/* no need the trailing s in format string */
scanf("%100[^\n]", str);
while (str[len++] != '\0');
return len - 1;
}
/* changed return type to void, since you're not returning anything */
void wordmaker(char str[], char word[15][15], int len)
{
int i, temp = 0, j = 0;
for (i = 0; i < len; i++) {
if (((str[i] >= 'a') && (str[i] <= 'z'))
|| ((str[i] >= 'A') && (str[i] <= 'Z'))) {
word[j][temp++] = str[i];
} else {
/* put the terminating null byte on each string */
word[j][temp] = 0x0;
j++;
temp = 0;
}
}
/* print the strings, not their characters
*
* If you use a loop to print characters, you need to have 15 byte
* strings, otherwise you're gonna print garbage.
*/
for (i = 0; i < 15; i++)
printf("%s\n", word[i]);
}
int main()
{
char line[max], word[15][15];
int len;
/* here a little modification to initialize the variable 'len' */
printf("%d\n%s\n", (len = getter2(line)), line);
wordmaker(line, word, len);
}
As a side note, if you include ctype.h, you can change ((str[i] >= 'a') && (str[i] <= 'z')) || ((str[i] >= 'A') && (str[i] <= 'Z')) for isalpha(str[i]), which is clearer. The isalpha() manual.

checking if character is upper or lower case in alphanumeric

I have this C code. If I input a LOL123 it should display that it is uppercase. And lol123 it is in lowercase. How do I use isalpha in excluding non-numerical input when checking isupper or is lower?
#include <stdio.h>
#define SIZE 6
char input[50];
int my_isupper(char string[]);
int main(){
char input[] = "LOL123";
int m;
m= isupper(input);
if( m==1){
printf("%s is all uppercase.\n", input);
}else
printf("%s is not all uppercase.\n", input);
return 0;
}
int my_isupper(char string[]){
int a,d;
for (a=0; a<SIZE); a++){
d= isupper(string[a]) ;
}
if(d != 0)
d=1;
return d;
}
For upper-case function just loop trough the string and if a lowercase character is encountred you return false like value. And don't use standard library functions names to name your own functions. Use isUpperCase instead.
Live Demo: https://eval.in/93429
#include <stdio.h>
#include <string.h>
int isUpperCase(const char *inputString);
int main(void)
{
char inputString1[] = "LOL123";
char inputString2[] = "lol123";
printf("%s is %s\n", inputString1, isUpperCase(inputString1)?"upper-case":"not upper-case");
printf("%s is %s\n", inputString2, isUpperCase(inputString2)?"lower-case":"not upper-case");
return 0;
}
int isUpperCase(const char *inputString)
{
int i;
int len = strlen(inputString);
for (i = 0; i < len; i++) {
if (inputString[i] >= 'a' && inputString[i] <= 'z') {
return 0;
}
}
return 1;
}
int my_isalpha_lower(int c) {
return ((c >= 'a' && c <= 'z')); }
int my_isalpha_upper(int c) {
return ((c >= 'A' && c <= 'Z')); }
int isdigit(int c) {
return (c >= '0' && c <= '9'); }
while (*s) {
if (!is_digit(*s) && !my_isalpha_lower(*s))
{
//isnot lower but is alpha
}
else if (!is_digit(*s) && !my_alpha_upper(*s))
{
//is not upper but is alpha
}
s++;
}
char c = ...;
if (isalpha(c))
{
// do stuff if it's alpha
} else {
// do stuff when not alpha
}
You have a lot to learn, besides using a name of a standard function your design also is completely flawed. You only memorize the case of the last character that you encounter in your for loop, so the result that you return is not at all what you think.
Some more observations:
Don't use the name of a standard function for your own.
Arrays decay to pointers when then are used as function parameters. You have no way to automatically detect the size of the array.
You expect your return from isupper to be a logical value. Testing that again with ==1 makes not much sense.
You have two different variables called input, one in file scope, one in main.
Fairly simple:
#include <ctype.h>
/**
* Will return true if there's at least one alpha character in
* the input string *and* all alpha characters are uppercase.
*/
int allUpper( const char *str )
{
int foundAlpha = 0;
int upper = 1;
for ( const char *p = str; *p; p++ )
{
int alpha = isalpha( *p );
foundAlpha = foundAlpha || alpha;
if ( alpha )
upper = upper && isupper( *p );
}
return foundAlpha && upper;
}

Removing spaces and special characters from string

How do you remove spaces and special characters from a string?
I couldn't find a single answer while googling. There were a lot related to other languages, but not C. Most of them mentioned the use of regex, which isn't C standard (?).
Removing a simple space is easy:
char str[50] = "Remove The Spaces!!";
Then a simple loop with a if-statement:
if (str[i] != ' ');
Output would be:
RemoveTheSpaces!!
What do I add to the if-statement so it would recognize special characters and remove them?
My definition of special characters:
Characters not included in this list:
A-Z a-z 0-9
This is probably not the most efficient way of achieving this but it will get the job done fairly fast.
Note: this code does require you to include <string.h> and <ctype.h>
char str[50] = "Remove The Spaces!!";
char strStripped[50];
int i = 0, c = 0; /*I'm assuming you're not using C99+*/
for(; i < strlen(str); i++)
{
if (isalnum(str[i]))
{
strStripped[c] = str[i];
c++;
}
}
strStripped[c] = '\0';
There are millions of different ways this can be done. Here is just one example that is not using any additional storage and performs the removal of unneeded characters "in-place":
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
static void my_strip(char *data)
{
unsigned long i = 0; /* Scanning index */
unsigned long x = 0; /* Write back index */
char c;
/*
* Store every next character in `c` and make sure it is not '\0'
* because '\0' indicates the end of string, and we don't want
* to read past the end not to trigger undefined behavior.
* Then increment "scanning" index so that next time we read the
* next character.
*/
while ((c = data[i++]) != '\0') {
/* Check if character is either alphabetic or numeric. */
if (isalnum(c)) {
/*
* OK, this is what we need. Write it back.
* Note that `x` will always be either the same as `i`
* or less. After writing, increment `x` so that next
* time we do not overwrite the previous result.
*/
data[x++] = c;
}
/* else — this is something we don't need — so we don't increment the
`x` while `i` is incremented. */
}
/* After all is done, ensure we terminate the string with '\0'. */
data[x] = '\0';
}
int main()
{
/* This is array we will be operating on. */
char data[512];
/* Ask your customer for a string. */
printf("Please enter a string: ");
if (fgets(data, sizeof(data), stdin) == NULL) {
/* Something unexpected happened. */
return EXIT_FAILURE;
}
/* Show the customer what we read (just in case :-)) */
printf("You have entered: %s", data);
/*
* Call the magic function that removes everything and leaves
* only alphabetic and numberic characters.
*/
my_strip(data);
/*
* Print the end result. Note that newline (\n) is there
* when we read the string
*/
printf("Stripped string: %s\n", data);
/* Our job is done! */
return EXIT_SUCCESS;
}
I put a lot of comments in there so hopefully the code doesn't need explanation. Hope it helps. Good Luck!
This is just a silly suggestion.
char ordinary[CHAR_MAX] = {
['A']=1,['B']=1,['C']=1,['D']=1,['E']=1,['F']=1,['G']=1,['H']=1,['I']=1,
['J']=1,['K']=1,['L']=1,['M']=1,['N']=1,['O']=1,['P']=1,['Q']=1,['R']=1,
['S']=1,['T']=1,['U']=1,['V']=1,['W']=1,['X']=1,['Y']=1,['Z']=1,
['a']=1,['b']=1,['c']=1,['d']=1,['e']=1,['f']=1,['g']=1,['h']=1,['i']=1,
['j']=1,['k']=1,['l']=1,['m']=1,['n']=1,['o']=1,['p']=1,['q']=1,['r']=1,
['s']=1,['t']=1,['u']=1,['v']=1,['w']=1,['x']=1,['y']=1,['z']=1,
['0']=1,['1']=1,['2']=1,['3']=1,['4']=1,['5']=1,['6']=1,['7']=1,['8']=1,
['9']=1,
};
int is_special (int c) {
if (c < 0) return 1;
if (c >= CHAR_MAX) return 1;
return !ordinary[c];
}
void remove_spaces_and_specials_in_place (char *str) {
if (str) {
char *p = str;
for (; *str; ++str) {
if (!is_special(*str)) *p++ = *str;
}
*p = '\0';
}
}
Using your if statement:
if (str[i] != ' ');
With a little logic (the characters have to be in the range a-z or A-Z or 0-9:
If ( !('a' <= str[i] && 'z' >= str[i]) &&
!('A' <= str[i] && 'Z' >= str[i]) &&
!('0' <= str[i] && '9' >= str[i])) then ignore character.
This is Ascii Code Range
Char:Dec
0:48, 9:57
A:65, Z:90
a:97, z:122
try this:
char str[50] = "Remove The Spaces!!";
int i =0;
for(; i<strlen(str); i++)
{
if(str[i]>=48 && str[i]<=57 || str[i]>=65 && str[i]<=90 || str[i]>=97 && str[i]<=122)
//This is equivalent to
//if(str[i]>='0' && str[i]<='9' || str[i]>='A' && str[i]<='Z' || str[i]>='a' && str[i]<='z')
printf("alphaNumeric:%c\n", str[i]);
else
{
printf("special:%c\n", str[i]);
//remove that
}
}
#include <stdio.h>
#include <string.h>
main()
{
int i=0, j=0;
char c;
char buff[255] = "Remove The Spaces!!";
for(; c=buff[i]=buff[j]; j++){
if(c>='A' && c<='Z' || c>='a' && c<='z' || c>='0' && c<='9'){
i++;
}
}
printf("char buff[255] = \"%s\"\n", buff);
}
include < stdio.h >
int main()
{
char a[100];
int i;
printf("Enter the character : ");
gets(a);
for (i = 0; a[i] != '\0'; i++) {
if ((a[i] >= 'a' && a[i] <= 'z') || (a[i] >= 'A' && a[i] <= 'Z')
|| (a[i] - 48 >= 0 && a[i] - 48 <= 9)) {
printf("%c", a[i]);
} else {
continue;
}
}
return 0;
}

Resources