Strange output of the C program using toupper function - c

Here is my program to uppercases all letter inputted from the standard input. But some output is very strange. For example, if input is "lorem ipsum" and output will be "LOREM IPSUMS?". If input is a single character such as 'm', the output will be "MZ#X?" . "S?" and "Z#X?" should not be here but they append to the output.
Why this happens?
#include <stdio.h>
#include <ctype.h>
int main(void){
char input;
char upper[100];
int count = 0;
while((input = getchar())){
if(input == '\n')
break;
if(input >= 'a' && input <= 'z')
input = toupper(input);
*(upper + count) = input;
count++;
}
printf("%s\n", upper);
return 0;
}

Your code is working for me.
The only thing, but this is expected, you get garbage after the string, because your char array has a length of 100. You should put a 0 at the end of the string to tell printf your string ends there. put
*(upper + count) = 0;
right before printf.

Your code has a some issues:
the NULL terminator isn't added at the end of the string.
There isn't any check of index out of bounds of the allocated array.
User may interrupt input without a newline making the program loop forever.
getchar returns an int.
You can try this fix:
#include <stdio.h>
#include <ctype.h>
const int MAX_CHAR = 101;
int main() {
int input;
char upper[MAX_CHAR];
int count = 0;
while( count < MAX_CHAR - 1 ) {
input = getchar();
if ( input == EOF || input == '\n' || input == '\r' )
break;
if ( input >= 'a' && input <= 'z' )
input = toupper(input);
upper[count] = input;
count++;
}
// add the null terminator
upper[count] = '\0';
printf("%s\n", upper);
return 0;
}

You might want to set all the elements in your array to be 0 (ASCII NUL) because we have no idea what is in the upper array.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void){
char input;
char upper[100];
int count = 0;
memset(upper, 0, 100);
while((input = getchar())){
if(input == '\n')
break;
if(input >= 'a' && input <= 'z')
input = toupper(input);
*(upper + count) = input;
count++;
}
printf("%s\n", upper);
return 0;
}
If you are not sure what memset does, you can do it with a for loop.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void){
char input;
char upper[100];
int count = 0;
for (int i = 0; i < 100; i++) {
upper[i] = 0;
}
while((input = getchar())){
if(input == '\n')
break;
if(input >= 'a' && input <= 'z')
input = toupper(input);
*(upper + count) = input;
count++;
}
printf("%s\n", upper);
return 0;
}

Related

How to have a function output a string, not just the first word

I'm writing a function to capitalize every lowercase character in a string. It takes a string from the user and that is the input to the function. My program works if the user doesn't enter spaces, but when there is a space in the string, the function ends.
#include <stdio.h>
char *uppercase(char *c) {
int i = 0;
while (c[i] != '\0') {
if (123 > c[i] && c[i] > 96)
c[i] = c[i] - 'a' + 'A';
i++;
}
return c;
}
int main() {
char input[100];
printf("Enter the phrase: ");
scanf("%s", input);
printf("%s", uppercase(input));
return 0;
}
Examples:
Input: test test
Output: TEST
Input: Hello
Output: HELLO
Input: How are you
Output: HOW
I think it has to do with the while statement? Thanks for the help.
The problem is not in the while statement, but rather due to the scanf() format: %s reads a single word from the input, leaving the rest of the line in the stdin buffer. Note also that typing a word with more than 99 characters will cause undefined behavior because scanf() will write beyond the end of the input array. Using %99s would prevent this problem, but not solve your issue.
You should use fgets() to read a full line of input from stdin.
Furthermore, instead of using hard coded ASCII values, you should use character constants such as 'a' and 'z' or the functions from <ctype.h>.
Here is a modified version using ASCII:
#include <stdio.h>
char *uppercase(char *s) {
int i = 0;
while (s[i] != '\0') {
if (s[i] >= 'a' && s[i] <= 'z')
s[i] = s[i] - 'a' + 'A';
i++;
}
return s;
}
int main() {
char input[100];
printf("Enter the phrase: ");
if (fgets(input, sizeof input, stdin)) {
fputs(uppercase(input), stdout);
}
return 0;
}
Here is a more portable one using <ctype.h>:
#include <ctype.h>
#include <stdio.h>
char *uppercase(char *s) {
int i = 0;
unsigned char c;
while ((c = s[i]) != '\0') {
if (islower(c))
s[i] = toupper(c);
i++;
}
return s;
}
This can be further simplified as toupper() can be called for all byte values from 0 to UCHAR_MAX:
#include <ctype.h>
#include <stdio.h>
char *uppercase(char *s) {
for (size_t i = 0; s[i] != '\0'; i++) {
s[i] = toupper((unsigned char)c);
}
return s;
}
Either use
scanf ("%99[^\n]", input);
or
fgets( input, sizeof( input ), stdin );
Also it is a bad practice to use magic numbers like 123 or 96
if (123 > c[i] && c[i] > 96)
The code will be more readable if you will write at least
if ( 'a' <= c[i] && c[i] <= 'z' )
Also instead of the while loop it is better to use the for loop like
for ( char *p = c; *p; ++p )
{
if ( 'a' <= *p && *p <= 'z' )
{
*p = *p - 'a' + 'A';
}
}

