Counting the number of characters that are not in an array - arrays

In this method I am counting the type of characters that are in a data file. It successfully counts the number of character A-Z (Uppercase), a-z (Lowercase), and any digit, I also need it to count if there are any other type of character besides the ones already counted. Everything I have tried has counted all of the characters, none of the characters, or only a select few.
Thanks
public void countChars (){
String currentWord;
for(int pass = 0; pass < numberOfTokens; pass++){
currentWord = words[pass];
for (int i = 0; i < currentWord.length(); i++){
char ch = currentWord.charAt(i);
if (ch >= 'A' && ch <= 'Z'){
numberOfUpperCase++;
}
if (ch >= 'a' && ch <= 'z'){
numberOfLowerCase++;
}
if (ch >= '0' && ch <= '9'){
numberOfDigits++;
}
}
}
}//end of countChars

You should check their ascii values it will be easier, use (int) my_char
and check if it's value is between 0-47, 58-64 or 91-127. Refer to this table to understand why: ASCII VALUES
This is basically what you are already doing, by saying if(char >= a && char <= z) The next code should be enough to solve your issue.
char my_char = '#';
int ascii_value = (int) my_char;
System.out.println("ASCII value of " + my_char + " is " + ascii_value);
if((ascii_value >= 0 && ascii_value <= 47) || (ascii_value >= 58 && ascii_value <= 64) || (ascii_value >= 91 && ascii_value <= 127)){
System.out.println("Your character is a symbol!");
}

Related

Kernighan and Ritchie - exercise 3.3 (expand function)

