Array function removes first char from the array - c

I am trying to write a function for a bigger project that consists of working with character arrays. The current function I am working on, is supposed to save only alphabetical characters and remove any special characters (Ex: ! # # $ ? ) and spaces. My current function works, but for some reason when I run it, the first character of the array is always removed. Why is that and how can I make it to save the first character instead?
#include <stdio.h>
int main(void)
{
char phrase[101];
printf("Enter a phrase to change:");
fgets(phrase, 101, stdin);
printf("original phrase: %s", phrase);
int i = 0, j = 0;
while(phrase[i] != '\0')
{
if( ('A' <= phrase[i] && phrase[i] >= 'Z') ||
('a' <= phrase[i] && phrase[i] >= 'z') )
{
phrase[j] = phrase[i];
i++;
j++;
}
else
i++;
phrase[j] = '\0';
}
printf("new phrase: %s\n", phrase);
return 0;
}

The direction of your comparison operators is wrong. Instead of:
if( ('A' <= phrase[i] && phrase[i] >= 'Z') ||
('a' <= phrase[i] && phrase[i] >= 'z') )
You need:
if( ('A' <= phrase[i] && phrase[i] <= 'Z') ||
('a' <= phrase[i] && phrase[i] <= 'z') )
The way you wrote it will skip uppercase letters, which is probably why it skipped the first character of your input.
You should also move the line phrase[j] = '\0'; to after the loop, because otherwise you may overwrite the next character to be read.

Well, I'm guessing the first character isn't alphanumeric. You have a line specifically removing it:
phrase[j] = '\0';
Either you remove the first character (if it's not alphanumeric), or you remove the second (if the first is alphanumeric).
You should put the trailing \0 only after you're done scanning your string.
EDIT: As #interjay pointed out, your check is wrong, so your first character is always treated as not alphanumeric. That's why you erase it.

I guess because your first character is the only upper-case one, and your logic is wrong.
if( ('A' <= phrase[i] && phrase[i] >= 'Z') ||
('a' <= phrase[i] && phrase[i] >= 'z') )
should be
if( ('A' <= phrase[i] && phrase[i] <= 'Z') ||
('a' <= phrase[i] && phrase[i] <= 'z') )
although the C library does provide isalpha which would also work on EBCDIC character sets where 'A' to 'Z' are not consecutive.

How about using isalpha() from ctype.h?
if (isalpha(phrase[i])) {
phrase[j] = phrase[i];
/* ... */
}
But to speak about your question:
The while loop is only visited once, since the predicate of the loop is not met after the first time it is executed, because you set phrase[j] to '\0' in the first time the loop is run.
Edit: Oh, I have not read the if condition carefully. As #interjay points out, it is also wrong.

Related

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 to determine if user input is an number using a boolean function in C

I am trying to figure out how to determine if the user input is a number and not a letter/symbol (A,a,!,#,#,$,%) in C, using a boolean function. The code I am using (if statement) only works for lower case and capitals letters. Below is my code for the if statement that works. Below that I will include the boolean function I am (unsuccessfully) attempting. Am I missing something in my boolean function?
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')){
printf("Character '%c' does not represent a digit\n", ch);}
_Bool isNumber(char ch) {
printf("Character '%c' does not represent a digit\n", ch);
return 0;}
Is it possible without a library function?
The C standard library already has such a beast:
#include <ctype.h>
:
if (! isdigit(ch)) {
printf("'%c' is not a digit\n", ch);
}
If, for some bizarre reason(a) you cannot use the standard library function, simply roll your own:
bool isDigit(int ch) { // Uppercase D to distinguish it.
return ch >= '0' && ch <= '9';
}
You can also do it directly in the code rather than as a function:
if (ch < '0' || ch > '9') puts("Not a digit"); // or:
if (ch >= '0' && ch <= '9') puts("Is a digit");
The digit characters in C are guaranteed by the standard to be contiguous, unlike all the other characters. That's why doing the same for alphas (like ch >= 'a' && ch <= 'z') is a bad idea.
Keep in mind that's for a single character being a digit. That appears to be what you want. To check if a character string is a valid integer, it'll need to be more complex. Basically, every character will need to be a digit, and it may have an optional sign at the front. Something like this would be a good start:
bool isInt(char *sstr) {
unsigned char *str = sstr;
if (*str == '+' || *str == '-')
++str;
if (! isdigit(*str++)) // or your own isDigit if desired.
return false;
while (*str != '\0')
if (! isdigit(*str++)) // ditto.
return false;
return true;
}
(a) Though I suppose you may want to do it for educational purposes, so not necessarily that bizarre :-)
If you want to stay true to your original logic, if(ch >= '0' && ch <= '9')) will be true if ch is any digit and false for any other character.

