String character check - c

i should realize two very similar functions but i am having problems.
I have to read the string "username", this string can only contain letters (upper and lower case) and spaces.
I have to read the string "key", this string can only contain letters (upper and lower case) and numbers.
If the guidelines are not followed, the user must be able to retrieve the input.
Unfortunately, I cannot use special libraries (only stdio and stdlib).
I realized this:
void checkString(char *i){
int cont;
do {
scanf("%s", i);
if (checkStrLen(6, 6, i) != 0) { //function that controls the size of the string (min,max,string)
for(cont=0; cont<6;){
if((i[cont]>='0' && i[cont]<='9')||
(i[cont]>='A' && i[cont]<='Z')||
(i[cont]>='a' && i[cont]<='z')){
cont++;
}else{
printf("Not valid character");
printf("Try again");
}
}
}else{
printf("\nToo large string");
printf("\nTry again");
}
}while(1);
}
I was thinking of doing something similar.
For the first problem I would replace (i[cont]>='0' && i[cont]<='9') with (i[cont]==' ').
the problem is that I don't understand how to get out of the for if I find a forbidden character during the loop.
I was thinking of using a break, but that would get me out of the whole function.
any advice?
PS how does the function look like? can it be okay or is it completely wrong?

I think the do while loop is not necessary here. do the scanf and get user input first then call checkString. Inside checkString keep your if else statement.
char checkString(char *i){
int cont;
if (checkStrLen(6, 6, i) != 0) { //function that controls the size of the string (min,max,string)
for(cont=0; cont<6;){
if((i[cont]>='0' && i[cont]<='9')||
(i[cont]>='A' && i[cont]<='Z')||
(i[cont]>='a' && i[cont]<='z')){
cont++;
}else{
printf("Not valid character");
printf("Try again");
return i;
}
}
}
else{
printf("\nToo large string");
printf("\nTry again");
}
}

#include <stdio.h>
#define MAXSIZE 100
#define SIZELIM 6
#define true 1
#define false 0
// Returns length of string
// If possible, use strlen() from <string.h> instead
int strlen(char *str) {
char i;
for (i = 0; str[i] != 0 && str[i] != '\n'; i++);
return i;
}
// Returns 1 if strings are equal
// If possible, use strcmp() from <string.h> instead
int streq(const char *x, const char *y) {
char chrx = 1, chry = 1, i;
for (i = 0;
chrx != 0 && chry != 0 && chrx == chry;
chrx = x[i], chry = y[i], i++);
return chrx == chry;
}
// Returns 1 if chr is number or letter
// If possible, use isalnum() from <ctype.h> instead
int isalnum(const char chr) {
return (chr >= '0' && chr <= '9' ||
chr >= 'A' && chr <= 'Z' ||
chr >= 'a' && chr <= 'z');
}
// Checks if string contains numbers and letters only
int isvalid(const char *str) {
int valid = true;
for (int i = 0; str[i] != 0 && str[i] != '\n'; i++) {
if (!isalnum(str[i])) {
valid = false;
break;
}
}
return valid;
}
// Main
int main(void) {
char str[MAXSIZE];
for (;;) {
printf("> ");
fgets(str, MAXSIZE, stdin);
if (streq(str, "quit\n"))
break;
if (strlen(str) > SIZELIM || !isvalid(str)) {
if (strlen(str) > SIZELIM)
puts("String too large");
else if (!isvalid(str))
puts("Not a valid string");
puts("Try again"); }
}
return 0;
}

