Switching case of each letter in a string - c

#include <stdio.h>
int main() {
int i;
char arr[100];
for (i = 0; i < 100; i++)
scanf("%c", &arr[i]);
for (i = 0; i < 100; i++) {
if ('a' <= arr[i] && arr[i] <= 'z')
arr[i] =-32;
else
if ('A' <= arr[i] && arr[i] <= 'Z')
arr[i] =+32;
}
printf("%s", arr);
return 0;
}
There was a problem:
You have been given a String consisting of uppercase and lowercase English alphabets. You need to change the case of each alphabet in this String. That is, all the uppercase letters should be converted to lowercase and all the lowercase letters should be converted to uppercase. You need to then print the resultant String to output.
What is wrong with the above code? It is compiling successfully but there is a runtime error.

There are multiple problems in your code:
the main issue is the away you adjust the case: arr[i] =-32; does not decrement arr[i] by 32, but stores 32 into arr[i]. The combined assignment operator is spelled -=. You have the same problem for += in the other case.
Converting lower case to upper case by subtracting 32 works for ASCII, but is not portable to other character sets. Similarly, comparing to 'a' and 'z' works for ASCII, but not for EBCDIC. You should use the functions from <ctype.h>.
you read 100 characters with scanf("%c"...) but you do not check the return value, nor do you null terminate the array. Furthermore, you should read at most one less than the size of the array to leave space for the '\0' byte. As coded, your program invokes undefined behavior at printf("%s", arr); because arr is not null terminated.
Here is a corrected version:
#include <ctype.h>
#include <stdio.h>
int main(void) {
int c;
while ((c = getchar()) != EOF) {
if (isupper(c))
c = tolower(c);
else
if (islower(c))
c = toupper(c);
putchar(c);
}
return 0;
}

The most obvious problem is that you are not null-terminating the string, so when you call printf("%s", arr) the behavior will be unpredictable.

The problem with your code is that it never terminates the string. If you read 100 characters, and then you want to print them with %s in printf, you have to add a null terminator at the end, like this:
char arr[100+1]; // See +1
... // Reading code
arr[100] = '\0';
Note that library functions islower/isupper provide a portable, and a lot more readable, approach to testing character type. Similarly, tolower/toupper provide more information about your intentions to the reader of your code than simply adding and subtracting 32. Moreover, C code that uses these standard functions will work on systems with non-ASCII character encoding.

In order to printf("%s", arr), you need to terminate arr with a null-character.
One way to do it is by:
Declaring char arr[101]
Setting arr[100] = 0

Your code has serveral issues: not-null-terminated input string, unproper lower/uppercase conversion and confusion with =- / -= and =+ / += operators.
Next code is based on yours:
As an alternative to get a null-terminated string it uses fgets() instead of scanf(), just for the example.
Also uses C library functions for avoiding issues with different charsets, simplifing the conditions and for upper/lower case operations.
Edited to improve code quality, as #chqrlie suggested in a comment.
#include <stdio.h>
#include <ctype.h>
int main()
{
int i;
char arr[101];
printf("Enter string: ");
fgets(arr, sizeof(arr), stdin);;
for(i=0;i<strlen(arr); i++)
{
int value = (unsigned char) arr[i]; // to properly use int parameters, as expected by ctype.h next functions
if (isupper(value))
{
arr[i]=tolower(value);
}
else {
if (islower(value))
{
arr[i]=toupper(value);
}
}
}
printf("%s", arr);
return 0;
}
Test it here.

Related

Why is this code producing an infinite loop?

