I want the program to accept only upper and lower case letters, and if the user enters any numbers or symbols other than upper and lower case letters, the system will stop accepting characters and output the result backwards. I am use isalpha() on my code.
Here is my code.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char users_enter[21]; // set an character variables that include 21 characters
int str_length = 0; // set the length of string is 0
printf("Please print the string: \n");
scanf("%20s",users_enter); // accept character
for(int index = 0; index < 20; index++) { // set the index of elements of string is 0
if(isalpha(users_enter[index]) == 0) { // is character is num will return 0
str_length = strlen(users_enter); // find the length of current string
break; // stop loop
}
}
for(int len = str_length-1; len >= 0; len--) {
printf("%c",users_enter[len]); // print
}
printf("\n");
return 0;
}
The test result is :
Please print the string:
str5y
y5rts
my program did not stop when I enter 5.
The expected result should be rts.
How to modify my code?
Thank you
Instead of getting the length of the whole string, save the current index.
if(isalpha(users_enter[index]) == 0) { // is character is num will return 0
str_length = index; // find the length of current string
break; // stop loop
}
This way when you find an undesired character, you will have the length of the string just before that character.
You could also get input character by character and stop when you encounter a number.
Sidenote:
Check the return value of scanf(), so that you can exit if you encounter a conversion error while getting input.
Related
I am currently on a beginner course in C and was given an exercise requiring my program to check if the user input contains non-alphabets. I've figured to use the function isalpha() to check the user input and if it contains non-alphabets, the program should ask the user to enter another input.
Below is my current code:
#include <stdio.h>
#include <ctype.h>
#define MAX 13
int main() {
char player1[MAX];
int k = 0;
// Ask player 1 to type a word.
printf("Player 1, enter a word of no more than 12 letters: \n");
fgets(player1, MAX, stdin);
// // Loop over the word entered by player1
for (int i = 0; i < player1[i]; i++) {
// if any chars looped through is not an alphabet, print message.
if (isalpha((unsigned char)player1[i]) == 0) {
printf("Sorry, the word must contain only English letters.");
}
}
However, after testing it, I've derived a few cases from its results.
Case 1:
Entering without any input prints ("Sorry, the word must contain only English letters. ")
Case 2:
An input with 1 non-alphabetic character prints the 'sorry' message twice. Additionally, an input with 2 non-alphabetic characters print the 'sorry' message thrice. This implies that case 1 is true, since no input prints the message once, then adding a non-alphabetic prints the message twice.
Case 3:
An input of less than 10 characters(all alphabetic) prints out the sorry message also.
Case 4:
An input of more than 9 characters(all alphabetic) does not print out the sorry message, which satisfies my requirements.
Why are these the cases? I only require the message to print once if after looping through the user input, there's found to be a non-alphabetic character!
As #unwind has noted, the conditional of the OP for() loop is incorrect.
Good to trust to isalpha() but your code doesn't have to fondle each and every character. Another standard library function, strspn(), when supplied with your needs, can perform the looping work for you.
#include <stdio.h>
#include <string.h>
#define MAX 12
int main() {
char player1[ MAX + 1 + 1 ]; // buffer size for fgets() 12 + '\n' + '\0'
char *permissible =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Ask player 1 to type a word.
printf("Player 1, enter a word of no more than %d letters: \n", MAX);
fgets(player1, sizeof player1, stdin);
if( player1[ strspn( player1, permissible ) ] != '\n' )
printf("Sorry, the word must contain only English letters.");
return 0;
}
Strings in C are null-terminated, which means they contains an extra byte '\0' to mark the end of the string (character 0 in the ascii table), so you can only store 12 characters in a char array of size 13.
If you array contains a string smaller than 12 characters, since you loop over the whole array, you'll meet that null-terminating-byte, which fails isalpha(): it checks if character is in range ['A', 'Z'] or ['a', 'z']. Characters are just integers for your computers, so isalpha() checks if received value is is range [65, 90] or [97, 122], and 0 is not.
To be more precise, the notion of integer makes no sense for your computer, that's just how we interpret information, it's just a bunch of bits for your computer.
See ascii table: https://www.rapidtables.com/code/text/ascii-table.html
By having a fixed size buffer, you'll have garbage after the contained string if the string doesn't take all the space.
You have 2 conditions to stop iterating:
end of array, to prevent overflowing the array
end of string, to prevent mis-interpreting bytes in array which are further than string end
Error message might be printed several times, since you keep checking even after an error occured, you have to break the loop.
Below code doesn't meet mentioned problems
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define BUFFER_SIZE 13
#define MIN(a, b) (a < b ? a : b)
int main(void)
{
char player1[BUFFER_SIZE];
int maxIndex;
int i;
/* Ask player 1 to type a word */
printf("Player 1, enter a word of no more than 12 letters: \n");
fgets(player1, BUFFER_SIZE, stdin);
/*
* Max index for iteration, if string is lesser than 12 characters
* (excluding null-terminating byte '\0') stop on string end, otherwise
* loop over whole array
*/
maxIndex = MIN(strlen(player1) - 1, BUFFER_SIZE);
for (i = 0; i < maxIndex; i++) {
/* Print error if non-letters were entered */
if (isalpha(player1[i]) == 0) {
printf("Sorry, the word must contain only English letters.");
/* Error occured, no need to check further */
break;
}
}
/*
for (i = 0; i < maxIndex; i++)
printf("%d ", (int) player1[i]);
printf("\n%s\n", player1);*/
return 0;
}
The MIN() is a macro, a ternary expression which returns the smallest argument, nothing really complicated here.
But note that, when you enter the word, you press <Enter>, so your string contains a "go to next line" character (character '\n', n°10 in ascii table, as #Shawn mentioned in comments), so you have to stop before it: that's why I use strlen(player) - 1, string ends with "\n\0", and strlen() returns the number of bytes before '\0' (including '\n').
I've let a dump of the string at the end, you can modify the end-index there to see what's sent to isalpha(), replace maxIndex with BUFFER_SIZE.
This:
for (int i = 0; i < player1[i]; i++) {
loops from 0 up until (but not including) the code point value of the i:th character, updating i every time it loops. It will very likely access outside the array bounds, which is undefined behavior.
It should look for the terminator (or linefeed but let's keep it simple):
for (size_t i = 0; player1[i] != '\0'; ++i) {
to use the function isalpha() to check the user input and if it contains non-alphabets
Simply read one character at a time. No maximum needed.
#include <ctype.h>
#include <stdio.h>
int main(void) {
int ch;
int all_alpha = 1;
printf("Player 1, enter a line\n");
while ((ch = getchar()) != '\n' && ch != EOF) {
if (!isalpha(ch) {
all_alpha = 0;
}
}
if (!all_alpha) {
printf("Sorry, the line must contain only letters.");
}
}
I'm writing a code in C to find the digits that repeat in a given number, and the one that I wrote works fine for small numbers, but the output gets messed up if I input a large value, N < 1000.
Here is my code; please help me out!
For the input:
1839138012980192380192381090981839
I get this output:
0 2 3 5 7 8
#include <stdio.h>
int main()
{
int digit, digits[10], flag = 0, i;
long long num;
scanf("%lld", &num);
while (num)
{
digit = num % 10;
if (digits[digit])
flag = 1;
digits[digit]++;
num /= 10;
}
if (flag)
{
for (i = 0; i < 10; i++)
{
if (digits[i] > 1)
printf("%d ", i);
}
printf("\n");
}
else
printf("The are no repeated digits.\n");
return 0;
}
The long long type can only represent a limited range of numbers. In your C implementation, 1839138012980192380192381090981839 is too big for long long, and scanf("%lld", &num) does not work.
Instead, read each character of input using c = getchar();, where c is declared as an int. If, after getchar, c is EOF, stop looping and print the results. If c is not EOF, then check whether it is a digit using if (isdigit((unsigned char) c)). The isdigit function is defined in <ctype.h>, so include that header.
If the character is a digit, then convert it from a character to the number it represents using c - '0'. You can use int d = c - '0'; to store the number in d. Then increment the count for the digit d.
If the character is not a digit, you can decide what to do:
There will likely be a new-line character, '\n', at the end of the line the user entered. You may want to ignore it. When you see the new-line, you could end the loop and print the results, you could continue reading to see if there are any other digits or characters before EOF is seen and report a problem to the user if there are, or you could ignore it and continue looping.
There could be spaces in the input. You might want to ignore them, or you might want to report a problem to the user.
If there are other characters, you might want to report a problem to the user.
Here's another approach, which you could use with a string of some maximum length (defined by the constant MAX_LEN).
A string made up of a bunch of char will use one byte per character, so you can define MAX_LEN up to how many bytes you have in system memory, generally, although in practice you probably would use a much smaller and more reasonable number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 12345
int main()
{
int digit, digits_checker[10] = {0}, flag = 0, i;
char* num;
/* set aside space for the string and its terminator */
num = malloc(MAX_LEN + 1);
/* read num from input */
scanf("%s", num);
/* get the string length */
size_t num_length = strlen(num);
/* walk over every character in num */
for (size_t position = 0; position < num_length; position++)
{
/*
We assume that the value of num[position] is an
ASCII character, from '0' to '9'. (If you can't make
that assumption, check the input and quit with an
error, if a non-digit character is found.)
If the input is valid, the digits 0-9 in the ASCII
table start at 48 ('0') and end at 57 ('9'). Subtracting
48, therefore, gives you the integer value at each digit
in num.
*/
digit = num[position] - 48;
/*
Increment a counter for each digit
*/
digits_checker[digit]++;
}
/* num is no longer needed, so we free its memory */
free(num);
/* check each digit */
for (i = 0; i < 10; i++)
{
if (digits_checker[i] > 1) {
printf("%d ", i);
flag = 1;
}
}
if (!flag) {
printf("The are no repeated digits.\n");
}
else {
printf("\n");
}
return 0;
}
The suggestion to check input is a good one. You can't necessarily assume that what someone enters will be entirely made up of digit characters.
But hopefully this demonstrates how to set aside space for a string, and how to read through it, one character at a time.
I mixed up two programs in the cs50 sandbox, one was to find the the number of characters in an array and other was the print these characters. I know the program is garbage but could anyone explain me what is the compiler doing here?
When I ran this, the output starts printing alphanumeric text and never stops Thanks
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
int n = 0;
while (strlen(s) != '\0')
{
n++;
printf("%c", n);
}
}
You have multiple problems with the code you show, here's a couple of them:
strlen(s) will never be zero as you never modify or remove characters from the string, which means you have an infinite loop
n is an integer and not a character so should be printed with the %d format specifier
'\0' is (semantically) a character, representing the string terminator, it's not (semantically) the value 0
To fix the first problem I suspect you want to iterate over every character in the string? Then that could be done with e.g.
for (int i = 0; i < strlen(s); ++i)
{
printf("Current character is '%c'\n", s[i]);
}
But if all you want is to could the number of characters in the string, then that's what strlen is already gives you:
printf("The number of characters in the string is %zu\n", strlen(s));
If you want to count the length of the string without using strlen then you need to modify the loop to loop until you hit the terminator:
for (n = 0; s[n] != '\0'; ++n)
{
// Empty
}
// Here the value of n is the number of characters in the string s
All of this should be easy to figure out by reading any decent beginners book.
while (strlen(s) != '\0') is wrong. '\0' equals 0. There string length is never 0, so the loop keeps going on forever, printing integers interpreted as characters.
You can either use the indexes to go through the string characters by using the variable "n" or you can increment the pointer of the string that you have received from the standard input to go through all of its characters.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
/* First way using n to iterate */
int n = 0;
for (n = 0; n < strlen(s); ++n)
{
printf("%c", s[n]);
}
printf("\n");
/* Second way increment the string pointer*/
while (strlen(s) != '\0')
{
printf("%c", *s); //print the value of s
s++; // go to the next character from s
}
printf("\n");
return 0;
}
#include "stdafx.h"
#include "stdlib.h"
#include <ctype.h>
int num = 0;
int i = 0;
int ch = 0;
int letter_index_in_alphabet(int ch) {
if (isalpha(ch) == true) {
char temp_str[2] = { ch };
num = strtol(temp_str, NULL, 36) - 9;
printf("%d is a letter, with %d as its location in the alphabet!", ch, num);
}
else {
return -1;
}
}
int main()
{
char input_str[10];
printf("Please enter a series of up to 10 letters and numbers: \n");
fgets(input_str, 10, stdin);
for (i == 0; i <= 10; i++) {
ch = input_str[i];
letter_index_in_alphabet(ch);
}
return 0;
}
Hello everyone, this is my first post on SOF! The goal of this program is to read characters from the standard input to EOF. For each character, report if it is a letter. If it is a letter, print out its respective index in the alphabet ('a' or 'A' = 1, 'b' or 'B' = 2..etc). I have been searching some other posts on stackoverflow and this has helped me get this far(using fgets and strtol functions). I have no visible syntax errors when I run this code, but after I enter a string of characters (ex: 567gh3fr) the program crashes.
Basically, I am trying to use 'fgets' to bring each character entered into a string with the appropriate index. Once I have that string, I check each index for a letter and if it is, I print the number assigned to that letter of the alphabet.
Any help or insight into why this isn't working as intended is greatly appreciated, Thanks!
You have a few problems.
First, char input_str[10] is only big enough for the user to enter 9 characters, not 10, because you need to allow one character for the null byte that ends a string.
Second, your loop goes too far. For a string with 10 characters, indexes go up to 9, not 10. It also should stop when it gets to the null byte, since the user might not have entered all 9 characters.
To get the position in the alphabet, you can simply subtract the value of A or a from the value of the character. Use tolower() or toupper() to convert the character to the case that you're going to use. Your method works, but it's overly complicated and confusing.
letter_index_in_alphabet() is declared to return int. But when the character is a letter, it doesn't execute a return statement. I'm not sure why it's supposed to return something, since you never use the return value, but I've changed it to return the position (maybe the caller should be the one that prints the message, so the function just does the calculation).
In the for loop, it should be i = 0 to perform an assignment, not i == 0 which is comparison.
You also shouldn't use global variables so much. And system header files should have <> around them, not "".
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int letter_index_in_alphabet(int ch) {
if (isalpha(ch)) {
int num = tolower(ch) - 'a' + 1;
printf("%d is a letter, with %d as its location in the alphabet!\n", ch, num);
return num;
} else {
return -1;
}
}
int main()
{
char input_str[10];
printf("Please enter a series of up to 9 letters and numbers: \n");
fgets(input_str, sizeof(input_str), stdin);
for (int i = 0; input_str[i]; i++) {
letter_index_in_alphabet(input_str[i]);
}
return 0;
}
I am studying C but am stuck on a program I've been trying to create. Essentially I'm testing to see if a character string only contains alphabetic characters a-z or A-Z.
What I have done:
defined a function called strisalpha to do this
called the function in my "test bench", which asks the user to enter a string
What goes wrong in the gcc compiler:
testBench1.c:21:28: warning: implicit declaration of function 'atoi' [-Wimplicit-function-declaration]
integerCharValue = atoi( string[loopPointer1] );
This is my definition of strisalpha:
int strisalpha(char *string)
{
int stringLength = 0;
int loopPointer1 = 0;
int integerCharValue = 0;
int dummyArgument = 0;
/* Get length of string */
stringLength = strlen (string);
printf("\nString length is: %d", stringLength);
/* ASCII Codes In Decimal */
A (65Decimal) to Z(90Decimal) and
a (97Decimal) to z (122Decimal)
Set up a loop and query if ASCII alphabetic character
*/
for (loopPointer1 = 1; loopPointer1 > stringLength; loopPointer1++ )
{
/* Convert character to integer */
integerCharValue = atoi( string[loopPointer1] );
printf ("%d \n", integerCharValue);
if (integerCharValue >= 65)
if (integerCharValue <= 90)
return 1; /* Upper case alphabetic character, so OK */
else if (integerCharValue >= 97)
if (integerCharValue <= 122)
return 1; /* Lower case alphabetic character, so OK */
else
The result always says I entered an ASCII character, even if I didn't. Please could someone shed some light on what I'm doing wrong? Thanks
The main problem is your for loop
for (loopPointer1 = 1; loopPointer1 > stringLength; loopPointer1++ )
Arrays in C start at 0 and the middle section defines if the loop should continue not finish. So what you want is:
for (loopPointer1 = 0; loopPointer1 < stringLength; loopPointer1++ )
And then for checking each character you don't need to do anything to them as you can compare characters like this for example
if (string[loopPointer] >= 'A')
atoi isn't what you want to use here. chars are already stored as numeric ASCII values. You can just set integerCharValue = string[loopPointer1].
Your loopPointer1 is starting at 1, so you will skip the first character in the string. In C, the index starts at 0.
Also, you don't want to return immediately if you find a letter. Calling return will exit the function and stop your loop. What you probably want to do is look for characters that are not letters, and return 0 if you find one. Then, if you make it to the end of the loop, you can return 1 because you know you didn't find any characters that weren't letters.
Here is a one-liner function that evaluates to 1 if the string only contains alphabetic characters, and 0 otherwise:
#include <string.h>
int strisalpha(const char *str) {
return str[strspn(str, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ")] == '\0';
}
And here is a more classic approach with isalpha():
#include <ctype.h>
int strisalpha(const char *str) {
while (*str) {
if (!isalpha((unsigned char)*str++)
return 0;
}
return 1;
}