Detect empty string on stdin and tolower function in C - c

I'm currently making a dictionary program in C.
How to detect empty string on stdin ? Using search_for for my input.
void find_track(char search_for[])
{
int i;
for (i = 0; i < 5; i++) {
if (strstr(tracks[i], search_for)){
printf("The meaning of %s: %s\n",tracks[i], meaning[i]);
break;
}
}
if (!strstr(tracks[i], search_for)) {
printf("%s could not found in dictionary.\n",search_for);
}
}
Again, how do I lower cast the input using tolower function ?
int main()
{
int setloop =1;
titlemessage();
do {
char search_for[80];
char varchar;
printf("Search for: ");
fgets(search_for, 80, stdin);
if(search_for[strlen(search_for)-1]=='\n')
search_for[strlen(search_for)-1]='\0';
find_track(search_for);
printf("Press ENTER to start new search\n");
//printf("Press 'q' to exit the program\n\n");
varchar = getchar();
if (varchar == 10) {
continue;
}else {
break;
}
} while (setloop = 1);
return 0;
}
Any methods will be appreciated.

Detect empty string on stdin and tolower function in C
fgets(search_for, 80, stdin);
if(search_for[strlen(search_for)-1]=='\n')
search_for[strlen(search_for)-1]='\0';
if(strlen(search_for)==0)
{
// empty string, do necessary actions here
}
char ch;
tolower() Converts ch to its lowercase equivalent if ch is an uppercase letter and has a lowercase equivalent. If no such conversion is possible, the value returned is ch unchanged.
for(i = 0; search_for[i]; i++){
search_for[i] = tolower(search_for[i]); // convert your search_for to lowercase
}

After reading the input, potentially change each char to lower case.
// Test fgets() return value, use sizeof
if (fgets(search_for, sizeof search_for, stdin) == NULL) {
break;
}
size_t i;
for (i = 0; search_for[i]; i++) {
search_for[i] = tolower(search_for[i]);
}
// Advantage: we've all ready run through `search_for` & know its length is `i`.
// Also avoid a `[strlen(search_for)-1]` which could be -1
if ((i > 0) && (search_for[i-1] =='\n')) {
search_for[--i] = '\0';
}
// If empty line entered (OP's "detect empty string on stdin")
if (i == 0) {
break;
}
find_track(search_for);
#if 0
// Reccomedn delete this section and using the above empty line test to quit
//printf("Press 'q' to exit the program\n\n");
varchar = getchar();
if (varchar == 10) {
continue;
} else {
break;
}
#endif
// OP likel want to _test_ setloop (==), not _assign_ setloop (=)
// } while (setloop = 1);
} while (setloop == 1);

Related

I want to loop my program with a user prompt "Do you wish to run again? Yes(Y), No(N)". In C