How to truncate characters over a certain length in C?

I'm working on a C program that takes in an input of lines of text, and return it by printing only 40 characters each.
So far, I have this code:
#include <stdio.h>
#include <stdlib.h>
int main() {
char input = getchar();
int numChar;
int total;
while ((input != EOF) && (input != '\n')) {
++numChar;
if (numChar > 40) {
printf("\n");
++total;
numChar = 0;
}
putchar(input);
input = getchar();
}
return EXIT_SUCCESS;
}
Just updated my post with a new draft I have. For this attempt I am trying to print each character as it takes each input but if the character count is over 40, to make a new line. But, I don't get an output as expected.
You are using two uninitialized variables
int numChar;
int total;
So the program has undefined behavior.
Moreover the accumulated value of the variable total is not used in the program.
And the variable input has to be declared as having the type int.
Pay attention to that the last outputted substring can contain less than 40 characters. In this case you need to call
putchar( '\n' );
also after the loop.
Using your approach with inputting characters by means of the function getchar the program can look the following way
#include <stdio.h>
int main(void)
{
const size_t LINE_LENGTH = 40;
size_t count = 0;
for ( int c; ( c = getchar() ) != EOF && c != '\n'; )
{
putchar( c );
if ( ++count % LINE_LENGTH == 0 )
{
putchar( '\n' );
count = 0;
}
}
if ( count % LINE_LENGTH != 0 ) putchar( '\n' );
return 0;
}
If to input the string shown in your question then the output will be
This line is soooooooooooooooooo looooou
oooooooooooooooooooooooooooooooooooooooo
oooong!
I'm not sure if thats whats you're asking. Basically every 40 characters, a newline character is printed.
#include <stdio.h>
int main(void)
{
int c = 0;
size_t i = 0;
while ((c = getchar()) != EOF)
{
if (i++ < 40)
{
putchar(c);
}
else if (i++ > 40 && c !='\n')
{
i = 1;
printf("\n%c",c);
}
if (c == '\n')
{
i = 0;
}
}
return 0;
}
Edit:
Your code seem to work fine if you were to initiliaze numChar --> numChar = 0 and total --> total = 0.
Actually strings are sequences of chars terminated by a null char '\0', so strings are arrays of chars.
You can easily iterate over the string untill you encounter the null char and on every iteration you print the current char and if the character index is a multiple of 40 you print a new line char, in this way every 40 character you split the string.
So here is the code:
#include <stdio.h>
#define MAX_LENGHT 200
int main () {
char input[MAX_LENGHT];
fgets(input, MAX_LENGHT, stdin);
int index = 0;
while (input[index++] != '\0') {
putchar(input[index]);
if (index % 40 == 0) {
putchar('\n');
}
}
}
#include <stdio.h>
int main() {
char c;
for(int i = 0; (c = getchar()) != EOF; i++) {
if( !(i % 40) ) puts("");
putchar(c);
}
return 0;
}
Or if you want to avoid starting on a newline , just change the if to
if( i && !(i % 40) ) puts("");
There are multiple problems:
numChars and total are uninitialized, you get undefined behavior.
you only handle the first line of text as you stop when you read a newline.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main() {
int pos = 0, c;
while ((c = getchar()) != EOF) {
if (c == '\n') {
putchar(c);
pos = 0;
} else
if (pos < 40) {
putchar(c);
pos++;
} else {
// ignore the character beyond the first 40
}
}
return EXIT_SUCCESS;
}

How to count the characters of a string and assign them to different groups (lower case & upper case) in C

