My professor gave me some exercises in C language... In one of them I have to pass a string as an argument to a function, this function will verify the existence of lower case letters in the array and convert it into upper case letter;
Actually there's a function to do such a thing, but I can't use string.h.
Does anyone have an idea to do it?
void converterup(char palavra[])
{
int i;
for(i = 0; i < 10; i++)
{
if(palavra[i] != 'a')
{
palavra[i] == 'A';
}
}
Would be something like this?
you need to include <ctype.h> before using function toupper, then use it like in example below (I edited your code, need to adjust it for your needs):
for(i = 0; i < 10; i++){
palavra[i] = toupper(palavra[i]);
}
this loop will convert 10 first characters to their upper ascii equivalents
or if you cannot use standard functions, you can use function like this:
char myUpperChar(char x){
const int delta = 'a' - 'A'; //'a' has ascii code 97 while 'A' has code 65
if(x <= 'z' && x >= 'a'){
x -= delta;
}
return x;
}
If a character is between 'a' and 'z', you could just add ('A' - 'a') to it to convert it to upper.
char input, output;
int diff = 'A' - 'a';
output = input;
if ('a' <= input && input <= 'z')
output += diff;
return output;
I guess your professor is expecting something more basic without external functions, like this.
char str[] = "hello";
int len = sizeof(str) / sizeof(char);
int i;
for(i = 0; i < len; i++) {
int ascii = str[i];
if(ascii >= 97 && ascii <= 122) {// 97 => 'a' and 122 => 'z' in ascii
str[i] = (char) (ascii - 32); // 32 is the ascii substraction of lower
} // and upper letters 'a' - 'A'
}
Then output would be:
HELLO
function will verify the existence of lower case letters in the
array and convert it into upper case letter;
I can't use string.h.
Then you have to do conversion yourself. Take a look at the ASCII chart.
Then you can notice that small and capital letters are 0x40 apart.
0x40 happens to be space ' ';
Loop through your array and convert only the small letters
arr[i] <= 'z' && arr[i] >= 'a'
remember that small and capital letters are ' ' apart.
arr[i] = arr[i] - ' ' ;
advance to next character in the array by increasing the index i++ and stop when you encounter the end of the string arr[i]=='\0'.
#include <stdio.h>
void converterup(char arr[])
{
size_t i = 0;
if(arr == NULL) return;
while(arr[i]) // loop till the '\0'; this is equivalent to `arr[i]!='\0'`
{
if(arr[i] <= 'z' && arr[i] >= 'a'){
arr[i] = arr[i] - ' ' ;
}
i++;
}
}
int main(void)
{
char str[] = "Hello World!";
converterup(str);
printf("%s",str);
return 0;
}
Test:
HELLO WORLD!
Check out my code guys, is it acceptable?
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
void strupr(char palavra[])
{
int i;
for(i = 0;palavra[i] > 60 && palavra[i] < 122; i++)
{
printf("%c", palavra[i] - 32);
}
}
int main(void)
{
setlocale(LC_ALL, "");
char palavra[10];
printf("Insira uma palavra maiúsculas: "); gets(palavra);
printf("Valor com conversão: ");
strupr(palavra);
return 0;
}
Related
I’m working on a project called readability. the user input a text and the code should then use the coleman-liau function to determine the reading level. But in order to use this fuktion you have to determine the number of words, letters and sentences. Right now I’m busy counting the letters. So I wanted to ask how to count individual characters in c. right now this is my code:
int count_letters (string text)
{
int count_letters = 0;
int numb = 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (text[i] != '')
{
count_letters++;
}
}
return count_letters;
}
You can either use isalpha() or "improvise".
This will work for the ASCII character set:
#include <stdio.h>
int count_letters(const char *str)
{
int count = 0, i = 0;
for (; str[i] != '\0'; i++)
{
if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z'))
{
/* any character within this range is either a lower or upper case letter */
count++;
}
}
return count;
}
int main(void)
{
char *str = "Hello\n world hello123#";
printf("%d\n", count_letters(str));
return 0;
}
or use isalpha(), also supports your current locale.
#include <ctype.h>
int count_letters(const char *str)
{
int count = 0, i = 0;
for (; str[i] != '\0'; i++)
{
if (isalpha((unsigned char)str[i]))
{
count++;
}
}
return count;
}
EDIT: As Andrew mentioned, to be pedantic, you better pass an unsigned char as argument to isalpha() to avoid any undefined behavior that might arise due to the signed type of str.
I have a problem with my homework. I need to count quantity of upper case and quantity of vowels in string. Unfortunately, it always returns number 0 which looks as it doesn't change in function. Everything works until this one.
Here is my code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *StringChange(char *text, int *upper, int *chars);
int main(void) {
char text[40];
int upper, chars;
puts("Type a string");
gets(text);
StringChange(text, &upper, &chars);
puts("Change words to start with upper case and change white spece to *");
puts(text);
printf("Quantity of upper case in string: %d\n", upper);
printf("Quantity of vowels: %d", chars);
getch();
return 0;
}
char *StringChange(char *text, int *upper, int *chars) {
int i, length;
length = strlen(text);
for (i = 1; i <= length; i++) {
if (text[i - 1] == '*' && (text[i] >= 'a' && text[i] <= 'z')) {
text[i] = text[i] - 32;
}
if (text[i] == ' ') {
text[i] = '*';
}
if (text[i] >= 'A' && text[i] <= 'Z') {
*upper = *upper + 1;
/* *upper++; that also doesn't work */
}
if (text[i] == 'a' || text[i] == 'e' || text[i] == 'i' || text[i] == 'o' || text[i] == 'u' || text[i] == 'y') {
*chars = *chars + 1;
/* *chars++; that also doesn't work */
}
}
if (text[0] >= 'a' && text[0] <= 'z') {
text[0] = text[0] - 32;
}
return (text);
}
I tried your code and I do get non-zero results -- depending on the input, of course, so maybe you are only testing on strings that produce zero.
However, the results are not always correct. There are two problems I found in the code:
1) As pointed out in a comment, you should initialize upper and chars to 0.
2) You are starting the loop at index 1, not index 0. I think you did this so you could look at text[i-1] inside the loop, but it is causing you to exclude the first character from your totals. You should start the loop index and 0 and figure out a different way to handle it within the loop. (Hint - note that the first if within the loop and the one following the loop have similar conditions and the same body.)
There are multiple issues in your code:
you should never use gets().
the variables upper and chars are not initialized
the function StringChange make a special case of text[0] but does not update the counts for this initial byte.
you hard code the conversion of lowercase to uppercase for ASCII.
you should stop at the end of the string
all white space is not replaced, on whitespace followed by a lowercase letter.
uppercase vowels should be counted too.
Here is a modified version:
#include <stdio.h>
char *StringChange(char *text, int *upper, int *chars);
int main(void) {
char text[200];
int upper, vowels;
puts("Type a string");
if (fgets(text, sizeof text, stdin)) {
StringChange(text, &upper, &chars);
puts("Change words to start with upper case and change white space to *");
puts(text);
printf("Quantity of upper case in string: %d\n", upper);
printf("Quantity of vowels: %d\n", vowels);
}
getchar();
return 0;
}
char *StringChange(char *text, int *upper, int *vowels) {
int i, at_start = 1;
*upper = *vowels = 0;
for (i = 0; text[i] != '\0'; i++) {
char c = text[i];
if (at_start && c >= 'a' && c <= 'z') {
c += 'A' - 'a';
text[i] = c;
}
if (c == ' ') {
c = '*';
text[i] = c;
at_start = 1;
} else {
at_start = 0;
}
if (c >= 'A' && c <= 'Z') {
(*upper)++; // *upper++ would just increment the pointer, leading to undefined behavior
}
if (strchr("aeiouyAEIOUY", c) {
(*vowels)++;
}
}
return text;
}
I had received this assignment last month and ended up getting it wrong because of the problem I will state after this. Currently, I am doing Caesar's Cipher and I believe I have the right format. I ask the user for a string and I encrypted with a key == 3. However, I want to loop around the alphabet if the plaintext letter is X, Y, Z, x, y, or z. But, when I put those any of those characters in, I do not get A, B, and C, but ]... and other braces. Any hints to fix the problem.
Thank you!
void main()
{
int key = 3;
char string[256];
int i = 0;
printf("Enter the string you want encrypted\n");
fgets(string, sizeof(string), stdin);
for (i = 0; i < strlen(string); i++) {
if (string[i] == ' ') {;}
else if ((string[i] >= 'a' && string[i] <= 'z' || string[i] >= 'A' && string[i] <= 'Z')){
string[i] = string[i] + key;
}
}
printf("Cipher text:%s",string);
}
You need to look at the ASCII table: http://www.asciitable.com/. You're using an ASCII encoding of the characters.
Z has a decimal value of 90, so 93 is ']'. You need to manually wrap back around to the beginning of the alphabet. This is best done with a modulo and adding the ASCII value of the first alphabetic character. It's up to you how you wrap capital letters (back to 'a' or to 'A').
You need to convert the character to its position in the alphabet, then find the result modulo 26 (alphabet length), then convert it back to the character. Something like:
char base = 0;
if(string[i] >= 'a' && string[i] <= 'z'){
base = 'a';
}else if(string[i] >= 'A' && string[i] <= 'Z'){
base = 'A';
}
if(base){
string[i] = ((string[i] - base) + key) % 26 + base;
}
You almost got it:
#include <stdio.h>
#include <string.h>
int main() {
char string[256];
int i = 0;
int key = 3;
const int num_letters = 26;
printf("Enter the string you want encrypted\n");
fgets(string, sizeof(string), stdin);
for (i = 0; i < strlen(string); i++) {
if (string[i] >= 'a' && string[i] <= 'z') {
string[i] = 'a' + (string[i] - 'a' + key) % num_letters;
}
else if (string[i] >= 'A' && string[i] <= 'Z') {
string[i] = 'A' + (string[i] - 'A' + key) % num_letters;
}
}
printf("Encrypted: %s\n", string);
return 0;
}
Enter the string you want encrypted
Zorro
Encrypted: Cruur
In C you can use the modulo operator % to wrap around, as shown above. Good luck!
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
The new string should contain only the alphabetic characters from the existing string in the same order. Non-alphabetic characters should be not be copied. If s is a null pointer, return a null pointer.
Example input:
"Ready... aim... fire!"
Output:
Readyaimfire
I don't know why in my first for loop, the code never enters the if statement. I'm also not sure if I allocated the memory for the new string correctly. Thanks for any help :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *alphabetic (const char *s);
char *alphabetic (const char *s)
{
char *newChar;
int i;
char n = 0;
long length = strlen(s);
for(i=0; i<length; i++)
{
if( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') )
{
n++;
}
}
newChar = (char*)malloc(sizeof(char)*n);
for(i=0; i<length; i++)
{
if( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') )
{
newChar[i] = s[i];
}
}
return newChar;
}
int main (void)
{
char *a, *b, *c;
a = alphabetic ("Ready... aim... fire!");
b = alphabetic ("***");
c = alphabetic ("*a*b*c*");
printf ("%s\n", a);
printf ("%s\n", b);
printf ("%s\n", c);
free(a);
free(b);
free(c);
return 0;
}
The conditional of the first if and the conditional of the second if are such that if one is true then the other is false. Hence, you never get to the line
n++;
You need
if ( (s[i] <= 122 && s[i] >= 97) || (s[i] <= 90 && s[i] >= 65) )
To make the code more readable, you can make it:
if ( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') )
If you have the option of using the standard library, you can just use:
if ( isalpha(s[i]) )
BTW, the line
s = s + i;
is going to mess things up. As you iterate through the loop, you'll end up skipping parts of the input string. Remove that line.
You Can use a single loop of that
int j = 0; //take integer variable
for(i=0; i<length; i++)
{
if( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') )
{
//n++; //Remove this
newChar[j] = s[i];
j++;
}
}
Things about your code:
n should be n+1 to accommodate '\0' character
2nd for loop: you need to have another variable say j =0 and incremented on every match. You can't use i for the newChar array as in the original array s,since i might point to an address that's outof bounds in the newChar array.For ex: ready...aim, newchar # elements 8 while s =11
So saying newChar[8]=s[8] is wrong,rather it should be newChar[5]=s[8].
Posting the corrected code:
char *alphabetic (const char *s)
{
char *newChar;
int i,j=0; //Change1: extra variable j to keep a track of elements for newChar
char n = 0;
long length = strlen(s);
for(i=0; i<length; i++)
{
if( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') )
{
n++;
}
}
newChar = (char*)malloc(sizeof(char)*(n+1)); // Change2: n+1 instead of n
for(i=0; i<length; i++)
{
if( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') )
{
newChar[j++] = s[i]; //Change3: j instead of i
}
}
newChar[j]='\0'; //Termination of strings
return newChar;
}
I can't tell you why your code doesn't enter the if statement because you didn't provide the test case (input data) on which the algorithm does not enter the if statement. What I can tell you is that it won't do what you want it to do. Let's break down the for loop for a moment here:
it says "make variable i = 0, then, while i is smaller then the length of char array s, do some stuff then increment i". This is a very handy way to parse a char array. That's just fine and dandy, but inside the for loop, the first instruction is s = s + i. What that will do is move the pointer s forward by i characters at each iteration. Keep in mind that i will increase with time. Say we give that function the char * "This is a sentence.". The function strlen(s) will return 19 (which will be stored in length) and thus the for loop will iterate 19 times, with i taking values from 0 to 18 including. Let's see what's happening to s in there. First time, *s value is T. When you make s = s + i (i = 0), *s will still be T. T's ascii code is 84 and the if checks for values between 97 and 122 (including). So that's that for the first iteration. Then i becomes 1. And s moves one position further, thus *s will be 'h'. The ASCII code for the letter h is 104, so it enters the first if (because it is beween 122 and 97). Then, you ask if s[i] is beween 90 and 65. Now, because you incremented s, *s is 'h', but i == 1 at this point and thus s[i] is actually 'i' (whose ASCII code is 105 and thus never entering that loop). So if you wanna increment your n with your given algorithm I would say you need an input test case looking like so: "ThIsiSaSENtENCE". What you want is a clean string parsing for loop with another clean if to check whether the current character is a letter:
for(i = 0; i < length; i++)
{
if((s[i]<='Z' && s[i] >= 'A') || (s[i]<='z' && s[i]>='a'))
n++;
}
This will count how many letters are there in your char array s.
EDIT:
If you wanna remove those characters which are not letters and return the new string then you might wanna try something like this (NOT OPTIMAL):
char *copyStringByLetter(char *arg, int size)
{
int i = 0;
int n = 0;
for(i = 0; i < size; ++i){
if((s[i]<='z' && s[i]>='a')||(s[i]<='Z' && s[i]>='A'))
n++;
}
char *result = malloc(n+1); //need #include <stdlib.h>
if(!result){
fprintf(stderr, "Error alocating memory!");
exit(EXIT_FAILURE) //you need #include <stdlib.h> for this
}
int j = 0;
for(i = 0; i < size; i++){
if((s[i]<='z' && s[i]>='a')||(s[i]<='Z' && s[i]>='A')){
result[j] = s[i];
j++;
}
}
result[j] = '\0' //terminate the array
return result;
}
If you want to ask me why I am sending the length of char array as an argument, it is to prevent char overruns (who happen more often than you might think)