I have solved the exercises 3.3 from the K&R book. The solution I have implemented seems to work, but is a bit verbose and there could be smarter way to write this code. I wanted to ask if there could be problems with the solution I implemented and if there were easier way to write it:
Write a function expand(s1,s2) that expands shorthand notations like
a-z in the string s1 into the equivalent complete list abc...xyz in
s2. Allow for letters of either case and digits, and be prepared to
handle cases like a-b-c and a-z0-9 and -a-z. Arrange that a leading or
trailing - is taken literally
My code is this one:
#include <stdio.h>
void expand(char s1[],char s2[]){
int j=0,i=0;
while(s1[j] != '\0'){
if (s1[j]>= 'a' && s1[j] <= 'z' && s1[j+1] == '-' && s1[j+1]!='\0' && s1[j+2] >= 'a' && s1[j+2] <= 'z' && s1[j+2] !='\0'){
int z = s1[j+2]-s1[j];
int c;
for (c=0;c<=z;c++){
s2[i]= c+s1[j];
i++;
}
j=j+3;
}
else if (s1[j]>= 'A' && s1[j] <= 'Z' && s1[j+1] == '-' && s1[j+1]!='\0' && s1[j+2] >= 'A' && s1[j+2] <= 'Z' && s1[j+2] !='\0'){
int z = s1[j+2]-s1[j];
int c;
for (c=0;c<=z;c++){
s2[i]= c+s1[j];
i++;
}
j=j+3;
}
else if (s1[j]>= '0' && s1[j] <= '9' && s1[j+1] == '-' && s1[j+1]!='\0' && s1[j+2] >= '0' && s1[j+2] <= '9' && s1[j+2] !='\0'){
int z = s1[j+2]-s1[j];
int c;
for (c=0;c<=z;c++){
s2[i]= c+s1[j];
i++;
}
j=j+3;
}
else if (j!= 0 && s1[j] == '-' && (s1[j-1] < s1[j+1])){
int z = s1[j+1]-(1+s1[j-1]);
int c;
for (c=0;c<=z;c++){
s2[i]= c+(s1[j-1]+1);
i++;
}
j=j+2;
}
else if ( s1[j]>= 32 && s1[j] <= 127 && (s1[j+1] != '-' || s1[j+1]>= 32 && s1[j+1] <= 127 )){
s2[i] = s1[j];
j++;
i++;
}
}
s2[i]='\n';
i++;
s2[i]='\0';
}
int main() {
int c;
char s2[100];
expand("-a-c,a-c-g,A-Z0-9--", s2);
printf("%s",s2);
}
The code works in this way:
First it check if there is a triplet of the kind "x-y" where x<y. Then if gives to the array the values from x to y included and jump to the next character after the triplet "x-y". The same is done for upper case letters and for numbers in further if conditions.
the condition else if (j!= 0 && s1[j] == '-' && (s1[j-1] < s1[j+1])) is used to check for cases like "a-c-d1". The code I have implemented in this example will work like this:
Since we start with the 0-th character in "a-c-d" and the pattern "x-y" is present, "abc" will be assigned to the array. then we will directly jump to the second - in "a-c-f". Since this second - is preceded by a letter "c" and followed by a letter "f", and "c"<"f", then the characters between "c" and "f" will be assigned to the array, excluding the initial "c". Then the index for the string will jump of two and reach 1.
Some other way :
you only to know the last char before - and if it is the same type as current one (lower or upper case letter or digit)
when you get a - and previous char is a letter or digit you know you may have to make expansion
if you have a letter or digit after - and it is corresponding to letter/digit before - you know you can expand from char before / to current one.
you do need to look forward but only save previous char and char before -
you do same kind of processing for each different char type (letter/digit)
You can find an example after :
#include <stdio.h>
// handle different char type
typedef enum E_chartype {
LowerCaseLetter,
UpperCaseLetter,
Digit09,
OtherChar
} E_chartype;
// save if we may have a posdible expansion
typedef enum E_states {
NothingStarted,
StartedExpansion
} E_states;
// find type of a char
E_chartype getCharType(char c) {
if ((c >= 'a') && (c <= 'z'))
return LowerCaseLetter;
if (( c >= 'A') && (c <= 'Z'))
return UpperCaseLetter;
if ((c >= '0') && (c <= '9'))
return Digit09;
return OtherChar;
}
void expandopt(char *inS, char *outS) {
// init output string to null string
outS[0] = 0;
char *endS = outS;
E_states automat = NothingStarted;
char savedChar = 0;
int currentIndex;
E_chartype prevCType=OtherChar,savedCType=OtherChar;
char savedC = 0,prevC=0;
// loop on input string
for (currentIndex = 0; inS[currentIndex] != 0;currentIndex++) {
// save current char in variable c for shorter writting
char c = inS[currentIndex];
printf("%c : ",c);
// save type of current char
E_chartype currentCType = getCharType(c);
switch (automat) {
// genersl case notjing yet started
case NothingStarted:
// possibkee expansion if previous chsr is letter or digit and current char is -
if ((prevCType != OtherChar) && (c == '-')) {
printf("start rep\n");
automat = StartedExpansion;
// save the previous char and its type as it eill br the reference fircexpansion
savedCType = prevCType;
savedC = prevC;
} else {
// reset and cooy current char to iutput
automat = NothingStarted;
printf("nothing\n");
*endS++ = c;
}
break;
case StartedExpansion:
// we make ecpansion only if still same char type and letter/digit is strictly after saved one
if ((currentCType == savedCType) && (c > savedC)){
printf("expansion ");
for (char newC
= savedC+1;newC <= c;newC++) {
*endS++ = newC;
}
// save char in case thrre id a - after, which mean nee expansion
savedC = c;
} else {
// save current chsrcsnd its type
savedCType = currentCType;
savedC = c;
// copy previous char (= -) whch was not vopief in case of expansion
*endS++ = prevC;
*endS++ = c;
}
automat = NothingStarted;
break;
}
// save current chsr and type
prevCType = currentCType;
prevC = c;
}
// add 0 at end of string
*endS = 0;
}
int main() {
expandopt("-a-c,a-c-g,A-Z0-9–",s2);
printf("%s\n",s2);
}
Sorry for the code formatting, I did not find good code editor on phone.

Find spaces and alphanumeric characters in a string C Language