I have this program that I finally finished however I am trying to get it after finishing once to prompt the user "Do you wish to run again? Yes(Y), No(N)". But I also want it to ask for s2 again, and the ch again as well. Keeping s1 to be the same random string if that makes sense.
This is my code:
#include <stdio.h>
#include <stdlib.h>
void s1(char *random);
void s2(char *s2_input, int index);
void strfilter(char *random, char *s2_input, char replacement);
int main()
{
char run = 'Y';
while(run != 'N')
{
int s1_index = 41;
char s1_random[s1_index];
s1(s1_random);
printf("\ns1 = ");
puts(s1_random);
printf("s2 = ");
int s2_index = 21;
char s2_input[s2_index];
s2(s2_input, s2_index);
if(s2_input[1] == '\0')
{
printf("size too small");
exit(0);
}
printf("ch = ");
char replacement = getchar();
printf("\n");
int filter_index = 41;
strfilter(s1_random, s2_input, replacement);
printf("\ns1 filtered = ");
puts(s1_random);
printf("Do you wish to run again? Yes(Y), No(N) ");
scanf("%c", &run);
}
}
void s1(char *random)
{
int limit = 0;
char characters;
while((characters = (('A' + (rand() % 26))))) /* random generatro */
{
if(limit == 41)
{
*(random + 41 - 1) = '\0';
break;
}
*(random + limit) = characters;
limit++;
}
}
void s2(char *s2_input, int index)
{
char array[21] = "123456789012345678901"; /* populated array to make sure no random memory is made */
char input;
int count = 0;
int check = 0;
while((input = getchar() ))
{
if(input == '\n')
{
*(s2_input + count) = '\0';
break;
}
else if(input < 65 || input > 90)
{
printf("invalid input");
exit(0);
}
*(s2_input + count) = input;
count++;
}
index = count;
}
void strfilter(char *random, char *s2_input, char replacement) /* replacement function */
{
while(*s2_input)
{
char *temp = random;
while(*temp)
{
if(*temp == *s2_input)
*temp = replacement;
temp++;
}
s2_input++;
}
}
At first I tried a do-while loop within the main function. But it doesn't seem to work. It just messes up the output of my program and still doesn't prompt the user. Should I create a new function with the sole purpose of prompting the User? If so how would I? Thanks in advance.
To avoid running afoul of trailing data, call readchar() till you get a newline or EOF after each prompt:
for(;;)
{
int s1_index = 41;
char s1_random[s1_index];
s1(s1_random);
printf("\ns1 = ");
puts(s1_random);
printf("s2 = ");
int s2_index = 21;
char s2_input[s2_index];
s2(s2_input, s2_index);
if(s2_input[1] == '\0')
{
printf("size too small");
exit(0);
}
printf("ch = ");
int replacement = getchar();
if(replacement == EOF)
break;
while(getchar() != '\n');
printf("\n");
strfilter(s1_random, s2_input, replacement);
printf("\ns1 filtered = ");
puts(s1_random);
printf("Do you wish to run again? Yes(Y), No(N) ");
int run = getchar();
// or include ctype.h and do:
// run == EOF || toupper(run) == 'N'
if(run == EOF || run == 'N' || run == 'n')
break;
while(getchar() != '\n');
}
and example run:
s1 = NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJY
s2 = NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJY
ch = B
s1 filtered = BBBBBBBB
Do you wish to run again? Yes(Y), No(N) y
s1 = DBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPK
s2 = NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJY
ch = B
s1 filtered = BBBBBBBB
Do you wish to run again? Yes(Y), No(N) N
A very common mistake in C programs taking user input from stdin using getchar and scanf is to forget that these functions may leave newlines (or other characters) in the input stream.
In this case the line
scanf("%c", &run);
will leave (at least) a newline in the stream. That newline will be read by the next getchar and thereby make the program have unexpected behavior.
So your code should remove that newline just after the scanf. Actually it should remove all characters until it sees a newline.
Further, I would also remove any white space present in the stream before scanning for the user input. That can be done simply by putting a space before %c
Finally, your prompt suggests that you expect the user to input either Y or N but your program continues on any input not being an N
Something like this should fix the above mentioned problems:
char run = 'Y';
while(run != 'N')
{
// ... do your stuff
while(1)
{
// notice the space before %c to remove initial white spaces
if (scanf(" %c", &run) != 1) exit(1); // Input error
// Empty the input stream until a newline is found
while (1)
{
int temp = getchar();
if (temp == '\n') break; // Found end-of-line so break this while-loop
if (temp == EOF) exit(1); // Input error
}
if (run == 'Y' || run == 'N') break; // Valid input so break this while-loop
}
}

How to stop the loop after one try?