#include <Stdio.h>
#include <string.h>
int main(){
char str[51];
int k = 1;
printf("Enter string\n");
scanf("%s", &str);
for(int i = 0; i < strlen(str); i++){
while(str[k] != '\0')){
if(str[i] == str[k]){
printf("%c", str[i]);
k++;
}
}
}
return 0;
}
It is simple C code that checks for duplicate characters in string and prints the characters. I am not understanding why it is producing an infinite loop. The inner while loop should stop when str[k] reaches the null terminator but the program continues infinitely.
Points to know
You don't need to pass the address of the variable str to scanf()
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Always check whether scanf() conversion was successful or not, by checking its return value
Always use size_t to iterator over any array
i < strlen(str), makes the loop's time complexity O(n3), instead of O(n2), which also isn't very good you should check whether str[i] != 0. But, many modern compilers of C will optimize it by the way.
#include <Stdio.h> it is very wrong, stdio.h != Stdio.h
Call to printf() can be optimized using puts() and putc() without any special formatting, here also modern compiler can optimize it
while(str[k] != '\0')){ has a bracket (')')
Initialize your variable str using {}, this will assign 0 to all the elements of str
Better Implementation
My implementation for this problem is that create a list of character (256 max) with 0 initialized, and then add 1 to ASCII value of the character (from str) in that list. After that print those character whose value was greater than 1.
Time Complexity = O(n), where n is the length of the string
Space Complexity = O(NO_OF_CHARACTERS), where NO_OF_CHARACTERS is 256
Final Code
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
static void print_dup(const char *str)
{
size_t *count = calloc(1 << CHAR_BIT, sizeof(size_t));
for(size_t i = 0; str[i]; i++)
{
count[(unsigned char)str[i]]++;
}
for (size_t i = 0; i < (1 << CHAR_BIT); i++)
{
if(count[i] > 1)
{
printf("`%c`, count = %zu\n", i, count[i]);
}
}
free(count);
}
int main(void) {
char str[51] = {};
puts("Enter string:");
if (scanf("%50s", str) != 1)
{
perror("bad input");
return EXIT_FAILURE;
}
print_dup(str);
return EXIT_SUCCESS;
}
Read your code in English: You only increment variable k if character at index k is equal to character at index i. For any string that has different first two characters you will encounter infinite loop: char at index i==0 is not equal to char at index k==1, so k is not incremented and while(str[k]!=0) loops forever.

Program to get an indefinite number of strings in C and print them out

As part of an assignment, I am supposed to write a small program that accepts an indefinite number of strings, and then print them out.
This program compiles (with the following warning
desafio1.c:24:16: warning: format not a string literal and no format arguments [-Wform
at-security]
printf(words[i]);
and it prints the following characters on the screen: �����8 ���#Rl�. I guess it did not end the strings I entered by using getchar properly with the null byte, and it prints out garbage. The logic of the program is to initiate a while loop, which runs untill I press the enter key \n, and if there are an space, this is a word that will be store in the array of characters words. Why am I running into problems, if in the else statement once a space is found, I close the word[i] = \0, in that way and store the result in the array words?
#include <stdio.h>
#include <string.h>
int main()
{
char words[100][100];
int i,c;
char word[1000];
while((c = getchar()) != '\n')
{
if (c != ' '){
word[i++] = c;
c = getchar();
}
else{
word[i] = '\0';
words[i] == word;
}
}
int num = sizeof(words) / sizeof(words[0]);
for (i = 0; i < num; i++){
printf(words[i]);
}
return 0;
}
Here are some fixes to your code. As a pointer (as mentioned in other comments), make sure to enable compiler warnings, which will help you find 90% of the issues you had. (gcc -Wall)
#include <stdio.h>
#include <string.h>
int main() {
char words[100][100];
int i = 0;
int j = 0;
int c;
char word[1000];
while((c = getchar()) != '\n') {
if (c != ' '){
word[i++] = c;
} else {
word[i] = '\0';
strcpy(words[j++], word);
i = 0;
}
}
word[i] = '\0';
strcpy(words[j++], word);
for (i = 0; i < j; i++) {
printf("%s\n", words[i]);
}
return 0;
}
i was uninitialized, so its value was undefined. It should start at 0. It also needs to be reset to 0 after each word so it starts at the beginning.
The second c = getchar() was unnecessary, as this is done in every iteration of the loop. This was causing your code to skip every other letter.
You need two counters, one for the place in the word, and one for the number of words read in. That's what j is.
== is for comparison, not assignment. Either way, strcpy() was needed here since you are filling out an array.
Rather than looping through all 100 elements of the array, just loop through the words that have actually been filled (up to j).
The last word input was ignored by your code, since it ends with a \n, not a . That's what the lines after the while are for.
When using printf(), the arguments should always be a format string ("%s"), followed by the arguments.
Of course, there are other things as well that I didn't fix (such as the disagreement between the 1000-character word and the 100-character words). If I were you, I'd think about what to do if the user entered, for some reason, more than 1000 characters in a word, or more than 100 words. Your logic will need to be modified in these cases to prevent illegal memory accesses (outside the bounds of the arrays).
As a reminder, this program does not accept an indefinite number of words, but only up to 100. You may need to rethink your solution as a result.

I mixed up two programs in the cs50 sandbox in c?

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;
}

program to remove special characters and number from string and only print english letter

this is what i tried.
this works properly for small string like wel$co*me
but gives weird output for pass#word. where am i going wrong exactly?
#include <stdio.h>
#include <string.h>
int main()
{
char s[100],rs[100];
int i,c=0;
scanf("%s",s);
int n = strlen(s);
for(i=0;i<n;i++)
{
if(((int)s[i] >= 65 && (int)s[i] <= 90) ||((int)s[i] >=97 && (int)s[i] <= 122) )
{
rs[c] = s[i];
c++;
}
else
{
continue;
}
}
printf("%s",rs);
return 0;
}
but gives weird output for pass#word. where am i going wrong exactly?
printf("%s",rs); expects rs to be a pointer to a string. Yet without a certain null character in the data pointed to by rs, the result is undefined behavior or in OP's case, "weird output".
A simple solution is
rs[c] = '\0'; // add this after the loop
printf("%s",rs);
Another important one is to avoid buffer overruns - use a width limit.
// scanf("%s",s);
scanf("%99s",s);
Code has other weaknesses, yet this are the key ones for now.

How to detect space and letters in a Char in C?

Do you know how I can detect space and letters in a CHAR variable?
I need to detect letters or space in a input of numbers:
This what I want to do:
Enter Document Number of 8 numbers:
// i press space and pressed enter
ERROR: please enter the age again: 4fpdpfsg
There's where my code doesn't detect the letters after the 4, and what I want is recognize that there's letters in the input, and then shows only the 4.
int isLetter(char input[]){
int i = 0;
while(input[i]!='\0'){
if((input[i]!=' ') && (input[i]<'a'||input[i]>'z') && (input[i]<'A'||input[i]>'Z'))
return 0;
i++;
}
return 1;
}
The standard C library has various character type testing functions. They are declared in the #include <ctype.h> header.
Unfortunately, the obvious way of using these functions is often wrong. They take an argument of type int which is actually expected to be an unsigned character value (a byte, effectively) in the range 0 to UCHAR_MAX. If you pass in a char value which happens to be negative, undefined behavior ensues, which might work by coincidence, crash or worse yet form a vulnerability similar to heartbleed (possibly worse).
Therefore the cast to (unsigned char) is quite likely necessary in the following:
#include <ctype.h>
/* ... */
char ch;
/* ... */
if (isalpha((unsigned char) ch) || ch == ' ') {
/* ch is an alphabetic character, or a space */
}
Simple character constants (not numeric escaped ones) derived from the C translation time character set have positive values in the execution environment; code which can safely assume that it only manipulates such characters can do without the cast. (For instance, if all the data being manipulated by the program came from string or character literals in the program itself, and all those literals use nothing but the basic C translation time character set.)
That is to say, isalpha('a') is safe; a is in the C translation time character set, and so the value of the character constant 'a' is positive. But say you're working with source code in ISO-8859-1 and have char ch = 'à';. If char is signed, this ch will have a negative value, which is fine according to ISO C because an accented à isn't in the basic C translation character set. The expression isalpha(ch); then passes a negative value to the isalpha function, which is wrong.
Try:
if (!((input[i] == ' ') || (input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z')))
or, better:
#include <ctype.h>
if (!((input[i] == ' ') || isalpha(input[i])))
You could use sscanf(input,"%d%n",&number,&nrOfDigits) which reads in an integral value into number and additionally stores the position of the first character which has not been part of the number in nrOfDigits. With this information, you can then decide what to do, e.g. nrOfDigits < 8 would indicate that either the input was shorter than 8 characters, or that it does contain less than 4 consecutive digits. See sample code of the usage below.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int isLetter(char input[]){
int nrOfDigits=0;
int number;
int scannedElems = sscanf(input,"%d%n",&number,&nrOfDigits);
if (scannedElems == 0) {// number could not be read--
printf ("No number read.\n");
return 0;
}
else {
char c = input[nrOfDigits];
int isAlpha = isalpha(c);
printf("input %s leads to number %d with %d digit(s); first characer after the digits is '%c', (isalpha=%d)\n", input, number, nrOfDigits, c, isAlpha);
return number;
}
}
int main(){
isLetter("4fpdpfsg"); // input 4fpdpfsg leads to number 4 with 1 digit(s); first characer after the digits is 'f', (isalpha=1)
isLetter("afpdpfsg"); // No number read.
isLetter("12345678"); // input 12345678 leads to number 12345678 with 8 digit(s); first characer after the digits is '�', (isalpha=0)
return 0;
}
BTW: you could implement a similar logic with strtoul as well.
hey guys i finally get the way to detect the input is conformed only for 8 numbers theres the code
char* InputDni(char dni[])
{
int sizeletter;
int i;
fflush(stdin);
gets(dni);
// 8 is the size of DNI in argentina
while((isLetter(dni)) || (strlen(dni)!=8))
{
printf("ERROR: enter again the DNI: ");
fflush(stdin);
gets(dni);
}
sizeletter=strlen(dni);
for(i=0 ;i<sizeletter; i++)
{
while(isalpha(dni[i]))
{
printf("ERROR: enter again the DNI: ");
fflush(stdin);
gets(dni);
i++
}
}
return dni;
}
//isLetter
int isLetter(char input[])
{
int i = 0;
int sizeletter;
int flag=1;
sizeletter=strlen(input);
for(i=0;i<sizeletter;i++)
{
if((input[i]!=' ') && (input[i]<'a'||input[i]>'z') && (input[i]<'A'||input[i]>'Z'))
{
flag=0;
}
}
return flag;
}
picture of the code running in cmd:

Resources