Hi i'm trying to build a function in C language that checks if the string contains numbers , upper cases and lower cases and space, if the string contains any other character then those the function return -1.
float avg_word_len(char* str)
{
float check;
for (int i = 0; i < strlen(str); i++)
{
if (((str[i] >= '0') && (str[i] <= '9')&&(str[i] >= 'a') && (str[i] <= 'z') && (str[i] == ' ')&& (str[i] >= 'A') && (str[i] <= 'Z')))
check = 1;
else
check = -1;
}
str = '\0';
return check;
that's my code ,but the function keep return -1 please help
Some of your && must replaced by || because one character is a number OR a lower case OR a space OR an upper case, but it cannot be all these things at a time :
check = 1;
for (int i = 0; i < strlen(str); i++)
{
if (! (((str[i] >= '0') && (str[i] <= '9')) ||
((str[i] >= 'a') && (str[i] <= 'z')) ||
(str[i] == ' ') ||
((str[i] >= 'A') && (str[i] <= 'Z')))) {
check = -1;
break;
}
}
You can use these three function which are countain in the hreader #include <ctype.h>
isalpha : Checks if a character is alphabetic (upper or lower case).
isdigit : Checks if a character is a number.
isblank : Checks whether a character is blank or not.
#include <ctype.h>
#include <stdio.h>
float avg_word_len(char* string)
{int check=-1;
for(int i=0;string[i]!='\0';i++)
{
if(isalpha(string[i])||isdigit(string[i])||isblank(string[i]))
{
check=1;
}
}
return check;
}
int main()
{
char string[150];
printf("Give me a text :");
scanf("%s[^\n]",string);
printf("\n%.f\n",avg_word_len(string));
}
As Weather Vane commented, a lot of those &&s should be ||s - additionally, parentheses should surround each range (e.g. ('0' <= str[i] && str[i] <= '9'))).
To check whether the character is in a range, we use AND (i.e. the character is above the lower bound AND below the upper bound). To check whether the character is in one of multiple ranges, we use OR (i.e. the character is in range 1 OR it is in range 2 OR...).
If we were to only fix that, here's how the if condition would look:
(str[i] >= '0' && str[i] <= '9') || (str[i] >= 'a' && str[i] <= 'z') || (str[i] == ' ') || (str[i] >= 'A' && str[i] <= 'Z')
Having said that, I would suggest using the function isalnum from ctype.h in the standard library, which checks if a character is alphanumeric. It makes the code much simpler and avoids the assumption that characters are ordered in such a way that all lowercase letters lie between 'a' and 'z' (which is true in ASCII - which is what is used in practice - but is not standard).
In addition, I would suggest initializing check to -1 and breaking early from the loop once you find a non-alphanumeric, non-space character so that a -1 is not later overwritten by a 1 (as would happen in the current version of your code).
This is what it would look like:
float check = -1;
for (int i = 0; i < strlen(str); i++)
{
if (!isalnum(str[i]) && str[i] != ' ') {
check = 1;
break;
}
}

reading space character into string with size determined by str_size