You can code those functions that you cannot import:
int letters_and_spaces(char c)
{
return c == ' ' || C >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
int letters_and_numbers(char c)
{
return c >= '0' && c <= '9' || C >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
And to use scanf to read spaces you can't use %s. You could change to:
scanf("%100[^\n]*c", i);
BE CAREFUL: I've put 100, supposing i has enough space for that. It will read up to 100 characters (or as many as the number you put there) or until find the \n.

Related

How to check a string contain a certain value in C

#include <stdio.h>
#include <string.h>
#define CHAR_SIZE 35
//Function to remove white space
char *remove_white_spaces(char *str)
{
int i = 0, j = 0;
while (str[i])
{
if (str[i] != ' ')
str[j++] = str[i];
i++;
}
str[j] = '\0';
return str;
}
void main()
{
int i = 0;
char str[CHAR_SIZE];
printf("\nKey in input: ");
fgetchar();
fgets(str , CHAR_SIZE, stdin);
//Remove white space
remove_white_spaces(str);
printf("%s",str);
//for (i = 0; str[i] != '\0'; ++i);
//printf("Length of the string: %d", i);
if (str[i] == '0' || str[i] == '1' )
{
printf("CORRECT");
}
else
{
printf("Wrong Input");
}
}
I want to check whether the user has type in the correct input. For example, I have key in 0 01111110 10100000000000000000000. After removing the white space, the str input became 00111111010100000000000000000000. From this str, I want to check that the user has only key in 0 and 1. The output of the result I got was correct which is shown below1.
Output of result
However, when the user key in another value including 0 and 1. The output I suppose to get is the wrong input. But I obtained Correct as the result which is shown below2.
Output of result
Additional question, How do I implement an if statement that the str has to only have 32 characters to continue otherwise it has to break and the user key has to key in 32 characters only. Can I do it in a while loop instead of an if statement so that the user would not need to run the code again?
You could use strtok to extract your characters. Also there's a flaw in your logic. it should be if (str[i] == '0' || str[i] == '1' to check if the value is '0' OR '1'. Here's a sample implementation you could refer to:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHAR_SIZE 100
int main()
{
char str[CHAR_SIZE];
printf("\n Key in value: ");
getchar();
fgets(str, CHAR_SIZE, stdin);
char *tok;
tok = strtok(str, "\n");
int i = 0;
tok++; //skip the first character which is a space
while (*tok != 0x00)
{
if (*tok <= 0x31 && *tok >= 0x30)
tok++;
else
{
printf("Wrong number input ==> %c \n", *tok);
break;
}
}
}
initialize i:
putting the equivalent of C's
int i = 0;
in your prog lang before entering the while loop should do the job.
First of all, you are checking that str[i] should be equal to 0 and equal to 1 – and that doesn't make any sense, because an element in the array can be only one value, 0 or 1; so, you should test if (str[i] == '0' || str[i] == '1').
And, before that, you should initialize i: int i = 0.
Edit you must loop over elements of the string
int check = 0;
while (str[i] != '\0')
{
if (str[i] == '0' || str[i] == '1')
i++;
else {
check = 1;
break;
}
}
if (check == 0){
print("CORRECT");
}
else {
printf("WRONG INPUT");
}

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.

palindrome c program is not working for some reason

this program checks weather the entered string is palindrome or not . it should be in a way like it should even tell the string is palindrome if there is space or any special character
like messi is a palindrome of iss em
and ronald!o is a palindrome of odlanor
this is the program and for some odd reason it is strucking and not working
#include <stdio.h>
#include <string.h>
int main() {
char palstr[100], ans[100];
printf("enter the string for checking weather the string is a palindrome or not");
scanf("%[^/n]", &palstr);
int ispalin = 1, i = 0, n = 0;
int num = strlen(palstr);
printf("the total length of the string is %d", num);
while (i <= num) {
if (palstr[i] == ' ' || palstr[i] == ',' || palstr[i] == '.' ||
palstr[i] == '!' || palstr[i] == '?') {
i++;
}
palstr[n++] == palstr[i++];
}
int j = num;
i = 0;
while (i <= num) {
ans[j--] = palstr[i];
}
printf("the reverse of the string %s is %s", palstr, ans);
if (ans == palstr)
printf("the string is a palindrome");
else
printf("the string is not a palindrome");
return 0;
}
A few points to consider. First, regarding the code:
if (ans == palstr)
This is not how you compare strings in C, it compares the addresses of the strings, which are always different in this case.
The correct way to compare strings is:
if (strcmp(ans, palstr) == 0)
Second, you should work out the length of the string after you have removed all unwanted characters since that's the length you'll be working with. By that I mean something like:
char *src = palstr, dst = palstr;
while (*src != '\0') {
if (*c != ' ' && *src != ',' && *src != '.' && *src != '!' && *src != '?') {
*dst++ = *src;
}
src++;
}
Third, you have a bug in your while loop anyway in that, if you get two consecutive bad characters, you will only remove the first (since your if does that then blindly copies the next character regardless).
Fourth, you may want to consider just stripping out all non-alpha characters rather than that small selection:
#include <ctype.h>
if (! isalpha(*src) {
*dst++ = *src;
}
Fifth and finally, you don't really need to create a new string to check for a palindrome (though you may still need to if you want to print the string in reverse), you can just start at both ends and move inward, something like:
char *left = &palstr, right = palstr + strlen(palstr) - 1, ispalin = 1;
while (left < right) {
if (*left++ != *right--) {
ispalin = 0;
break;
}
}
There may be other things I've missed but that should be enough to start on.
well, the are so many bugs in this code. I will point them out with comments.
#include <stdio.h>
#include <string.h>
int main() {
char palstr[100], ans[100];
printf("enter the string for checking weather the string is a palindrome or not\n");
scanf("%s", palstr); // your former code won't stop input util Ctrl+D
int ispalin = 1, i = 0, n = 0;
int num = strlen(palstr);
printf("the total length of the string is %d\n", num);
while (i < num) { // < insted of <=
if (palstr[i] == ' ' || palstr[i] == ',' || palstr[i] == '.' ||
palstr[i] == '!' || palstr[i] == '?') {
i++;
continue;// without this, marks still in the string
}
palstr[n++] = palstr[i++]; //should be =
}
palstr[n] = '\0'; //
num = n; // the length might be changed
i = 0;
int j = num-1; // reverse
while (i < num) { //
ans[i++] = palstr[j--]; //
}
ans[i] = '\0'; //
printf("the reverse of the string %s is %s\n", palstr, ans);
//if (ans == palstr) they can never be equal
if (strcmp(ans, palstr)==0)
printf("the string is a palindrome\n");
else
printf("the string is not a palindrome\n");
return 0;
}

Given a list of words, I am to read them using scanf("%c", &c), create a string out of the letters and print the rest unchanged

For instance, in a sentence such as
Its a great day. Right?
I want to keep reading until I reach a non-letter character, call my helper function on each string created and print the rest unchanged.
This is what I have so far but it only prints the first letter numerous times
void string_create(void) {
char word[1000+1] = {0};
int i = 0;
int j=0;
char c = 0;
while (scanf("%c", &c) == 1) {
if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
word[i] = c;
i++;
}
else {
printf("%s", word);
i=0;
printf("%c", c);
}
}
}
In the end for now, without going into details of the helper function, it should simply print the original sentence unchanged.
Current output:
Its ats great dayat.dayat Right?Right
The problem is here (infinite loop) :
while((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
Use if instead of while.
Try this,
#include <stdio.h>
void string_create(void)
{
char word[1000+1] = {0};
int i = 0;
char c = 0;
scanf("%c",&c);
while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
word[i++]=c;
while((c=getchar()!='\n')&&(c!=EOF)); //to remove white space
scanf("%c",&c);
}
printf("%s",word);
}
int main()
{
string_create();
return 0;
}
Output:
q
w
e
r
t
y
1
qwerty
Process returned 0 (0x0) execution time : 8.205 s
Press any key to continue.
you can also give new line(enter) instead of 1
you can also use this
scanf("%1000[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]",word);
it only read letters

How do I check if a string only contains one and zero?

I am trying to detect whether a string contains only the characters '0' and '1'. This is what I have so far:
while (indexCheck < 32) {
if ((input[indexCheck] != '0') && (input[indexCheck] != '1')) {
printf("not binary ");
indexCheck++;
} else if ((input[indexCheck] = '0') && (input[indexCheck] = '1')) {
indexCheck++;
printf("is binary ");
}
}
I know why it returns "is binary" or "not binary" for every single character in the array, but I don't know how to fix this. I want it to return "is binary" once if the string is only made of '1' and '0', and the opposite if this is false. I'm new to C so all help is appreciated.
Instead of looping manually through the string, you can see if it only contains certain characters by checking to see if strspn() returns the length of the string (By seeing if the index of the value it returns is the 0 terminator at the end of the string):
_Bool is_binary(const char *s) {
if (!s || !*s) {
return 0;
}
return s[strspn(s, "01")] == '\0';
}
I would make a function for this:
int isBinary(const char *input)
{
for (int i = 0; input[i]; ++i)
if (input[i] != '0' && input[i] != '1')
return 0;
return 1;
}
Then you can call the function:
if (isBinary("0001110110101"))
printf("is binary\n");
else
printf("is not binary\n");
https://ideone.com/tKBCbf
You can stop looping through the string the moment you find a character which is neither '0' nor '1'. After the loop is terminated, you check whether or not you've reached the end of the string, i.e. the current character is a null character '\0'
while (*s == '0' || *s == '1') ++s;
if (*s)
puts("not binary");
else
puts("binary");
You can do:
while (indexCheck < 32)
{
if ((input[indexCheck] != '0') && (input[indexCheck] != '1'))
{
break;
}
else
{
indexCheck++;
}
}
if (indexCheck == 32)
printf("is binary ");
else
printf("is not binary ");
Only when it has processed all elements and did not encounter a non 1-or-0 ends the loop with indexCheck == 32 so you can use that to determine what to print.
Note also that your else condition is not needed.
there is a block of code for you with comments.
#include <stdio.h>
#include <stdlib.h>
#define STRING_SIZE 32 // Better to use #define for reusability
// Function prototype
int isBinary(char * testInput);
// Main program
int main(void)
{
// Test inputs
char testInputBinary[33] = "01010101010101010101010101010101";
char testInputNotBinary[33] = "010101010101010101010101010101ab";
// Test & collect results
if (isBinary(testInputBinary))
{
printf("Binary ! \n");
}
else
{
printf("Not binary ! \n");
}
if (isBinary(testInputNotBinary))
{
printf("Binary ! \n");
}
else
{
printf("Not binary ! \n");
}
return EXIT_SUCCESS;
}
int isBinary(char * testInput)
{
int loopIdx = 0; // Loop index
int returnVal = 0; // 0: False, 1: True
// iterate over string
for (loopIdx = 0; loopIdx < STRING_SIZE; loopIdx++)
{
if(testInput[loopIdx] != '0' && testInput[loopIdx] != '1')
{
break;
}
}
// If the loop is not broken, it means all characters are in binary form
if (loopIdx == STRING_SIZE)
{
returnVal = 1;
} // No need to writing else clause since returnVal = 0 at the beginning
return returnVal;
}
int isBinary = 1;
while (input[indexCheck] != '\0')
{
if (input[indexCheck] != '1' && input[indexCheck] != '0')
{
isBinary = 0;
break;
}
++indexCheck;
}
if (isBinary)
{
printf("binary");
}
else
{
printf("not binary");
}
Check each element in string input. If input[index] is not 0 or 1 the flag isBinary becomes 0 and breaks while. And you do not need length of string.

Resources