How to reset this string scanning code for a new letter? - c

I'm in the middle of homework and nearly finish. This is my code
#include <stdio.h>
#include <stdlib.h>
void main()
{
char word[100],*ptr,input;
int count,i,n;
printf("Enter the word : ");
scanf("%[^\n]", word);
ptr = &word;
do
{
printf("Enter the letter : ");
scanf(" %c", &input);
if(input == '-'){
printf("Exit.");
return 0;
}
for(i=0;word[i] != '\0';i++)
{
if(*ptr == input)
count++;
ptr++;
}
printf("Has %d of '%c'",count,input);
printf("\n");
}while(input != '-')
}
This code will extract the number of letter in string
For example : If you input "WWWWooo" it will give you "has 4 of 'W'" and "has 3 of 'o'"
Code will exit when you put '-' letter.
Problem that I find is the 'count' value seems to remain the total of number of the first letter I want to find.
What I expect : "WWWWooo" will give "has 4 of 'W'" and "has 3 of 'o'"
What I get is "has 4 of 'W'" and "has 4 of 'o'". The count value didn't reset.
I tried to put count = 0; on the top of do while loop and the output will always be 0 for the second letter scanned for.
How can I fix this?

I changed your code a bit, I guess this is what you're looking for (the comments in the code explain pretty much all the changes I've made):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char word[100],*ptr,input;
int count,i,n;
printf("Enter the word : ");
scanf("%99[^\n]", word); //changed to %99[^\n] to avoid buffer overflows
do
{
count=0; //count=0 should be here as count++ changes the value of count afterwards
ptr=word; //ptr=word should be here too since ptr++ changes the value of ptr afterwards
/* you might have probably gotten a compiler warning because
of ptr=&word, since &word is char(*)[100] (a pointer to an array of 100 chars)
and char(*)[100] and char * are quite different,
so you can either do ptr=word or ptr=&word[0] (both of which point to the first character in the array) */
//the rest of the code below is basically the same
printf("Enter the letter : ");
scanf(" %c", &input);
if(input == '-'){
printf("Exit.");
return 0;
}
for(i=0;word[i] != '\0';i++)
{
if(*ptr == input)
count++;
ptr++;
}
printf("Has %d of '%c'",count,input);
printf("\n");
}while(input != '-'); //you had missed a ';' here
}
The int main(void) is because, quoting n1570 (emphasis mine):
It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ } or with two parameters (referred to here
as argc and argv, though any names may be used, as they are local to
the function in which they are declared): int main(int argc, char
*argv[]) { /* ... */ } or equivalent
Even though I haven't checked the return value of scanf() in the above code, but as mentioned by #Yunnosch in the comment, it's always a good idea to do so.

Related

scanf() adds character to string