I wrote a program in C that gets a string from the user (50 characters is the limit) and assign the upper-case characters to a string named upper, and the lower-case characters to lower, in the end it supposed to prints those strings (the upper first). My problem is when I enter a string, it only prints one string (i.e if the string starts with an upper character then upper will be printed) instead of two of them.
Here's my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define MAX_LEN 50
int main()
{
char str[MAX_LEN] = { 0 };
char upper[MAX_LEN] = { 0 };
char lower[MAX_LEN] = { 0 };
int i = 0;
int j = 0;
printf("Enter a string: ");
fgets(str, MAX_LEN, stdin);
str[strcspn(str, "\n")] = 0;
for (i = 0; i < strlen(str); i++)
{
if (str[i] > 'A' && str[i] < 'Z')
{
upper[j] = str[i];
}
else if (str[i] > 'a' && str[i] < 'z')
{
lower[j] = str[i];
}
j++;
}
printf("%s", upper);
printf("%s", lower);
getch();
return 0;
}
Use different index variables for upper and lower and in your if-statements, change > operator to >= and similarly < to <=
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define MAX_LEN 50
int main()
{
char str[MAX_LEN] = { 0 };
char upper[MAX_LEN] = { 0 };
char lower[MAX_LEN] = { 0 };
int i = 0;
int up = 0, low = 0;
printf("Enter a string: ");
fgets(str, MAX_LEN, stdin);
str[strcspn(str, "\n")] = 0;
for (i = 0; i < strlen(str); i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
upper[up] = str[i];
up++;
}
else if (str[i] >= 'a' && str[i] <= 'z')
{
lower[low] = str[i];
low++;
}
}
printf("%s\n", upper);
printf("%s", lower);
getch();
return 0;
}
You use one counter for two arrays. You increment the counter, no matter which array you fill in. As a result, the first letter to be processed will determine which array will not have its first character as the C string NULL terminator.
So? So, when you use printf(), it will stop printing when you use %s, as soon as it meets a NULL terminator, as all the functions of <stdio.h> do. BTW, you had forgotten to include that library.
One solution would be to use two counters, one for every array and increment the counter of the array that we just filled in.
Moreover, use >= instead of > to take into account 'a' too. Likewise for 'z', and their capitals.
Putting them all together you get something like this:
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdio.h> // you hadn't include that!
#define MAX_LEN 50
int main()
{
char str[MAX_LEN] = { 0 };
char upper[MAX_LEN] = { 0 };
char lower[MAX_LEN] = { 0 };
int i = 0;
int j = 0; // counter for 'upper'
int k = 0; // counter for 'lower'
printf("Enter a string: ");
fgets(str, MAX_LEN, stdin);
str[strcspn(str, "\n")] = 0;
for (i = 0; i < strlen(str); i++)
{
if (str[i] >= 'A' && str[i] <= 'Z') // use the equal operator as well for reading 'A' and 'Z' as well
{
upper[j++] = str[i]; // increment the counter 'j'
}
else if (str[i] >= 'a' && str[i] <= 'z') // use the equal operator as well for reading 'a' and 'z' as well
{
lower[k++] = str[i]; // increment the counter 'k'
}
}
// print your strings, but use a newline for aesthetics
printf("%s\n", upper);
printf("%s\n", lower);
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
Enter a string: Samaras
S
amaras
You are using j as an iterator for both of your arrays. You don't do that. If you do that, you could have a '\0' at the first place of your other array and it won't be written.
so you should do that:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define MAX_LEN 50
int main()
{
char str[MAX_LEN] = { 0 };
char upper[MAX_LEN] = { 0 };
char lower[MAX_LEN] = { 0 };
int i = 0;
int j = 0, h = 0;
printf("Enter a string: ");
fgets(str, MAX_LEN, stdin);
str[strcspn(str, "\n")] = 0;
for (i = 0; i < strlen(str); i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
upper[j++] = str[i];
}
else if (str[i] > 'a' && str[i] < 'z')
{
lower[h++] = str[i];
}
}
printf("%s", upper);
printf("%s", lower);
return 0;
}
Here you are itering on your arrays only when you add one value.
Also as said in comments, you should do str[i] >= 'A' && str[i] <= 'Z' not str[i] > 'A' && str[i] < 'Z'

Checking if string is only letters and spaces

