Converting ASCII code to a character value - c

I've just started learning how to program in C and I'm trying to make a program that accepts a number and uses it as an ASCII value to return the ASCII character associated with that value.
The program works when the parameters are predefined but when I introduce the scanf function it compiles but doesnt give me the same results.
Here is my code :
#include <stdio.h>
int main(void)
{
question2();
return 0;
}
int question2(void)
{
int myInt = 65;
scanf("%d", myInt);
char ch = myInt;
printf("%c",ch);
return 0;
}
Cheers and thanks for any help guys.

You need to pass the address of myInt to scanf() (the compiler should have emitted a warning for this):
scanf("%d", &myInt);
You should also check the return value of scanf() to ensure myInt was actually assigned to. scanf() returns the number of assignments made, which in this case is expected to be 1:
if (1 == scanf("%d", &myInt))
{
}
Note that int has a larger range values than a char so you should check that the value stored in myInt will fit into a char. There are macros defined in the header limits.h that you can use to check:
if (1 == scanf("%d", &myInt))
{
if (myInt >= CHAR_MIN && myInt <= CHAR_MAX)
{
printf("%c\n", (char) myInt);
}
else
{
printf("%d out-of-range: min=%d, max=%d\n",
myInt, CHAR_MIN, CHAR_MAX);
}
}
The compiler should have also emitted an implicit function declaration warning with respect to question2(). To correct, place the definition of question2(), or a declaration for question2(), prior to main().

Related

How to use isdigit function in C

I'm a complete beginner doing the cs50 course and I need to check if an argument from a user is a digit or not.
this is the code:
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
int main(void)
{
int i = 1;
if (isdigit(i) == 1)
{
printf("i is a digit");
}
else if (isdigit(i) == 0)
{
printf("i is not a digit");
}
return 0;
}
When I run this code I basically get a reverse of what I should be getting. When i is a number it prints out "i is not a number" and visa versa.
What am I doing wrong? I thought isdigit returns a non-zero value if it is a digit and 0 if not. Basically 1 being true and 0 being false. Is this not correct?
Much appreciated, Thanks!
What am I doing wrong?
"The isdigit function tests for any decimal-digit character". i with a value of 1 is not a digit character.
Try i = '1';. Then i will have the value of a digit character.
Code is testing the return value incorrectly. #tadman. is...() returns 0 or non-zero.
// if (isdigit(i) == 1)
if (isdigit(i))
Note: is...(int ch) functions are only valid for ch in the unsigned char range and EOF.
If you read the documentation for isdigit() you'll note the return value is expressed as:
Non-zero value if the character is a numeric character, zero otherwise.
In other words, don't compare to exactly one, that's not assured. Compare to non-zero.
That being said, this works on characters not integers, although in C the line is blurred. What you want is to ensure this is part of a string, like:
char* n = "12345";
if (isdigit(n[0]) == 0) {
...
}
In your case you're asking if ASCII character 1 is a digit, which it is not. That's the "Start of Heading" (SOH) control character.
isdigit is a character classification function.
It will return zero or non-zero depending on if a character (or rather, a character promoted to an int) is a digit.
For example:
int i = '1'; // Initialize to the character '1'
if (isdigit(i))
{
printf("i is a digit");
}
else
{
printf("i is not a digit");
}
Note that isdigit returns a non-zero value for digit characters, it doesn't have to be 1.
The argument to isdigit should be a single character, not a number. Thus your test code should more properly be
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = '1';
if(isdigit(c))
printf("c is a digit");
else
printf("c is not a digit");
return 0;
}
Your code should stick to the definition of the function, and not make assumptions about the returned value if it is a digit - the actual returned value may be implementation dependent, here's a better C-style, though as others have have said, you should be passing in a char, not an int - did the compiler not complain about that?
if (isdigit(i)) {
printf("i is a digit");
} else {
printf("i is not a digit");
}

strings and isdigit function