I have this code and it keeps adding what ever the guesses string is to the wordle string when I compare them, resulting in them to never be the same. How can I fix this?
#include <string.h>
int main() {
char wordle[5];
char guesses[5];
int guess = 5;
int value;
printf("Please input a secret 5 letter word:\n");
scanf("%s",wordle);
while (guess != 0){
printf("You have %d tries, please guess the word\n",guess);
scanf("%s",guesses);
value = strcmp(wordle,guesses);
if (value == 0){
printf("you win\n");
break;
}
guess = guess - 1;
}
return 0;
}```
Your program has undefined behavior. You're making two mistakes.
If your user enters 5 characters, it takes 6 characters to store the string. The program would attempt to write a null terminator into wordle[5] which is not a valid index.
Your user could enter any number of letters. You need to make sure they don't overflow your buffer.
#include <stdio.h>
#include <string.h>
int main() {
char wordle[6];
char guesses[6];
int guess = 5;
int value;
int chars_read;
do {
printf("Please input a secret 5 letter word:\n");
chars_read = scanf("%5s%*s\n", wordle);
} while(chars_read != 1 && strlen(wordle) != 5);
while (guess != 0){
do {
printf("You have %d tries, please guess the word\n", guess);
chars_read = scanf("%5s%*s\n", guesses);
} while(chars_read != 1 && strlen(wordle) != 5);
value = strcmp(wordle, guesses);
if (value == 0){
printf("you win\n");
break;
}
guess = guess - 1;
}
return 0;
}
See it in action
scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s
MSC24-C. Do not use deprecated or obsolescent functions
Your strings for wordle and guesses are too short. You need to make room for '\0'. They should be 6 bytes long not 5.
char wordle[6];
char guesses[6];

Output not showing in C

I'm writing a code that must identify the letter 't' or 'T' in a word, before or after the middle of it.
If the first half of the word does contain a 't' or a 'T', the program should output a 1. If the first half does not contain the letter 't' or 'T', but the second half does, then the program should output a 2. Otherwise, if there is no 't' or 'T' in the word at all, the program's output should be -1. The word entered will not have more than 50 letters.
#include <stdio.h>
#include <string.h>
int main() {
char word[50];
int i = 0, length, t = 0, T = 0;
scanf("%s", word);
length = strlen(word);
t = word[i] == 't';
T = word[i] == 'T';
while(!t || !T) {
if((t || T) && i <= length / 2) {
printf("%d", '1');
} else if((t || T) && i > length / 2) {
printf("%d", '2');
//}else{
// printf("%d", '-1');
}
i++;
}
return 0;
}
If I enter any word and press enter, nothing is printed. Another thing is that when I remove the comment slashes from the two lines at the bottom, the program goes through an infinite loop.
Could someone please help?
This sounds like a school assignment, so I'll focus on advising/critiquing your code rather than giving a solution.
The first recommendation I have is to use a for loop instead of a while loop. A Rule of thumb in C is to only use a while loop when you actually don't have any idea how many things you need your program to look at.
You already have the length of the string, so set up your for loop to loop exactly once for each character.
Next you need to change how you are using printf. The %d format specifier is for printing integers, but you are passing it '1'. This is not an integer, it is the ascii representation of the symbol 1 (which is actually has the value 49, see the ascii table for more info)
You can either pass printf the value 1, or use the %c specifier, which expects ascii characters.
Better yet, just say printf("1");
That doesn't get you all the way there, but I think it lays the ground work so you can find the solution!
Condition !t || !T has no sense to be used as loop condition ...ask yourself how the loop will end ? you need just to check i is less than length
Second, the assignments t = word[i] == 't'; T = word[i] == 'T'; outside the loop have no sense ...you will be just pointing to the zero index of the string ...you should check all characters
third , the printf lines need to use %d
fourth , you appear not getting the purpose of the program printing inside loop will lead to printing many numbers and you just want to know if there is t or T you need to print single line.you may use variable int result=0; to hold the value you want and print it in the end ...of course you will need using break statement in the if((t || T) && i <= length / 2) and if((t || T) && i > length / 2) because no need for more searching
fifth, you should re-read , re-think , re-code the assignment before going bored and asking about it
sixth, there is a working version by modifying your code but you should try writing a good solution before looking at a solution as it better to solve your problems by yourself
#include <stdio.h>
#include <string.h>
int main() {
char word[50];
int i = 0, length, t = 0, T = 0;
scanf("%s", word);
length = strlen(word);
int result=0;
while( i<length) {
t = word[i] == 't';
T = word[i] == 'T';
if((t || T) && i <= length / 2) {
result=1;
break;
} else if((t || T) && i > length / 2) {
result=2;
break;
}else{
result=-1;
}
i++;
}
printf("%d",result);
return 0;
}
# include <stdio.h>
int main()
{
char name[20];
int age;
int siblings;
int childrens;
printf ("Hello my name is A.I, what is your name? \n");
scanf("%s", &name);
printf("how old are you : \n");
scanf("%d",&age);
printf("how many siblings you have: \n");
scanf("%d", &siblings);
printf("how many children you have: \n");
scanf("%d", &childrens);
printf("so your name is : %s \n", name);
printf("and your age is : %d \n", age);
printf("you have siblings : %d\n", siblings);
printf("so you have childrens : %d\n", childrens);
return 0;
}

Making sure the input is a charachter

This might be a rookie question, but I need to make sure that the input given by the user is of data type char [%c] or a string [%s].
If it were an integer, I would just do something like this:
int data, x;
do {
printf("Please enter a number: ");
x = scanf(" %d", &data);
getchar();
} while(x!=1);
So I was wondering if there's a similar way to do this, if the input is supposed to be a string or a character. Thanks, Any help would be appreciated!
Avoid to use %c in scanf() because some unexpected character like \r\n will be input.
You can use a char[2] to receive a single character. An \0 will be filled after your string to represent the end of string, so the length of array must be bigger than 1.
An example:
#include <stdio.h>
int main()
{
char data[2];
scanf("%1s", data);
if (data[0] >= 'a' && data[0] <= 'z') // custom your constraint here
{
// legal
printf("legal: %s", data);
}
else
{
// illegal
printf("illegal: %s", data);
}
return 0;
}
While I input b, the data will be "b\0".
part of the answer is if you just want to read only alphabet you can use below.
#include <stdio.h>
#include <ctype.h>
int main()
{
char ch;
do {
printf("enter a char:");
scanf(" %c",&ch);
}while(!isalpha(ch));
printf("%c",ch);
return 0;
}
Update 1:
Just for the completeness and for the FUN part of the programing, have added code here.
This works well (not tested robustly, you can do if you need to) for the single char input or for a string of length 9.
Remember to type the EOF after input is entered in case length of input is < 9.
and read EOF behavior on same line and new line.
#include <stdio.h>
#include <ctype.h>
#define LEN 10
int main()
{
char ch;
char str[LEN] = {0};
int i = 0;
int ret;
printf("enter a char or string(len = 9) and press EOF if len < 9\n");
do {
if(1== (ret = scanf(" %c",&ch)))
{
if(isalpha(ch))
str[i++] = ch;
}
else
printf("scanf:Error (%d)\n", ret);
}while(ret != EOF && ( !isalpha(ch) || i < LEN-1));
str[i] = '\0';
printf("str is %s\n",str);
return 0;
}

Char array pointer in C

I want to run this code but i can not. i have yet started to learn pointer in C. I am trying to get the addresses of letters. Problem is printf("in adress: %p\n",p[i]);` Thanks
#include <stdio.h>
int main(void){
char letter;
int c=0;
int i;
char pattern[7];
char *p;
printf("Enter a letter: ");
scanf("%c",&letter);
printf("Enter a pattern: ");
scanf("%s",pattern);
p=pattern;
for(i=0;i<7;i++)
{
if(letter==pattern[i])
{
c++;
printf("Letter < %c > is found in pattern %s\n",letter,pattern);
printf("in adress: %p\n",p[i]);
printf("index:%d\n",i);
}
}
if(c==0)
printf("The pattern does not include any letter");
return 0;
}
This line of code has some potential problem that can easily happen
scanf("%s",&pattern);
you can make it a little bit safer like this
scanf("%6s",&pattern);
it's a 6 because you need one extra byte '\0' at the end of the string, which takes us to the next problem
for(i=0;i<7;i++)
here you are assuming that all bytes are non-nul which would be ok except that you are reading a string with scanf() and unless you create the array one byte bigger than the number of characters you want to store in it, scanf() will overflow the array i.e. write a byte beyond it's bounds.
Adding the "%6s" length specifier to the format string solves this, but you can only store 6 non-nul bytes in the array, and for the other problem
for (i = 0 ; pattern[i] != '\0' ; i++)
would be better, because you don't need to know the length of the string in advance and you don't risk reading past the end of the array.
Try this:
#include <stdio.h>
int main(void)
{
char letter;
char c;
int i;
char pattern[7];
printf("Enter a letter: ");
if (scanf(" %c",&letter) != 1)
{
printf("error: invalid input.\n");
return -1;
}
printf("Enter a pattern: ");
if (fgets(pattern, sizeof(pattern), stdin) == NULL)
{
printf("error: end of file.\n");
return -1;
}
for (i = 0 ; pattern[i] != 0 ; ++i)
{
if (letter == pattern[i])
{
c++;
printf("Letter < %c > is found in pattern %s\n", letter, pattern);
printf("in adress: %p\n", pattern + i);
printf("index :%d\n", i);
}
}
if (c == 0)
printf("The pattern does not include any letter");
return 0;
}
You also was printg the address wrong, because in pointer[i] the subscript operator dereferences the pointer, it's equivalent to *(poitner + i).