I'm trying to make this program such that the user could type any given string of characters, and the program would separate alphanumerical characters from the rest, print them into a second string, and finally print the final result into the screen.
I've already tried using scanf ("%[^\n]%*c", string);, but it doesn't seem to work since the size of the string is not specified beforehand, and is rather defined by STR_SIZE.
char string[STR_SIZE];
printf("please type in a string \n");
scanf("%s", string);
printf("string: \n %s \n", string);
int size = (strlen(string));
char alfanumerico[STR_SIZE];
int count = 0;
int count2 = 0;
while(count <= size)
{
if(string[count] >= '0' && string[count] <= '9')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] >= 'a' && string[count] <= 'z')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] >= 'A' && string[count] <= 'Z')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] ==' ')
{
alfanumerico[count2] = string[count];
count2++;
}
count++;
}
printf("alphanumerical characters typed: \n %s \n", alfanumerico);
Given the user typed a string such as: -=-=[[][][]}}Hello 123 ```//././.
I expect the output to be: Hello 123
scanf is not the way to go, especially if your input might contain white-spaces on which scanf would stop reading more inputs and wouldn't store spaces for instance.
You should use fgets which lets you limit the input data according to the buffer this data is stored in. So something like:
fgets(string, STR_SIZE, stdin)
should work.
About the size - you should have some limitation about the maximum size of the string and then STR_SIZE should be set to this number. It should be part of your program requirements or just a size that makes sense if you're making the requirements. It must be defined before you're reading input from the user because the buffer memory is allocated before reading to it.
A comment about style, unrelated to your question - always try to decrease code duplication to 0. The line alfanumerico[count2] = string[count]; count2++; appears 4 times in your code. A more elegant minimal if statement with exactly the same functionality would be:
if ((string[count] >= '0' && string[count] <= '9') ||
(string[count] >= 'a' && string[count] <= 'z') ||
(string[count] >= 'A' && string[count] <= 'Z') ||
(string[count] == ' '))
{
alfanumerico[count2] = string[count];
count2++;
}
and to be even more minimal:
char c = string[count];
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c == ' '))
{
alfanumerico[count2] = c;
count2++;
}
It's also more readable and more maintainable - if you want to change the variable count to i you do it in one place instead of 8.
Also, always close a scope in a new line.

How do I get my C program to ignore whitespace(spaces, tabs, newlines)?

Im new to programming with C and I'm having a hard time coming up with the proper formula to where it ignores, spaces, tabs, and new lines when I enter a string
My Current Code
Replace else specialCharacter++; with else if(!isspace(str[x])) specialCharacter++;.
You can see for spaces, tab, new lines in a string by taking each character and checking for them and then doing appropriate operations if necessary.
Here is the code which is in alignment with your code.
#include<stdio.h>
#include<ctype.h>
int main(void){
char str[1000];
int x,lowerCase,upperCase,digit,specialCharacter,total;
printf("Enter a string");
gets(str);
x = lowerCase = upperCase = digit = specialCharacter = total =0;
for(;str[x]!='\0';x++){
if(str[x] >= 'A' && str[x] <='Z') upperCase++;
else if(str[x] >= 'a' && str[x] <='z') lowerCase++;
else if(str[x] >= '0' && str[x] <='9') digit++;
else if(str[x] == '\n' || str[x] == '\t' || str[x] == ' '){}
else specialCharacter++;
}
total = lowerCase + upperCase + digit + specialCharacter;
printf("lowercase= %d , uppercase=%d , digit=%d , special=%d \n", lowerCase,upperCase,digit,specialCharacter );
printf("%d",total);
return 0;
}

Change letter with number

I'm doing an exercise, to practice, where the point is to receive a string of numbers and letters, check if it's a letter, transforme it to number with the rule
A = 10, Z = 35
and then place everything in an array. Some operations after.
I know how to do everything except the rule part, no idea about how to check which letter it is and how to replace it with the right number. I know there's a way with something like
if(string[x] == 'a-Z')
but i'm neither sure how that works, or how to pick the right number knowing that it's a letter.
There are many approaches, some more portable than others.
The following looks for thestring[x] in an array. If successful, the pointer difference between it and the start is the value.
const char *alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *p = strchr(alphanum, string[x]);
if (p == NULL || *p == '\0') {
; // Not a digit or A-Z
} else {
int value = p - alphanum;
// do something with the value;
}
I'll leave handling of a-z to the OP. (convert to upper or use another array)
If code assumes ASCII, with its A Z in sequential order:
int ToValue(char ch) {
if (ch >= 'A' && ch <= 'Z') return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'z') return ch - 'a' + 10;
if (ch >= '0' && ch <= '9') return ch - '0';
// No match
return -1;
}
I like to divide functions like that into more functions that deal with smaller pieces of logic.
int isLowerCaseLetter(char c)
{
return ( c >= 'a' && c <= 'z');
}
int isUpperCaseLetter(char c)
{
return ( c >= 'A' && c <= 'Z');
}
int letterToNumber(char c)
{
if ( isdigit(c) )
{
return (c - '0');
}
else if ( isLowerCaseLetter(c) )
{
return (c - 'a' + 10);
}
else if ( isUpperCaseLetter(c) )
{
return (c - 'A' + 10);
}
// Problem
assert(0);
return 0; // Keep the compiler happy
}

Resources