I am facing some problem here. Whenever I run this code it asks me about name and date of birth. When I give it, it asks me again until I press Ctrl+D. I want this process to be stop after one time and instead it asks me, do you want to continue? If I say yes then it repeat the loop and again ask me one more time. How to do this? I tried but failed.
int main(void){
const char *listing[] = {"Name", "Date of birth"};
char data[2][51];
int done = 0;
FILE *fp;
fp = fopen("/home/bilal/Documents/file.txt", "w+");
while (!done){
for (int i = 0; i < 2; i++){
printf("Enter your %s: ", listing[i]);
if (scanf(" %50[^\n]", data[i]) != 1){
done = 1;
break;
}
}
if (!done){
fprintf(fp, "%s %s\n", data[0], data[1]);
}
}
fclose(fp);
return 0;
}
If I'm interpreting your post correctly, after the first prompt for name and [then] DOB, you want to inject a "Shall I continue?" question.
Here's the refactored code:
#include <stdio.h>
int
domore(void)
{
char buf[51];
int moreflg = -1;
while (moreflg < 0) {
printf("Shall I continue (y/n)? ");
if (scanf(" %50[^\n]", buf) != 1)
break;
switch (buf[0]) {
case 'y':
case 'Y':
moreflg = 1;
break;
case 'n':
case 'N':
moreflg = 0;
break;
}
}
if (moreflg < 0)
moreflg = 0;
return moreflg;
}
int
main(void)
{
const char *listing[] = { "Name", "Date of birth" };
char data[2][51];
int done = 0;
int again = 0;
FILE *fp;
#if 0
fp = fopen("/home/bilal/Documents/file.txt", "w+");
#else
fp = fopen("/tmp/file.txt", "w+");
#endif
while (!done) {
if (again) {
if (! domore())
break;
}
again = 1;
for (int i = 0; i < 2; i++) {
printf("Enter your %s: ", listing[i]);
if (scanf(" %50[^\n]", data[i]) != 1) {
done = 1;
break;
}
}
if (!done) {
fprintf(fp, "%s %s\n", data[0], data[1]);
}
}
fclose(fp);
return 0;
}
scanf() returns the count of parameters successfully matched and formatted, or EOF (-1) in case of an invalid input.
So, the expressions,
char data[1][50]={0};
int val=0;
int count = scanf(" %50[^\n]", data[0]); // 1 parameter to scan and format
will return 1, for a single formatted item.
To get more than 1, you have to scan in, and successfully format more than one item:
count = scanf(" %50[^\n] %d", data[0], &val); //2 parameters to scan and format.
(The return value here will be 2 if successful.)
So, if you change your loop exit criteria to match these expectations, your loop will exit properly.
if (scanf(" %50[^\n]", data[i]) == 1){//now 'done' will be set to true (1)
^^
Edit: Illustrates concepts described above:
(Note, uncomment your file functions, I did not need them for this illustration.)
Program loops until both 'name' and 'date of birth' are captured into a 2D character array. Loop exit criteria uses count of successful, single parameter scanf calls:
int main(void){
const char *listing[] = {"Name", "Date of birth"};
char data[2][51];
int done = 0;
int count = 0;//added to allow visibility of return value of scanf function.
FILE *fp;
//fp = fopen("/home/bilal/Documents/file.txt", "w+");
while (done != 2){
for (int i = 0; i < 2; i++){
printf("Enter your %s: ", listing[i]);
count = scanf(" %50[^\n]", data[i]);
if (count != EOF){
done += count;
// 'break' is not needed here, let the loop leave naturally
}
}
}
if (done == 2)//moved outside of loop because both variables
{ //need to be populated before printing
;//fprintf(fp, "%s %s\n", data[0], data[1]);
}
//fclose(fp);
return 0;
}
The scanf function returns the number of input items success‐fully matched and assigned. So when you type something from the keyboard, the return value of this function is always 1 in your case (you try to input the string, then every character from the keyboard is added to your string).
You can use fgets then compare with the string that content only the enter character "\n" when you want to quit the loop.
printf("Enter your %s: ", listing[i]);
if (strcmp(fgets(data[i], 51, stdin), "\n") == 0){
done = 1;
break;
}
With this code, if you want to quit the while loop, you just have to hit only ENTER.

C Programming: alternative way of creating a test string and letting the user search for the character within the string vs source code

This lab is trying to show the use of coder-defined functions to execute the code, but I'm trying to do it alternatively so when we actually are tested on it I won't be freaking out that I just copied the source code.
#define NotFound -1
#define WordSize 20
int stringSearch(char * string, char array, int * letter);
int main(void)
{
char * string = (char *) malloc(WordSize * sizeof(char));
char tester = '\0';
int index_tester = 0, i;
// do
// {
// printf("Enter a test string and character, enter q for the test string to exit.\n");
// printf("Test string: ");
// scanf("%s", string);
// while (getchar() != '\n') {}
// if (strcmp(string, "q") == 0) {
// break;
// }
// } // ----> Is it possible to do a while or for look instead? loop here?
printf("What is the test string you wish to enter: ?");
for (i = 0; i < sizeof(string); i++)
{
{
scanf("%c", &string[i]);
}
}
string[i] = '\0';
puts(string);
printf("Tester for the inputed string: ");
scanf("%c", &tester);
while (getchar() != '\n') {}
int ResultofSearch = stringSearch(string, tester, &index_tester);
if (ResultofSearch == NotFound)
{
printf("That letter is not foudn in the string, try again: ");
}
else {
printf("Character found at index %d.\n\n", index_tester);
}
return 0;
}
int stringSearch(char * string, char array, int * letter)
{
for (int i = 0; i < strlen(string); i++)
{
if (string[i] == array)
{
*letter = i;
return (Found);
}
}
return(NotFound);
}
When executing the code, I can put in the string, which I think is working fine, but it will automatically put in the search for some random letters immediately without prompting for the user input. I'm still a greenhorn to all this coding stuff so sorry in advance, any advice would be appreciated though
Apart from the issues pointed out in the comments there is some things you should improve:
char * string = (char *) malloc(WordSize * sizeof(char)); is the same as char * string = malloc(WordSize), but for a 20 word string we will need char * string = malloc(WordSize + 1)
This part of the code:
for (i = 0; i < Wordsize; i++) // already corrected
{
{
scanf("%c", &string[i]);
}
}
string[i] = '\0';
This will obligate you to always have a 19 character string. The cycle will not end until you do (you replace the 20th character with the null-terminator).
You can replace the whole thing with:
fgets(string, WordSize + 1, stdin);
And for good measure, discard the extra characters when the input is too big to fit the string.
int c;
while((c = fgetc(stdin)) !='\n' && c =! EOF); //discard until newline, for completion check for EOF return
This will allow a 20 character max size string but also for smaller ones.
Working sample
You should add required headers, use fgets() rather than scanf() and set tester_index to -1 rather than 0 which means found at index 0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Found 1
#define NotFound 0
#define WordSize 20
int stringSearch(char * string, char array, int * letter);
int main(void)
{
char * string = (char *) malloc(WordSize * sizeof(char));
//char tester = '\0';
char tester[2] = {'\0', '\0'};
int index_tester = -1; // 0 means found # index 0
/* (...) */
printf("What is the test string you wish to enter: ?\n");
fgets(string, WordSize, stdin);
if (string[WordSize-1]=='\n')
string[WordSize-1]='\0';
puts(string);
printf("Tester for the inputed string: \n");
while (getchar() != '\n') {}
///scanf("%c", &tester[0]);
fgets(tester, 2, stdin);
int ResultofSearch = stringSearch(string, tester[0], &index_tester);
if (ResultofSearch == NotFound)
{
printf("That letter is not found in the string.\n");
}
else {
printf("Character found at index %d.\n\n", index_tester);
}
return 0;
}
int stringSearch(char * string, char c, int * index)
{ ... }
It's definitely not perfect but works more less expected way.

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.

C Program Looping Incorrectly

I'm just a beginner and I'm trying to use whatever I know to make a simple program that:
Asks the user to input the letter 'S' or 's'. The program loops if 's' is not input. If the user does input 's', the program then
Asks the user to input a number, 1 or 2. The program loops if the incorrect number is input.
The problem I'm having is that after 's' is successfully input and the user is asked to enter a number, if an incorrect number is input (not 1 or 2) the program asks the user to input a letter again from the beginning which is incorrect. The program loops from the very beginning and doesn't work anymore. Can anyone help me fix this please?
#include <stdio.h>
#include <ctype.h>
int function(int num);
int main()
{
char input,ch,temp,c[64],exit;
int i,invalid,num,index,flag,day;
invalid = 0;
num = 0;
size_t length = 0;
index = 0;
flag = 0;
do
{
puts("Enter the letter S to start the program:");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
{
if(isalpha(input)==0)
{
printf("Invalid input. Please input something.\n");
continue;
}
if(input == 'S' || input == 's')
{
printf("\nProgram start.");
while( sscanf(c, "%d", &num) != 1)
{
length = 0;
flag = 0;
num = 0;
printf("\nEnter 1 for Module A. Enter 2 for Module B. Enter here: ");
fgets(c, 63, stdin);
length = strlen(c);
for(index = 0; index < length; ++index)
{
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
}
if( flag)
{
printf("\nInvalid character\n");
continue;
}
if( sscanf(c, "%d", &num) != 1)
{
printf("\nNo input detected.");
continue;
}
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
}
}
else
{
printf("\nInvalid input.");
continue;
}
}
}
while(1);
}
Make the scanf into like this.
scanf(" %c",&input);
Then While getting the input from the user using fgets It will place the new line character into that buffer. So this will lead to fails this condition.
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
So make the this condition into like this.
length=strlen(c)-1;// to skip the new line character
Or else to like this.
length=strlen(c);
if ( c[length] == '\n' )
c[length]='\0';
Output After placing this,
Enter the letter S to start the program:
S
Program start.
Enter 1 for Module A. Enter 2 for Module B. Enter here: 1
Module A Selected.
Make this in you code.
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
else if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
else
{
printf("\nInvalid option\n");
c[0]='\0'; // It is for satisfy the second while loop condition.
continue;
}
Note that the loop:
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
is limited to the one line by the semicolon at the end. The following code is not the body of the loop, despite indentation trying to pretend that it is.
Also note that getchar() returns an int, not a char; you cannot reliably assign the result to a char and then test it for EOF. Depending on the platform, you will either never detect EOF at all or you will misdetect EOF when some other character (often ÿ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS) is typed. You must use int ch;.
Here. I fixed the problem using the following code. This way the code does the following:
Scans letters 'S' or 's'. Keeps looping if these are not entered.
Scans either number 1 or 2. Keeps looping until either number is entered and then exits.
The program does not loop from the very beginning (by outputting "Enter 'S' to start program), if any number other than 1 or 2 in entered in part 2 of the program. This was the problem originally.
The following is the correct code:
#include <stdio.h>
#include <ctype.h>
int function();
char input,temp,c[64],ch,exit;
int i,invalid,num,index,flag,start;
start = 0;
invalid = 0;
num = 0;
size_t length = 0;
index = 0;
flag = 0;
int main()
{
do
{
puts("Enter the letter S to start the program: ");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
{
if(isalpha(input)==0)
{
printf("Invalid input. Please input something.\n");
continue;
}
if(input == 'S' || input == 's')
{
printf("\nProgram start.");
start = 1;
if(start == 1)
{
function();
return(0);
}
}
else
{
printf("\nInvalid input.");
continue;
}
}
}
while(1);
}
int function()
{
while( sscanf(c, "%d", &num) != 1)
{
length = 0;
flag = 0;
num = 0;
printf("\nEnter 1 for Module A. Enter 2 for Module B. Enter here: ");
fgets(c, 63, stdin);
length = strlen(c);
length --;
for(index = 0; index < length; ++index)
{
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
}
if( flag)
{
printf("\nInvalid character\n");
continue;
}
if( sscanf(c, "%d", &num) != 1)
{
printf("\nNo input detected.");
continue;
}
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
else if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
else
{
printf("\nInvalid option\n");
c[0]='\0'; // It is for satisfy the second while loop condition.
continue;
}
}
}

Resources