#include<stdio.h>
#include<string.h>
#include<ctype.h>
int digit(s1);
int main()
{char s1[10];
printf("\n Type anything you want:\n");
gets(s1);
printf("The number of digits is:%d",digit(s1));
return 0;
}
int digit(char* s1)
{
int i=0;
while(*s1)
{
i+= !!isdigit(*s1++);
}
return i;
}
This is my code, I need to find out is the element that I give a digit or not.
I change it into void digit and it runs perfectly now.
isdigit is a standard C function declared in <ctype.h>. Your function conflicts with it. Choose a different name for your function.
That will avoid the compiler message about conflicting types, but there are other errors in your program you will need to fix.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int count_digits(const char *s1);
int main()
{
char s1[20];
printf("\n Type anything you want:\n");
fgets(s1, sizeof(s1), stdin);
printf("The number of digits is:%d", count_digits(s1));
return 0;
}
int count_digits(const char* s1)
{
int count = 0;
while(*s1)
{
count += !!isdigit(*s1++);
}
return count;
}
The code you provided has several major issues. If the lecture says to use gets(), throw it into the trash, use fgets() instead. The reason why, you can find in this link:
Why is the gets function so dangerous that it should not be used?
Apart from that, The lecture seems to not even provided you the knowledge to correctly pass parameters or to output values of variables correctly.
I recommend you to read a good C starting book, f.e. this. A list of recommended books can be also found here:
The Definitive C Book Guide and List
To only focus one issue, the output:
printf("There are %d digits in your string.");
This use of printf() is incorrect. Where shall the value specified by %d come from? The %d format specifier is missing a corresponding argument which points to an integer value or an int variable, like:
int a = 10;
printf("a = %d",a);
%d requires a matching argument of type int to actually print a value. Else the behavior is undefined.
This shall in all cases give a diagnostic. Never ignore compiler warnings.
Why should I always enable compiler warnings?

Variable value is reset inside a loop in C

I have a case in which I have to identify if a number is positive, negative or zero and count how many times each of these cases happen. The code I wrote is this:
#include
#include
#include
using namespace std;
int main(int argc, char *argv[])
{
char opcion = 's';
int positivos = 0;
int negativos = 0;
int ceros = 0;
//int ceros2 = 0;
int temporal;
do{
printf("Enter a number: ");
scanf("%d",&temporal);
if(temporal >= 0)
{
if(temporal==0)
{
ceros ++;
}
else
{
positivos ++;
}
}
if(temporal < 0)
{
negativos ++;
}
printf("Do you want to enter another number? (s/n)");
scanf("%s",&opcion);
}
while(opcion == 's' || opcion=='S');
printf("you have %d possitive numbers \n",positivos);
printf("you have %d negative numbers \n",negativos);
printf("you have %d zero \n",ceros);
return 0;
}
If I run the code as it is, the number of zeroes will always be zero, but if you uncoment the line 13 int ceros2 = 0; (my logic was "let's declare another initializaed variable and see what happens") then the program will count the zeroes as expected. Why do i have to declare a useless variable in order to the program make the count?
What is C compiler doing with the code that does not respect the value of the last declared and initialized variable unless you declare a new initialized variable?
You are asking scanf() to read in a C string, which, if the user types a character, will contain both that character and the null terminator. You have provided only a single character's worth of storage. So, the null terminator doesn't fit but it gets stored somewhere. As it happens, it's clobbering other data that happens to be next to opcion on the stack and that happens to be your ceros variable.
Declaring another variable has reorganized the layout of data on the stack and changes what gets clobbered, so you're not noticing it. It's still writing out of bounds, though.
You could use a format string of "%c" to read a single character.

Cesar Cipher out of bounds in Array

