I'm making a multi-feature command-line application where users have features like encrypt-decrypt a string, check string palindrome and reverse a string, and I started to write my whole code with the encrypt-decrypt feature, but apparently it is not working as expected, sometimes it encrypts/decrypts the string, the same code when executed again exits itself without taking the string input! I have even inserted the fflush(stdin), but no luck!
#include <stdio.h>
void encryptDecrypt();
// void checkPalindrome();
// void reverseWord();
void main()
{
int choice;
printf("\nWelcome to Jeel's multi-feature C App\n\n");
printf("1. Encrypt-Decrypt a word\t2. Check Palindrome\t3. Reverse a word\n\n");
printf("Enter a feature: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
fflush(stdin);
encryptDecrypt();
break;
case 2:
// checkPalindrome();
break;
case 3:
// reverseWord();
break;
default:
break;
}
}
void encryptDecrypt()
{
fflush(stdin);
char eOrD;
printf("\nWelcome to the World of Encryption & Decryption! We're so glad that you're here!\n\n");
printf("Enter 'e' if you want to encrypt a word or 'd' if you want to decrypt a word (e/d): ");
scanf("%c", &eOrD);
if (eOrD == 'e' || eOrD == 'E')
{
fflush(stdin);
char *word;
printf("\nGreat! Now enter a word to encrypt it: ");
fflush(stdin);
gets(word);
char *ptr = word;
for (int i = 0; i < sizeof(ptr); i++)
{
if (*ptr != '\0')
{
*ptr = *ptr + 7;
ptr++;
}
}
printf("\nEncrypted string is: %s, which is encrypted with the key: %d", word, 7);
}
else if (eOrD == 'd' || eOrD == 'D')
{
fflush(stdin);
char *deWord;
printf("\nGreat! Now enter a word to decrypt it: ");
gets(deWord);
char *dePtr = deWord;
for (int i = 0; i < sizeof(dePtr); i++)
{
if (*dePtr != '\0')
{
*dePtr = *dePtr - 7;
dePtr++;
}
}
printf("\nDecrypted string is: %s, which is decrypted with the key: %d\n", deWord, 7);
}
else
{
printf("Invalid input! Please try again!");
}
}
The best and most portable way to clear the stdin is using this:
void clearStream()
{
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
}
Also the following is incorrect, create an array instead of the pointer:
char *word;
gets(word); //word is a pointer, gets will not create a block of memory for it
Related
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
}
}
I am trying to get 4 integers from an IP-address. For example, 12.34.56.78. A = 12, b = 34, c = 56, and d = 78. Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ADDRESS[100];
printf("Enter IP: ");
scanf("%s", ADDRESS);
return 0;
}
How would I be able to do this?
try to use good old sscanf().
int A, B, C, D;
sscanf(ADDRESS, "%d.%d.%d.%d", &A, &B, &C, &D);
It may be a good idea to check if sscanf() returned 4 what indicates that all four numbers were correctly parsed.
if you're asked to read it as a string at first , you need to add a condition that it exists 4 points in the string
do {
count=0;
for (i=0;i<strlen(address);i++) {
if (address[i] == '.')
count++;
}
if (count > 4) {
printf("Enter IP: ");
scanf("%s", ADDRESS); }
while (!(count <= 4));
secondly using strtok can make everything easy , you have to split your string with the . caracter so it goes with something like this
char *tester;
int counter=0,a,b,c,d;
tester = strtok(address, ".");
while( tester != NULL ) {
switch (counter) {
case 0:
a=atoi(tester);
counter++;
break;
case 1:
b=atoi(tester);
counter++;
break;
case 2 :
c=atoi(tester);
counter++;
break;
case 3:
d=atoi(tester);
counter++;
break; }
tester= strtok(NULL, ".");
}
Program question is:
Write a C program to find and replace the character in the word.
Here flag('A'/'F') indicates whether all occurrences has to be replaced or only the first occurrence has to be replaced.
I have written this code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void cond(char *a,int n,char k,char l,char m)
{
printf("The word is\n");
int i,count=0,max=0;
switch(m)
{
case 'A':
for(i=0;i<n;i++)
{
if(a[i]==k)
{
a[i]=l;
count++;
}
}
if(count==0)
{
printf("No such character present in the word.");
}
else
for(i=0;i<n;i++)
{
printf("%c",a[i]);
}
break;
case 'F':
for(i=0;i<n;i++)
{
while(max<1)
{
if(a[i]==k)
{
a[i]=l;
max++;
}
}
}
if(max==0)
{
printf("No such character present in the word.");
}
else
for(i=0;i<n;i++)
{
printf("%c",a[i]);
}
break;
}
}
int main()
{
char a[20],b,e,p;
printf("Enter the word:\n");
scanf("%s",a);
printf("Enter the character to be find:\n");
scanf("%c\n",&b);
printf("Enter the character to be replaced:\n");
scanf("%c\n",&e);
printf("Enter the 'A'/'F':\n");
scanf("%c\n",&p);
int n=strlen(a);
cond(a,n,b,e,p);
return 0;
}
It does not give any output
For example:
If I input this
Enter the word: aeroplane
Enter the character to be find:a
Enter the character to be replaced:z
Enter the 'A'/'F': A
The word is
It gives a blank output
someone, please help me for this code.
Since a is of type char*, a[i] is a char. k is a char too, thus you can simply compare them like this:
if(a[i] == k)
Moreover your scnafs' use the newline, discard it. Change this:
scanf("%c\n",&b);
to this:
scanf(" %c",&b);
where you should notice I left a space before %c, in order to eat a pending character (I have an example here).
If you test your functions it is better to create some test cases and avoid user input. This can be added later when you are sure that your function works.
Example (I do not know what n means in your example as you even do not declare it in your main :)
int s_replace(char *haystack, char needle, char replace, char flag) // a/A only first - any other complete
{
int result = 0;
if (haystack == NULL) result = -1;
if (!result)
{
while (*haystack)
{
if (*haystack == needle)
{
*haystack = replace;
if (!(result++) && tolower(flag) == 'a')
{
break;
}
}
haystack++;
}
}
return result;
}
int main()
{
int result;
char test[] = "Program question is: Write a C program to find and replace the character in the word. Here flag('A'/'F') indicates whether all occurrences has to be replaced or only the first occurrence has to be replaced.";
printf("Original string = \"%s\"\n", test);
result = s_replace(test, 'a', 'z', 'A');
switch (result)
{
case -1:
printf("Error !!!!!\n");
break;
case 0:
printf("Nothing was found. \n");
break;
default:
printf("Amended string = \"%s\"\n", test);
printf("Number of changes - %d\n", result);
}
return 0;
}
I would appreciate some help with this. I'm trying to create this simple program that repeatedly loops asking for the user to enter in an int. If he enters an int, it exits but if he enters something else or bigger than int (ex.4gs4r33) it will loop again asking to enter an int. This is what I have tried, and it's not working. It says it's an int even if it's not.
#include<stdio.h>
unsigned int findInt();
int main() {
printf("Please input an int.\n");
findInt();
}
unsigned int findInt() {
char input;
long num = 0;
int b = 0;
do {
scanf("%c", &input);
if (isdigit(input)){
num = num*10+input+'0';
b = 1;
}
else if (input == '\n')
b = 1;
else
b = 0;
} while(input != '\n');
if (b == 1)
printf("Great!\n");
else{
printf("Not an int \n");
findInt();
}
return 0;
}
Two possible approaches. One would be to modify your code:
b = 1; // start off with good intentions…
do {
scanf("%c", &input);
if (isdigit(input)){
num = num*10+input -'0'; // *** SUBTRACT '0', don't add it!
}
else if (input != '\n') {
b = 0;
break; // *** break when you find non-digit
}
} while (input != '\n');
Two changes: getting the math right as you compute the integer, and fixing the logic (so you break out of your loop when you find a non digit character)
Second approach:
char buf[100];
char intAsString[100];
fgets(buf, 100, stdin);
sscanf(buf, "%d", num);
sprintf(intAsString, "%d\n", num);;
if(strcmp(buf, intAsString) == 0 ) {
printf("yay - you entered an integer!\n");
}
I'm sure you can figure out how that works.
update a complete code snippet that solves the issue of "loop logic" as well: you call the findInt function once from the top level, and it keeps going until you get the int. Note - in order for this to work properly, I read the entire input at once (rather than one at a time), then pick off the characters one by one using sscanf (and updating the pointer manually). It has a number of advantages - not least of which is that you start with a fresh input every time you call findInt, instead of having the rest of the input buffer that still needs reading (and which was giving rise to "no,no,no,great!" - as you would keep reading the bad input until you got to the newline, and accept that...)
#include<stdio.h>
#include <ctype.h>
unsigned int findInt();
int main() {
findInt();
}
unsigned int findInt() {
char input;
char buf[100];
char *temp;
long num = 0;
int b = 0;
printf("please enter an int:\n");
fgets(buf, 100, stdin);
temp = buf;
do {
sscanf(temp++, "%c", &input);
if (isdigit(input)){
num = num*10+input-'0';
b = 1;
}
else if (input == '\n')
{
b = 1;
break;
}
else {
b = 0;
break;
}
} while(input != '\n');
if (b == 1)
printf("Great! %d is an integer!\n", num);
else{
printf("Not an int \n");
findInt();
}
return 0;
}
In the else branch - i.e. not a digit or a newline - you set b to 0. Now if a digit DOES follow you reset that to 1.
You'll probably want to break or somehow record the permanent failure instead of just continuing.
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
void findInt(){
int x;
bool ok;
do{
char buff[32], *endp;
long long num;
ok = true;//start true(OK)
printf("Enter a number: ");
fgets(buff, sizeof(buff), stdin);
//strtoll : C99
x=(int)(num=strtoll(buff, &endp, 0));//0: number literal of C. 10 : decimal number.
if(*endp != '\n'){
if(*endp == '\0'){
printf("Too large!\n");//buffer over
while('\n'!=getchar());
} else {
printf("Character that can't be interpreted as a number has been entered.\n");
printf("%s", buff);
printf("%*s^\n", (int)(endp - buff), "");
}
ok = false;
} else if(num > INT_MAX){
printf("Too large!\n");
ok = false;
} else if(num < INT_MIN){
printf("Too small!\n");
ok = false;
}
}while(!ok);
}
,
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);