How to invalidate an input in c

I'm writing a program in C that is suppose to ask the user for a number.
The number has to be greater than zero and cannot have letters before or after the number. (ie: 400 is valid but abc or 400abc or abc400 is not). I can make my program invalidate everything besides 400abc. How would I make it invalidate an input if it starts valid then turns invalid? (I'm about 2 months into an intro to c class so my knowledge is very limited.)
#include<stdio.h>
int check(void);
void clear_input(void);
main()
{
int num;
printf("Please enter a number: ");
num = check();
printf("In Main %d\n", num);
}
int check(void){
int c;
scanf("%d", &c);
while (c < 0){
clear_input();
printf("Invalid, please enter an integer: ");
scanf("%d", &c);
}
return c;
}
void clear_input(void){
char junk;
do{
scanf("%c", &junk);
}while (junk != '\n');
}
You can also check whether ascii value of each char scanned from user input should lie in range 48-57, It will only then be integer value.
strtol can be used to do it, but it takes some extra work.
After running this code:
char *endptr;
int n = strtol(num_text, &endptr, 10);
n will contain the number. But you still have to check that:
1. *endptr=='\0' - this means strtol didn't stop in the middle. In 400abc, endptr will point to abc. You may want to allow trailing whitespace (in this case, check that endptr points to an all-whitespace string.
2. num_text isn't empty. In this case, strtol will return 0, but an empty string isn't a valid number.
Read the input as a line, using fgets.
Check if all characters are numeric.
If not, it's invalid. If yes, use sscanf to get the line into an int.
Check if the int is in the range; you're done.
Scanf with %d will treat the "400abc" as 400, all the trailing characters would be ignored, so there is nothing to worry about.
If you definitely want to treat "400abc" as an invalid input, then maybe you shouldn't use %d in scanf, use %s instead?
One way is to read the whole line as a string and check by yourself if it contains any non-digits.
The other way is reading the integer and then looking into the input using fgetc() to see if the next character after the detected input is valid. Or you could even use the same scanf() for this:
char delim;
if(scanf("%d%c", &c, &delim) == 2 && !isspace(delim))
// the input is invalid
You can read the number in a character array and validate it by checking if all the characters lie in the ascii range 48 to 57 ( '0' to '9' ) .If so your no. is valid otherwise you can safely regard it as invalid input.Here the the demonstration :
#include<stdio.h>
#include<string.h>
int conv( char * word )
{
int ans=0;
int res=0;
for(int i=0;i<strlen(word);i++)
if(word[i]>='0' && word[i]<='9')
ans=(ans*10) + (word[i] - '0');
else
res=-999;
if(res==-999)
return res;
else
return ans;
}
int main()
{
char a[10];
gets(a);
int b=conv(a);
if(b==-999)
printf("Invalid Entry.\n");
else
printf("Success.No is %d.\n",b);
return 0;
}
You can adjust for negatives as well by checking the first character in the word array to be '-' and adjusting the sign accordingly.
This is C99, so compile with -std=c99
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
bool getNum(int *n) {
char c, s[10];
if (!scanf("%9s", s))
return false;
for (int i=0; c=s[i]; i++)
if (!isdigit(c))
return false;
*n = atoi(s);
return true;
}
int main() {
int n;
if (getNum(&n))
printf("you entered %d\n", n);
else
printf("you did not enter a number\n");
}
The following is your check function rewritten to fix your problem, so try this:
int check(void){
int n;
char c;
while (EOF==scanf("%d%c", &n,&c) || n < 0 || !isspace(c)){
clear_input();
printf("Invalid, please enter an integer: ");
}
return n;
}

Resources