I wrote this simple code to check if a string is letters and spaces only
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#define N 100
int checkString(char str1[]);
void main()
{
char str1[N];
scanf("%s", str1);
printf("%d",checkString(str1));
getch();
}
int checkString(char str1[])
{
int i, x=0, p;
p=strlen(str1);
for (i = 0; i < p ; i++)
{
if ((str1[i] >= 'a' && str1[i] <= 'z') || (str1[i] >= 'A' && str1[i] <= 'Z') || (str1[i] == ' '))
{
continue;
}
else{ return 0; }
}
return 1;
}
This works fine when I type something like :
hello asds //returns 1
hello1010 sasd // return 0
but if I type anything after space it returns 1, like this :
hello 1220 //returns 1
blabla 11sdws // returns 1
Can someone please tell me why?
The function can be written more simpler and correctly if to use standard C functions isalpha and isblank declared in header <ctype.h> For example
#include <ctype.h>
//...
int checkString( const char s[] )
{
unsigned char c;
while ( ( c = *s ) && ( isalpha( c ) || isblank( c ) ) ) ++s;
return *s == '\0';
}
If you want to check whether a string contains white spaces then instead of function isblank you should use function isspace.
Take into account that it is not a good idea to use statement continue in such simple loops. It is better to rewrite the loop without the continue statement.
And instead of function scanf it is better to use function fgets if you want to enter a sentence The function allows to enter several words as one string until the Enter will be pressed.
For example
fgets( str1, sizeof( str1 ), stdin );
Take into account that the function includes the new line character. So after entering a string you should remove this character. For example
size_t n = strlen( str1 );
if ( n != 0 && str1[n-1] == '\n' ) str1[n-1] = '\0';
You forgot about the numbers
int checkString(char str1[]) {
int i, x=0, p;
p=strlen(str1);
for (i = 0; i < p ; i++)
if ((str1[i] >= 'a' && str1[i] <= 'z') || (str1[i] >= 'A' && str1[i] <= 'Z') || (str1[i] == ' ') || (str1[i] >= '0' && str1[i] <= '9')) {
continue;
} else return 0;
return 1;
}
Or better
#include <ctype.h>
...
int checkString(char str1[]) {
int i, x=0, p;
p=strlen(str1);
for (i = 0; i < p ; i++)
if (isalnum(str1[i]) || (str1[i] == ' '))
continue;
else return 0;
return 1;
}
This is happening because you are taking input with scanf(%s,&str). In this way of input only characters before space \n or other whitespace characters are stored. So your when you enter space the input is stored only upto space.
eg, you input helloo 1234
Your str stores only helloo and 1234 remains in buffer. Try using getchar().
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#define N 100
int checkString(char str1[]);
void main()
{
char str1[N];
int i=0;
while(1)
{
str1[i++]=getchar();
if(str1[i-1]=='\n') break;
}
printf("%d",checkString(str1));
getch();
}
int checkString(char str1[])
{
int i, x=0, p;
p=strlen(str1);
for (i = 0; i < p ; i++)
{
if ((str1[i] >= 'a' && str1[i] <= 'z') || (str1[i] >= 'A' && str1[i] <= 'Z') || (str1[i] == ' '))
{
continue;
}
else{ return 0; }
}
return 1;
}
When you use scanf("%s",str1);,you input hello 112,what str1 gets is hello.So you can use fgets(str1,N,stdin); to get the string.I think it will work.
There is a problem with your input String
scanf() which will take your input up to space only as it is whitespace
So when you input as hello 1234 actual input it is checking is hello . Check this by printing what you are taking input (that is print str1). Then you will come to know mistake in this code.
You can use gets or fgets to solve the problem.
if you print back the string you just scanf()ed you will notice that it only gets the first portion of all inputs. i.e. anything after the white space including the white space is ignored.
you could use getch() (windows) or getchar() (linux) to get every char input and terminate when you have a "\n" (newline)
source: http://www.cplusplus.com/reference/cstdio/scanf/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define N 100
int checkString(char str1[]);
void main()
{
int i = 0;
int c;
char str1[N];
memset(str1, 0, sizeof(str1));
do {
c = getchar();
str1[i++] = c;
} while ((c != '\n') && (i < (N - 1))); // (i < N - 1) reserves one place for null char
// last char is '\n' - remove it.
str1[i-1] = 0;
printf("Result: %s\n", checkString(str1) ? "letters and/or spaces only" : "other characters other than spaces and/or letters present");
}
// expects a null terminated string
int checkString(char str1[])
{
char* p = str1;
while (*p) {
if (!isalpha(*p) && !isspace(*p)) {
return 0;
}
p++;
}
return 1;
}

checking if the characters in a string are either alphabets, numbers, or special characters. in c

i have been working on a question which asks to check the numbers, alphabets or other special characters in a string.
for example if you are given two inputs. one is an integer which is string length and the second input is the string of characters.
input1: 6
input2: 4!hs%5.
the output should be: noaaon.
n stands for number, a stands for alphabets, and o stands for other.
#include<stdio.h>
#include<string.h>
int main(){
char c[20];
int n,i;
scanf("%d %s",&n,c);
for(i=1;c[i]<=n;i++)
if(i>='a' && i<='z')
printf("%c\n",(c[i]));
if(i=='!')
printf("%c \n",i);
else
{
printf("%c \n",);
}
return 0;
}
Why not just try something much simpler like isalpha() and isdigit() like
for( i = 0 ; i < n ; i++ )
{
if ( isalpha( c[i] ) )
// it is an alphabet, so some code
else if ( isdigit ( c[i] ) )
// it is a number , so some code
else
// it is some other character
}
This is actually much simpler than your current code
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char input[10];
char out[10];
int i;
memset(out, '\0', 10);
scanf("%s", input);
for(i = 0; i < strlen(input); ++i){
if( (c[i] >= 'a' && c[i] <= 'z') || (c[i] >= 'A' && c[i] <= 'Z') ){
out[i] = 'a';
}
else if(isdigit(c[i])){
out[i] = 'n';
}
else{
out[i] = 'o';
}
}
printf("%s", out);
return 0;
}
You can try it here: http://ideone.com/d8Id1Z

Resources