I'm new to C and programming. I got stuck at a homework exercise. My output only shows the first character in upper case, and the following characters in some weird numbers. Can someone take a look at my code and give me some tips on what I've done wrong and ways to fix the issue? Your help is greatly appreciated!
"Write a function void sticky(char* word) where word is a single word such as “sticky” or “RANDOM”. sticky() should modify the word to appear with “sticky caps” (http://en.wikipedia.org/wiki/StudlyCaps), that is, the letters must be in alternating cases(upper and lower), starting with upper case for the first letter. For example, “sticky” becomes “StIcKy” and “RANDOM” becomes “RaNdOm”. Watch out for the end of the string, which is denoted by ‘\0’. You can assume that legal strings are given to the sticky() function."
#include <stdio.h>
#include <stdlib.h>
/*converts ch to upper case, assuming it is in lower case currently*/
char toUpperCase(char ch)
{
return ch-'a'+'A';
}
/*converts ch to lower case, assuming it is in upper case currently*/
char toLowerCase(char ch)
{
return ch-'A'+'a';
}
void sticky(char* word){
/*Convert to sticky caps*/
for (int i = 0; i < sizeof(word); i++)
{
if (i % 2 == 0)
{
word[i] = toUpperCase(word[i]);
}
else
{
word[i] = toLowerCase(word[i]);
}
}
}
int main(){
/*Read word from the keyboard using scanf*/
char word[256];
char *input;
input = word;
printf("Please enter a word:\n");
scanf("%s", input);
/*Call sticky*/
sticky(input);
/*Print the new word*/
printf("%s", input);
for (int i = 0; i < sizeof(input); i++)
{
if (input[i] == '\n')
{
input[i] = '\0';
break;
}
}
return 0;
}
you need to use strlen not sizeof to find the length of a char* string
Modify your change upper and change lower function
/*converts ch to upper case,*/
char toUpperCase(char ch)
{
if(ch>='a' && ch<='z')/*If condition just to make sure current letter is in lower case*/
return ch-'a'+'A';
}
/*converts ch to lower case, assuming it is in upper case currently*/
char toLowerCase(char ch)
{
if(ch>='A' && ch<='Z')/*If condition just to make sure current letter is in Upper case*/
return ch-'A'+'a';
}
Also, only four characters are converted since you are using sizeof for finding the string length.sizeof always returns 4(depends upon machine).
use strlen(word) to find the length of string word in following for loop:
for (int i = 0; i < strlen(word); i++)
{
}
You should use strlen instead of sizeof.
Also, you must check whether your letter is already upper or lower case:
for (int i = 0; i < strlen(word); i++)
{
if (i % 2 == 0)
{
if ( isLowerCase(word[i]) )
{
word[i] = toUpperCase(word[i]);
}
else
{
// do nothing.
}
}
else
{
if ( isUpperCase(word[i]) )
{
word[i] = toLowerCase(word[i]);
}
else
{
// do nothing.
}
}
}
Note that I haven't implemented the isUpperCase and isLowerCase functions ;D
Function sizeof() is used to calculate the size of the datatype, not the size allocated to the pointer.
So you can not use it like sizeof(word). Instead, iterate over a characters until you stumble upon a \0, which indicates end of string.
On example:
int i = 0;
while ( word[i] != 0 ) {
// do lower/upper case conversion.
}
sizeof (word) is the size of a char *, you must pass another parameter with the array size... or use strlen ().
Something is wrong in your code : you are making odd characters upper case and even ones lower but you do no check whether they were lower or upper case in the first place. But lowering an already lower-case letter gives you a wrong value (the same is true for "uppering" an already upper-case letter).
So you should do :
char toUpperCase(char ch)
{
if ((ch >= 'a') && (ch <= 'z')) {
return ch-'a'+'A';
} else {
return ch;
}
}
and the same for toLowerCase.
Thank you so much for the tips! Using your suggestions, I modified my code and it's working now.
Below is my revised code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*converts ch to upper case, assuming it is in lower case currently*/
char toUpperCase(char ch){
return ch-'a'+'A';
}
/*converts ch to lower case, assuming it is in upper case currently*/
char toLowerCase(char ch){
return ch-'A'+'a';
}
void sticky(char* word)
{
/*Convert to sticky caps*/
for (int i = 0; i < strlen(word); i++)
{
if (i % 2 == 0)
{
if (word[i] >= 'a' && word[i] <= 'z')
{
word[i] = toUpperCase(word[i]);
}
}
else
{
if (word[i] >= 'A' && word[i] <= 'Z')
{
word[i] = toLowerCase(word[i]);
}
}
}
}
int main(){
/*Read word from the keyboard using scanf*/
char word[256];
char *input;
input = word;
printf("Please enter a word:\n");
scanf("%s", input);
/*Call sticky*/
sticky(input);
/*Print the new word*/
printf("%s", input);
for (int i = 0; i < sizeof(input); i++)
{
if (input[i] == '\n')
{
input[i] = '\0';
break;
}
}
return 0;
}
Related
I need to build a function that gets an input and capitalizes only the first letter, doesn't print numbers, capitalizes after a . for a new sentence, and capitalizes all words between a double quotation marks ".
This is what I got until now:
#include <stdio.h>
#define MAX 100
int main()
{
char str[MAX] = { 0 };
int i;
//input string
printf("Enter a string: ");
scanf("%[^\n]s", str); //read string with spaces
//capitalize first character of words
for (i = 0; str[i] != '\0'; i++)
{
//check first character is lowercase alphabet
if (i == 0)
{
if ((str[i] >= 'a' && str[i] <= 'z'))
str[i] = str[i] - 32; //subtract 32 to make it capital
continue; //continue to the loop
}
if (str[i] == '.')//check dot
{
//if dot is found, check next character
++i;
//check next character is lowercase alphabet
if (str[i] >= 'a' && str[i] <= 'z')
{
str[i] = str[i] - 32; //subtract 32 to make it capital
continue; //continue to the loop
}
}
else
{
//all other uppercase characters should be in lowercase
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] = str[i] + 32; //subtract 32 to make it small/lowercase
}
}
printf("Capitalize string is: %s\n", str);
return 0;
}
I cant find a way to remove all numbers from input and convert all lowercase to uppercase inside a " plus code for not printing numbers if user input them.
if I input
I am young. You are young. All of us are young.
"I think we need some help. Please" HELP. NO, NO NO,
I DO NOT
NEED HELP
WHATSOEVER.
"Today’s date is
15/2/2021"...
I am 18 years old, are you 20 years old? Maybe 30 years?
output:
I am young. You are young. All of us are young.
"I THINK WE NEED SOME HELP. PLEASE" help. No, no no,
i do not
need help
whatsoever.
"TODAY’S DATE IS
//"...
I am years old, are you years old? maybe years?
The C standard library provides a set of functions, in ctype.h, that will help you
Of particular interest, would be:
isdigit() - returns true if digit
isalpha() - returns true if alphabet character
isalnum() - returns true if alpha/numeric character
islower() - returns true if lower case character
isupper() - returns true if upper case character
tolower() - converts character to lower case
toupper() - converts character to upper case
So, for example, you could replace the test/modify with:
if ( islower( str[i] ) )
{
str[i] = toupper( str[i] );
}
Pedantically, islower() and toupper() return an unsigned int but that's a separate matter...
You can remove letters from a string if you keep two indices, one for reading and one for writing. The following loop will remove all digits from a string:
int j = 0; // writing index, j <= i
int i; // reading index
for (i = 0; str[i]; i++) {
int c = (unsigned char) str[i];
if (!isdigit(c)) str[j++] = c;
}
str[j] = '\0';
(I've used to character classification functions from <ctype.h> mentioned in Andrew' answer.)
This is safe, because j will always be smaller or equal to i. Don't forget to mark the end of the filtered string with the nullterminator, '\0'. You can combine this filtering with your already existing code for replacing characters.
In your code, you capitalize letters only if they are directly behind a full stop. That's usually not the case, there's a space between full stop and the next word. It's better to establish a context:
shift: capitalize the next letter (beginning or after full stop.)
lock: capitalize all letters (inside quotation marks.)
When you read a letter, decide whether to capitalize it or not depending of these two states.
Putting the filtering and the "shift context§ together:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char str[] = "one. two. THREE. 4, 5, 6. \"seven\", eight!";
int shift = 1; // Capitalize next letter
int lock = 0; // Capitalize all letters
int j = 0; // writing index, j <= i
int i; // reading index
for (i = 0; str[i]; i++) {
int c = (unsigned char) str[i];
if (isdigit(c)) continue;
if (isalpha(c)) {
if (shift || lock) {
str[j++] = toupper(c);
shift = 0;
} else {
str[j++] = tolower(c);
}
} else {
if (c == '"') lock = !lock;
if (c == '.') shift = 1;
str[j++] = c;
}
}
str[j] = '\0';
puts(str);
printf("(length: %d)\n", j);
return 0;
}
In order to remove some characters, you should use 2 index variables: one for reading and one for writing back to the same array.
If you are allowed to use <ctype.h>, it is a much more portable and efficient way to test character types.
Also do not use scanf() with protection against buffer overflow. It is as bad as using gets(). Given the difficulty in specifying the maximum number of bytes to store into str, you should use fgets() instead of scanf().
Here is a modified version:
#include <ctype.h>
#include <stdio.h>
#define MAX 100
int main() {
char str[MAX];
int i, j;
unsigned char last, inquote;
//input string
printf("Enter a string: ");
if (!fgets(str, sizeof str, stdin)) { //read string with spaces
// empty file
return 1;
}
last = '.'; // force conversion of first character
inquote = 0;
//capitalize first character of words
for (i = j = 0; str[i] != '\0'; i++) {
unsigned char c = str[i];
//discard digits
if (isdigit(c)) {
continue;
}
//handle double quotes:
if (c == '"') {
inquote ^= 1;
}
//upper case letters after . and inside double quotes
if (last == '.' || inquote) {
str[j++] = toupper(c);
} else {
str[j++] = tolower(c);
}
if (!isspace(c) && c != '"') {
// ignore spaces and quotes for the dot rule
last = c;
}
}
str[j] = '\0'; // set the null terminator in case characters were removed
printf("Capitalized string is: %s", str);
return 0;
}
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.
Hi I am stuck while trying to cipher and decipher string using pointer. i need to shift the alphabet by +1.
example: Hello will be Ifmmp. And i also need to eliminate other characters such as $%^^. so when the string is 'z' +1 would give me 'a'
Here is my code.
char *cipher(char *s) {
int i =0;
int shift = 1;
while(*(s+i)!= '\0') {
if (*(s+i)) {
*(s+i)+= (shift);
}
i++;
}
}
char *decipher(char *s) {
int i =0;
int shift = -1;
while(*(s+i)!= '\0') {
if (*(s+i) +shift) {
*(s+i)+= (shift);
}
i++;
}
}
my current output is:
To cipher: abcxyz -> bcdyz{
To decipher: bcdyz{ -> abcxyz
Thanks
First of all, change the while to For-Loop, if you increase itearator at the for loop and its your condition the best readable code is For-Loop
Second, you need to add condtion-
If the letter is 'z' assign 'a'
else do the same thing
Third if you want to avoide another letters you need to add condition:
if((*s+i)<'a' || (*s+i)>'z'){
do what you want
} else {
avoide
} /// it will work if you use character encoding that the alphebet is by order and continuous
I add the code with change at chipher function, you will add the same to the next function
char *cipher(char *s){
int shift = 1;
for(int i=0; *(s+i)!= '\0'; i++){
if (*(s+i)){
//i add that condtion for 'z' you need to add the same condition to the next function
if(*(s+i)=='z'){
*(s+i)='a';
}else{
*(s+i)+= (shift);
}
}
}
}
char *decipher(char *s){
int shift = -1;
for(int i=0 ;*(s+i)!= '\0'; i++){
if (*(s+i) +shift){
*(s+i)+= (shift);
}
}
}
i need to shift the alphabet by +1
Shift only characters a-z. So code must detect those
char *shift_AZ(char *s, int shift) {
// Bring shift into 0-25 range
shift %= 26;
if (shift < 0) shift += 26;
// loop until at end of string
// while(*(s+i)!= '\0') {
while(*s) {
// Assuming ASCII, detect select characters
if ((*s >= 'a') && (*s <= 'z')) {
// Do the shift, wrap around via %26
*s = (*s - 'a' + shift)%26 + 'a';
}
s++; // next chraracter
}
char *cipher(char *s) {
return shift_AZ(s, 1);
}
char *decipher(char *s) {
return shift_AZ(s, -1);
}
Reposting because my first post was no good. I have a question that I'm not really sure how to do. I know the process I'm going for, but am not totally sure how to scan a string into an array so that each character/integer is scanned into a independent element of the array. I'll post the question and the code I have so far, and any help would be appreciated.
Question:
Assume that we have a pattern like the following: ([n][letter])+ in which n is an integer number and letter is one of the lowercase letters from a-z. For example, 2a and 3b are valid expressions based on our pattern. Also, “+” at the end of the pattern means that we have at least one expression (string) or more than one expression attached. For instance, 2a4b is another valid expression which is matched with the pattern. In this question, we want to convert these valid expressions to a string in which letters are repeated n times.
o Read an expression (string) from user and print the converted version of the expression in the output.
o Check if input expression is valid. For example, 2ab is not a valid expression. If the expression is not valid, print “Invalid” in the output and ask user to enteranother expression.
o Sample input1 = “2a”, output = aa
o Sample input2 = “2a3b”, output = aabbb
o You will receive extra credit if you briefly explain what concept or theory you can use to check whether an expression is valid or not.
What I have so far:
#include <stdio.h>
int main()
{
int size, i, j;
char pattern[20];
char vowel[20];
int count[20];
printf("Please enter your string: ");
gets(pattern);
size = strlen(pattern);
for(i=0; i<size; i++)
if((i+1)%2 == 0)
vowel[i] = pattern[i];
else if((i+1)%2 != 0)
count[i] = pattern[i];
for(i=0; i<size/2; i++);
for(j=0; j<count[i]; j++)
printf("%s", vowel[i]);
}
I assumed you want to write the "invalid\n" string on stderr. If not just change the file descriptor given to write.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INPUT_SIZE 20
int
check_input(char *input)
{
while (*input)
{
if (*input < '0' || *input > '9')
{
write(2, "invalid\n", 8);
return 1;
}
while (*input >= '0' && *input <= '9')
input++;
if (*input < 'a' || *input > 'z')
{
write(2, "invalid\n", 8);
return 1;
}
input++;
}
return 0;
}
void
print_output(char *input)
{
int i;
while (*input)
{
i = atoi(input);
while (*input >= '0' && *input <= '9')
input++;
for (; i > 0; i--)
write(1, input, 1);
input++;
}
write(1, "\n", 1);
}
int
main()
{
char input[MAX_INPUT_SIZE];
do
{
printf("Please enter your string: ");
fgets(input, MAX_INPUT_SIZE, stdin);
input[strlen(input) - 1] = '\0';
}
while (check_input(input));
print_output(input);
return 0;
}
The steps are:
Read pattern
Check if pattern is valid
Generate output
Since the input length is not specified you have to assume a maximum length.
Another assumption is n is a single digit number.
Now you may read the whole expression with fgets() or read it char by char.
The latter allows you to check for validity as you read.
Lets use fgets() for convenience and in case the expression needs to be stored for later use.
char exp[100]; // assuming at most 50 instances of ([n][letter])
int len;
printf("Input: ");
fgets(exp, 100, stdin);
len = strlen(exp) - 1; // Discard newline at end
An empty input is invalid. Also a valid expression length should be even.
if (len == 0 || len%2 != 0) {
printf("Invalid-len\n");
return 1;
}
Now parse the expression and separately store numbers and letters in two arrays.
char nums[50], letters[50];
invalid = 0;
for (i = 0, j = 0; i < len; i += 2, j++) {
if (exp[i] >= '1' && exp[i] <= '9') {
nums[j] = exp[i] - '0';
} else {
invalid = 1;
break;
}
if (exp[i+1] >= 'a' && exp[i+1] <= 'z') {
letters[j] = exp[i+1];
} else {
invalid = 1;
break;
}
}
Notice that in each iteration if first char is not a number or second char is not a letter, then the expression is considered to be invalid.
If the expression is found to be invalid, nothing to do.
if (invalid) {
printf("Invalid\n");
return 1;
}
For a valid expression run nested loops to print the output.
The outer loop iterates for each ([n][letter]) pattern.
The inner loop prints n times the letter.
printf("Output: ");
for (i = 0; i < len/2; i++) {
for (j = 0; j < nums[i]; j++)
printf("%c", letters[i]);
}
This is a rather naive way to solve problems of this type. It is better to use regular expressions.
C standard library doesn't have regex support. However on Unix-like systems you can use POSIX regular expressions.
like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#define prompt "Please enter your string: "
void occurs_error(const char *src, const char *curr){
printf("\nInvalid\n");
printf("%s\n", src);
while(src++ != curr){
putchar(' ');
}
printf("^\n");
}
bool invalid(char *pattern){
char *p = pattern;
while(*p){
if(!isdigit((unsigned char)*p)){//no number
occurs_error(pattern, p);
break;
}
strtoul(p, &p, 10);
if(!*p || !islower((unsigned char)*p)){//no character or not lowercase
occurs_error(pattern, p);
break;
}
++p;
}
return *p;
}
int main(void){
char pattern[20];
while(fputs(prompt, stdout), fflush(stdout), fgets(pattern, sizeof pattern, stdin)){
pattern[strcspn(pattern, "\n")] = 0;//chomp newline
char *p = pattern;
if(invalid(p)){
continue;
}
while(*p){
int n = strtoul(p, &p, 10);
while(n--)
putchar(*p);
++p;
}
puts("");
}
}
I'm trying to create a function that will identify whether the first letter input is upper or lower case then output the rest of the string in that same case(upper/lower).
For example, "Hi there" would become "HI THERE".
I'm not familiar with fgets. Once I run it I can input and press enter and the program doesn't run. I'm not getting any compiler errors. I believe I went wrong in the void shift function.
Also, I know gets is not recommended, is fgets similar? Or is it better to use scanf?
#include <stdio.h>
#include <ctype.h>
void shift (char *my_string); // Function declaration
int main()
{
char inputstring[50];
printf("Enter a string\n");
char *my_string = inputstring;
shift(my_string); // Function
}
void shift (char *my_string) // Function definition
{
int i =0;
char ch;
for(i=0; i<50; i++)
fgets(my_string, 50, stdin);
while(my_string[i])
{
if(ch>='A' && ch<= 'Z') // When first char is uppercase
{
putchar (toupper(my_string[i]));
i++;
}
else if (ch>='a' && ch <= 'z') // When first char is lowercase
{
putchar(tolower(my_string[i]));
i++
}
}
return;
}
You don't need to call fgets() fifty times. It reads a line from stdin and writes it to my_string. It seems you only want to read one line, not fifty (and keep only the last one). The 50 is the maximum number of characters (minus one) that will be read and written to the buffer. This limit is to prevent buffer overflow. See fgets().
Try removing the for loop on the line before the fgets() call. Also, you don't need the my_string in main(). The corrected code:
#include <stdio.h>
#include <ctype.h>
void shift (char *my_string);//function declaration
int main()
{
char inputstring[50];
printf("Enter a string\n");
shift(inputstring);
}
void shift (char *my_string) //function definition
{
int i;
char ch;
if ( fgets(my_string, 50, stdin) == NULL )
return;
ch = my_string[0];
for ( i=0; my_string[i]; i++ )
{
if(ch>='A' && ch<= 'Z') //when first char is uppercase
{
putchar (toupper(my_string[i]));
}
else if (ch>='a' && ch <= 'z')//when first char is lowercase
{
putchar(tolower(my_string[i]));
}
}
return;
}
Edit: Added ch initialization, pointed out by #thurizas. Changed while loop to for loop. Added check to return value of fgets() as suggested by #JonathanLeffler. (See his comment about the buffer size.)
Here is another solution for your problem,
#include <stdio.h>
#include <ctype.h>
void convertTo (char *string);
int main()
{
char inputString[50];
printf("Enter a string\n");
convertTo(inputString);
}
void convertTo (char *string)
{
int i;
char ch;
gets(string);
ch = string[0];
for ( i=0; string[i]; i++ )
{
if(ch>='A' && ch<= 'Z')
{
if(string[i]>='a' && string[i]<= 'z')
string[i] = string[i] - 32;
}
else if (ch>='a' && ch <= 'z')
{
if(string[i]>='A' && string[i]<= 'Z')
string[i] = string[i] + 32;
}
}
printf("%s\n", string);
return;
}
All ASCII characters are represented by 7-bits. (thus the term 7-bit ASCII) The only bitwise difference between lower-case and upper-case is that bit-5 (the sixth bit) is set for lowercase and cleared (unset) for uppercase. This allows a simple bitwise conversion between lowercase and uppercase (either by adding/subtracting 32 or by simply flipping bit-5 directly.)
+-- lowercase bit
|
a = 01100001 A = 01000001
b = 01100010 B = 01000010
c = 01100011 C = 01000011
...
This allows a simple test and conversion if the first character is upper-case:
#include <stdio.h>
enum { MAXC = 50 };
char *shift (char *my_string);
int main (void)
{
char inputstring[MAXC] = {0};;
printf ("\n Enter a string: ");
if (shift (inputstring))
printf (" my_string is : %s\n", inputstring);
return 0;
}
char *shift (char *my_string)
{
char *p;
if (!(p = fgets (my_string, MAXC, stdin))) return NULL;
if (*p == '\n') return NULL; /* Enter only pressed */
if ('A' <= *p && *p <= 'Z') /* test for upper case */
for (; *p; p++) /* convert lower/upper */
if ('a' <= *p && *p <= 'z') *p &= ~(1 << 5);
return my_string;
}
Example Use
$ ./bin/case_1st_to_upper
Enter a string: this is my string
my_string is : this is my string
$ ./bin/case_1st_to_upper
Enter a string: This is my string
my_string is : THIS IS MY STRING