Function to check for alphabetic characters

I created a Function to check if user typed a Real Name excluding all other non alphabetic characters.
Well, from my side, as a beginer in C language its works fine.
Anyway i have just a small problem, with the string name, if there is space inside that string i get wrong Name, but if there is only one name (michi) everything is ok.
#include <stdio.h>
#include<string.h>
/* Here is the Function which check if the string contains only: */
/* abcdefghijklmnopqrstuvwxyz and ABCDEFGHIJKLMNOPQRSTUVWXYZ */
int checkName(char *s){
int i,length;
length = (strlen(s));
for (i=0;i<length;i++){
if(s[i] == '0' || s[i] <= '9'){
return 1;
}
}
return 0;
}
int main(){
char name[]= "Michi";
int check;
if((check = checkName(name)) == 0){
printf("\n\n\t\t\tYour name is:\t%s\n\n",name);
}else{
printf("\n\n\t\t\tWrong name:\t%s\n\n",name);
}
return 0;
}
My questions are:
1)
Did i found a right way of checking if string contains only non alphabetic characters.
2)
How can i extend my Function to skip spaces
Take a look at isalpha in ctype.h. This returns true if a char is a letter, just like what you want.
http://www.cplusplus.com/reference/cctype/isalpha/
By the way, if you're checking ASCII encodings, your function fails for characters such as '(' or '~'.
Here is the Function which check if the string contains only:
abcdefghijklmnopqrstuvwxyz and ABCDEFGHIJKLMNOPQRSTUVWXYZ
Looking at the code below that statement, you're lying. What your code does is checking whether there is a character 0 or any character below 9 in the string. Better do what you're saying:
if((str[i] >= 'a' && str[i] <= 'z') ||
(str[i] >= 'A' && str[i] <= 'Z') ||
(str[i] == ' ')) {
// fine ..
}
else {
// not fine!
}
As you see I added the space to the set of allowed characters. To get rid of the if branch just negate the whole test expression (either by hand or using the not operator !).
The comparisons are working this way because of the layout of the ASCII table.
Note that there's a library function for this: isalpha
If you have a valid set, test against this set, not other sets that might or might not be the complement set (So many sets in one sentence :-):
for (i=0; i<length; i++) {
int valid = 1;
valid &= s[i] >= 'a' && s[i] <= 'z';
valid &= s[i] >= 'A' && s[i] <= 'Z';
valid &= s[i] == ' ';
if (!valid) {
return 0; // or any value you prefer to indicate "not valid"
}
}
If you want to check only alphabetic chars and space, you can use isapha and isspace from ctype.h. These functions return non-zero for ture and zero for false.
You can just continue the loop if the character is a space:
for (i=0;i<length;i++){
if(s[i] == ' '){
continue;
}
else if(s[i] == '0' || s[i] <= '9'){
return 1;
}
}
Furthermore, you could also make sure it does not contain any other character than just alphabetic, by checking if all character are not outside the range of accepted characters:
for (i=0;i<length;i++){
if((s[i] < 'A') || (s[i] > 'Z' && s[i] < 'a') || (s[i] > 'z')){
return 1;
}
}
Note: the ASCII table is a nice "tool" to confirm the range you have to check.

Exceptions in c programming language

I'm learning c language and I hit a wall, if you would like to help me I appreciate (here is the ex: "Write a program that reads characters from the standard input to end-of-file. For each character, have the program report whether it is a letter. If it is a letter, also report its numerical location in the alphabet and -1 otherwise." btw is not homework).The problem is with the \n i don't know how to make it an exception. I'm new around here please let me know if I omitted something. Thank you for your help.
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z')
{
order = ch - 'A' + 1;
printf(" %d \n", order);
}
if (ch >= 'a' && ch <= 'z')
{
order = ch - 'a' + 1;
printf(" %d \n", order);
}
if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
{
if (ch == '\n');
else if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
printf(" -1 \n");
}
}
system("pause");
}
You are talking about an "exception" which can be interpreted in other ways in programming.
I understand that you want that '\n' be "excepted" in the set of nonalphabetical characters, that is, that it doesn't generate the error value -1.
Since you are using console to run the program, a sequence of character is going to be read till ENTER key is pressed, which generates the character \n. So, I'm not pretty sure that the while() condition you used, that compares against EOF, it's a good decision of yours.
I would put there directly the comparisson against '\n'.
while ((ch = getchar()) != '\n')
To inform if ch is a letter or not, we could use string literals. The following use of string assignment would deserve more explanation, but I will omit it. It's valid with string literals:
char *info;
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
You are assuming an encoding where the letters are in contiguous increasing order (as in ASCII).
By assuming that, it's enough to work with uppercase or lowercase letters, since you are only interested in the position that the letter occupy in the alphabet. So, you can choose to work with uppercase, for example, in this way:
if (ch >= 'a' && ch <= 'z')
ch = (ch - 'a' + 'A');
The effect of that line of code is that ch is converted to uppercase, only if ch is a lowercase letter. Another kind of character is not affected.
As a consequence, from now on, you only have uppercase letters, or nonalphabetical characters.
Then it's easy to code the remaining part:
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; // It brings no. position of letter in alphabet
else
order = -1; // This is the erroneous case
A printf() at the end of the loop could bring all the information about the character:
printf(" %16s: %4d \n", info, order);
The resulting code is shorter in more clear:
#include <stdio.h>
int main(void) {
char ch;
int order;
char *info;
while ((ch = getchar()) != '\n') {
printf("%c",ch);
if (ch >= 'a' && ch <= 'z') /* Converting all to uppercase */
ch = (ch - 'a' + 'A');
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; /* Position of letter in alphabet */
else
order = -1; /* Not in alphabet */
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
printf(" %16s: %4d \n", info, order);
}
}
If you need to end the input by comparing against EOF, then the type of ch has to be changed to int instead of char, so you can be sure that the EOF value (that is an int) is properly held in ch.
Finally, this means that ch needs initialization now, for example to a neutral value in the program, as '\n'.
Finally, just for fun, I add my super-short version:
#include <stdio.h>
int main(void) {
int ch, order;
while ((ch = getchar()) != '\n') {
order = (ch>='a' && ch<='z')? ch-'a'+1:((ch>='A' && ch<='Z')? ch-'A'+1: -1);
printf("%c %8s a letter: %4d \n", ch, (order != -1)? "is":"is not", order);
}
}
The C language does not have exceptions. Exceptions were first introduced into programming in C++. You can do it manually in C using setjmp() and longjmp(), but it really isn't worth it.
The two most popular of doing error handling in C are:
Invalid return value. If you can return -1 or some other invalid value from a function to indicate 'there was an error', do it. This of course doesn't work for all situations. If all possible return values are valid, such as in a function which multiplies two numbers, you cannot use this method. This is what you want to do here - simply return -1.
Set some global error flag, and remember to check it later. Avoid this when possible. This method ends up resulting in code that looks similar to exception code, but has some serious problems. With exceptions, you must explicitly ignore them if you don't want to handle the error (by swallowing the exception). Otherwise, your program will crash and you can figure out what is wrong. With a global error flag, however, you must remember to check for them; and if you don't, your program will do the wrong thing and you will have no idea why.
First of all, you need to define what you mean by "exception"; do you want your program to actually throw an exception when it sees a newline, or do you simply want to handle a newline as a special case? C does not provide structured exception handling (you can kind-of sort-of fake it with with setjmp/longjmp and signal/raise, but it's messy and a pain in the ass).
Secondly, you will want to read up on the following library functions:
isalpha
tolower
as they will make this a lot simpler; your code basically becomes:
if ( isalpha( ch ) )
{
// this is an alphabetic character
int lc = tolower( ch ); // convert to lower case (no-op if ch is already lower case)
order = lc - 'a' + 1;
}
else
{
// this is a non-alphabetic character
order = -1;
}
As for handling the newline, do you want to just not count it at all, or treat it like any other non-alphabetic character? If the former, just skip past it:
// non-alphabetic character
if ( ch == '\n' )
continue; // immediately goes back to beginning of loop
order = -1;
If the latter, then you don't really have to do anything special.
If you really want to raise an honest-to-God exception when you see a newline, you can do something like the following (I honestly do not recommend it, though):
#include <setjmp.h>
...
jmp_buf try;
if ( setjmp( try ) == 0 ) // "try" block
{
while ( (ch = getchar() ) != EOF )
{
...
if ( ch == '\n' )
longjmp( try, 1 ); // "throw"
}
}
else
{
// "catch" block
}
I'm having hard time trying to understand why you even try to handle '\n' specifically.
You might be trying to implement something like this:
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z') {
order = ch - 'A' + 1;
printf(" %d \n", order);
} else if (ch >= 'a' && ch <= 'z') {
order = ch - 'a' + 1;
printf(" %d \n", order);
} else if (ch == '\n') { } else {
printf(" -1 \n");
}
}
system("pause");
}
While this is a good solution, I would recommend rewriting it in a more optimal way:
int main(void)
{
char ch;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
int order;
if (ch != '\n'){
if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {
order = ch & 11111B;
printf("Letter %d\n", order);
} else {
order = -1;
printf("Not letter: %d\n", order);
}
}
}
system("pause");
}
This way the program relies on specific way letters coded in ASCII

Resources