Guys i found this caesar cipher code in some site.... But when i run it its showing segmentation fault in online compilers..but in c compiler tat i'm using its showing processor fault... can anyone pls point out the wrong in this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define caesar(x) rot(13, x)
#define decaesar(x) rot(13, x)
#define decrypt_rot(x, y) rot((26-x), y)
void rot(int c, char *str)
{
int l = strlen(str);
const char *alpha[2] = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
int i;
for (i = 0; i < l; i++)
{
if (!isalpha(str[i]))
continue;
str[i] = alpha[isupper(str[i])][((int)(tolower(str[i])-'a')+c)%26];
}
}
int main()
{
char str[] = "This is a top secret text message!";
printf("Original: %s\n", str);
caesar(str);
printf("Encrypted: %s\n", str);
decaesar(str);
printf("Decrypted: %s\n", str);
return 0;
}
Your code is correct except for one detail, which might be confusing for a newbie.
It is ok to assume that the function isupper() returns a boolean value 1 or 0, but if you check the documentation it says A value different from zero (i.e., true) if indeed c is an uppercase alphabetic letter. Zero (i.e., false) otherwise.
This and the fact that isupper() is returning an int and not a _Bool is causing the problem.
int isupper ( int c );
When returning true isupper() might return any non_zero value. In my case it returns 8 ( a specific bit-field ). Probably the same in yours.
All you have to do is cast the return of isupper() to _Bool
printf("%d %d" ,(_Bool)isupper('A') , ((int)(tolower(str[i])-'a')+c)%26 ) ;
The problem is most likely your use of isupper as index. It's not guaranteed to return 1 for true values, just that it will return "true" (which may be any non-zero value).
You can solve this by using the ternary expression:
alpha[isupper(str[i]) ? 1 : 0][...]
In the first iteration of your loop, you are trying to write to alpha[256][6], (isupper does not always return 0 or 1)
isupper returns: A value different from zero (i.e., true) if indeed c is an
uppercase alphabetic letter. Zero (i.e., false) otherwise.
alpha[isupper(str[i]) != 0][...] will do the trick
Also note that you should always cast the argument you pass to
isupper(), isalnum(), etc. to unsigned char

What happens when using scanf("%d", &c) while c is a char?

the code is like this:
char c;
scanf("%d", &c);
inputting 3...
My guess is that when 3 is inputted, it is as type int;
and then type-demoted to char and assigned to c;
I print the value of c in specifier %d yielding 3, seems to be as expected;
but printing the value of c with specifier %c yields --a blank-- on the terminal;this is one question...(1);
to test more I furthermore declare a variable ch with type char and initialized it like this:
char ch = 1;
and the test is like this:
(i&j)? printf("yes") : printf("no");
and the result is "no"
I print out the value of i&j, and it is 0
but 1&3 should be 1? this is another question....(2);
my question is (1) and (2)
You're actually invoking undefined behavior doing that.
By using the format string %d, you're telling scanf to expect an int* as a parameter and you're passing it a pointer to a single character. Remember that scanf has no further type information on what you're passing it than what you're putting in the format string.
This will result in scanf attempting to write an int sized value to memory at an address that points to a char sized reservation, potentially (and for most architectures) writing out of bounds.
After invoking UB, all bets are off on your further calculations.
Suppose that scanf() were not a varargs-function, but a plain ordinary function taking a pointer-to-int as the 2nd argument:
int noscanf(char *format, int *ptr)
{
*ptr = 42;
return 1;
}
int main(void)
{
char ch;
int rc;
// This should *at least* give a warning ...
rc = noscanf("Haha!" , &ch);
return 0;
}
Now, scanf() is a varargs function. The only way for scanf() to determine the type of the (pointer) arguments is by inspecting the format string. And a %d means : the next argument is supposed to be a pointer to int. So scanf can happily write sizeof(int) bytes to *ptr.
I can't see a variable jthere. So i&j will be 0. And yes, if i == 1 and j == 3 then i & j == 1.
(i&j)? printf("yes") : printf("no");
statement gives the output yes,for i=1 and j=3.
And for (1) question ASCII 3 is for STX char which is not printable.

Resources