I'm trying to compare two chars to see if one is greater than the other. To see if they were equal, I used strcmp. Is there anything similar to strcmp that I can use?
A char variable is actually an 8-bit integral value. It will have values from 0 to 255. These are almost always ASCII codes, but other encodings are allowed. 0 stands for the C-null character, and 255 stands for an empty symbol.
So, when you write the following assignment:
char a = 'a';
It is the same thing as this on an ASCII system.
char a = 97;
So, you can compare two char variables using the >, <, ==, <=, >= operators:
char a = 'a';
char b = 'b';
if( a < b ) printf("%c is smaller than %c", a, b);
if( a > b ) printf("%c is smaller than %c", a, b);
if( a == b ) printf("%c is equal to %c", a, b);
Note that even if ASCII is not required, this function will work because C requires that the digits are in consecutive order:
int isdigit(char c) {
if(c >= '0' && c <= '9')
return 1;
return 0;
}
In C the char type has a numeric value so the > operator will work just fine for example
#include <stdio.h>
main() {
char a='z';
char b='h';
if ( a > b ) {
printf("%c greater than %c\n",a,b);
}
}
I believe you are trying to compare two strings representing values, the function you are looking for is:
int atoi(const char *nptr);
or
long int strtol(const char *nptr, char **endptr, int base);
these functions will allow you to convert a string to an int/long int:
int val = strtol("555", NULL, 10);
and compare it to another value.
int main (int argc, char *argv[])
{
long int val = 0;
if (argc < 2)
{
fprintf(stderr, "Usage: %s number\n", argv[0]);
exit(EXIT_FAILURE);
}
val = strtol(argv[1], NULL, 10);
printf("%d is %s than 555\n", val, val > 555 ? "bigger" : "smaller");
return 0;
}
You are going to have to roll your own way of comparing characters. The C standard only mandates that the digits 0 to 9 have an easy way to compare them using basic c1 > c2 style comparison. This is NOT guaranteed to work for other characters like letters. (Although in practice it often will for simple ASCII ranges like a-z and A-Z.)
One way to do it, often unsatisfactory, is to convert the characters to strings and use strcoll().
Related
I'm trying to compare two chars to see if one is greater than the other. To see if they were equal, I used strcmp. Is there anything similar to strcmp that I can use?
A char variable is actually an 8-bit integral value. It will have values from 0 to 255. These are almost always ASCII codes, but other encodings are allowed. 0 stands for the C-null character, and 255 stands for an empty symbol.
So, when you write the following assignment:
char a = 'a';
It is the same thing as this on an ASCII system.
char a = 97;
So, you can compare two char variables using the >, <, ==, <=, >= operators:
char a = 'a';
char b = 'b';
if( a < b ) printf("%c is smaller than %c", a, b);
if( a > b ) printf("%c is smaller than %c", a, b);
if( a == b ) printf("%c is equal to %c", a, b);
Note that even if ASCII is not required, this function will work because C requires that the digits are in consecutive order:
int isdigit(char c) {
if(c >= '0' && c <= '9')
return 1;
return 0;
}
In C the char type has a numeric value so the > operator will work just fine for example
#include <stdio.h>
main() {
char a='z';
char b='h';
if ( a > b ) {
printf("%c greater than %c\n",a,b);
}
}
I believe you are trying to compare two strings representing values, the function you are looking for is:
int atoi(const char *nptr);
or
long int strtol(const char *nptr, char **endptr, int base);
these functions will allow you to convert a string to an int/long int:
int val = strtol("555", NULL, 10);
and compare it to another value.
int main (int argc, char *argv[])
{
long int val = 0;
if (argc < 2)
{
fprintf(stderr, "Usage: %s number\n", argv[0]);
exit(EXIT_FAILURE);
}
val = strtol(argv[1], NULL, 10);
printf("%d is %s than 555\n", val, val > 555 ? "bigger" : "smaller");
return 0;
}
You are going to have to roll your own way of comparing characters. The C standard only mandates that the digits 0 to 9 have an easy way to compare them using basic c1 > c2 style comparison. This is NOT guaranteed to work for other characters like letters. (Although in practice it often will for simple ASCII ranges like a-z and A-Z.)
One way to do it, often unsatisfactory, is to convert the characters to strings and use strcoll().
first post (as you would know) and the form tells me that my title is bad and will get downvoted but I can't do better :) I've worked on this a bunch already.
I'm trying to cipher text by adding a number given in the command line to a string.
Why does
include <stdio.h>
int main(int argc, char * argv[])
{
printf("%i", argc);
char k = argv[1][0];
printf("%c", k);
char * s = "a";
printf("%c", s[0] + 0);
}
correctly print "a" (besides for printing argc and k)
but when the last line is
printf("%c", s[0] + k);
it just prints argc and k and then nothing. I wanted it to print 20a (when running ./question 0).
( I tried
char k = 0;
char * s = "a";
printf("%c", s[0] + k);
and that does work :( )
It seems like the fact that k is coming from argv is the issue but I don't have any idea why (not that I really understand any of this)
Thanks!
argv and argc and "a" are all red herrings. They have nothing to do with the problem. The problem lies in not understanding the difference between two character values, '0' and 0 (the latter is aso known as '\0').
In order to understand the difference I suggest experimenting with this program:
#include <stdio.h>
int main(void) {
char a = 'a', b = '0';
printf ("as char: a=%c b=%c sum=%c\n", a, b, a+b);
printf ("as int: a=%d b=%d sum=%d\n", a, b, a+b);
}
Use different values for b, including 0, 1, '0' and '1' and see what happens.
The answer is very simple.
The ASCII code of 'a' is 97.
Assuming only the printable characters in the arguments, the lowest printable ASCII code from the argv is 32.
97+32 = integer overflow which is UB - on ideone.com system it is -127
you can try yourself
https://ideone.com/D8DLcy
#include <stdio.h>
int main(void) {
for(char x = 32; x < 127; x++)
{
char m = 'a' + x;
printf("'a' + %c = char value in decimal is:%hhd - and the char is%c\n", x, m, m);
}
return 0;
}
The problem is that the expression s[0] + k is that adding a letter and a number together (conceptually speaking, ignoring the data types for a minute) can easily result in a value that is past the end of the alphabet, and printing it out as if it was a letter isn't necessarily going to work.
Bonus problem: reading the command line parameter into a single character isn't giving you a value of 0, but '0' which has a numerical value of 48. You can't just pull out the first character from the string. What if the user runs the program and passes 10 as a parameter?
You need to make sure that the result of your calculation is within the bounds of the alphabet.
As suggested by commenters above, take a look at the ASCII table, and try using some character constants sich as 'a' 'z' 'A' and 'Z' to modify the result
From the information you provided, it looks like you're implementing a simple shift cipher. Note the use of modulo for cases where the input for k is greater than 25.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING 16
int main(int argc, char *argv[])
{
char num[MAX_STRING];
char * s = "a";
int k;
if (argc == 2)
{
snprintf(num,MAX_STRING, argv[1], 10);
k = (int)strtol(num, NULL, 10) % 26;
printf("%c\n", s[0] + k);
}
else
{
fprintf(stderr,"Invalid number of arguments\n");
return(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}
I am trying to convert an integer(greater than 9 as below 9 it converts easily by the below process) to character. But after conversion I get some characters like '?'..below is the code:
#include <stdio.h>
int main(void) {
int i = 15;
char c;
c=i+'0';
printf("%c", c);
return 0;
}
output: ?
Expected output: 15
"15" are two characters. You would have to convert it digit by digit.
It won't work because you have two digit number. Such simple convertion will work for numbers 0-9 but not for greater. You can use itoa function. Example of use is in the link provided
Making a string from an integer is not possible directly, the reason why this works
int number = 2;
char character = number + '0';
fprintf(stdout, "%c\n", character);
is because '0' is the ascii value that represents the number 0 which is 48, and since they appear in order in the ascii table, adding the number to it will give you the ascii value of the number.
But 15 consists of 2 ascii values, a quick way to perform the conversion is to use an array, like this
char string[3];
int number;
int result;
number = 15;
result = snprintf(string, sizeof(string), "%d", number);
if (result >= sizeof(string))
fprintf(stdout, "the string was truncated, there is no space to store the result");
else if (result < 0)
fprintf(stderr, "an error occurred\n");
else
fprintf(stdout, "%s\n", string);
You have 2 digits which is why printing it out like that doesn't work. If you want to convert the int to a string use sprintf :
int i= 15;
char str[15];
snprintf(str, 15, "%d", i); // str now contains "15"
I've been trying to fix this source code for a long time but the compiler still shows error.
#include<cs50.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
int main(int argc, char* argv[])
{
char ptext[40];
int i=0;
if(argc!=2)
{
printf("invalid key");
return 1;
}
else
printf("enter plain text\n");
ptext= GetString();
int key= atoi(argv[1]);
int n=strlen(ptext);
while( ptext[i]!= '\0')
{
if( ptext[i]>65 && ptext[i]<90)
{
int c= (ptext+key)%26;
int d= c+26;
printf("%c", d);
}
else if( ptext[i]>97 && ptext[i]<122)
{
int c= (ptext+key)%26;
int d= c+26;
printf("%c", d);
}
else
{
printf("%c",ptext[i]);
}
i++;
}
}
The errors it shows while compiling are array type 'char [40]' is not assignable (which does nothing even when a number smaller than 40 is entered or the brackets are left empty), and invalid operands to binary operation int c = (ptext+key)%26.
Couple of things:
What you really need ptext to be is a char*, not an array. I'm guessing GetString() will return a string, or a char[]/char* what have you. Depending on how GetString() works, you might need to test for a NULL return.
At the line int c= (ptext+key)%26; it appears you're trying to process ptext[i]. Perhaps you forgot to include the indexer?
And just a suggestion, if using ASCII, at lines like if( ptext[i]>65 && ptext[i]<90) you can use the char values themselves instead of numbers so you don't have to pore over the ASCII tables. You can do it like so: if(ptext[i] >= 'A' && ptext[i] <= 'Z').
Notice above, also, I changed the comparators > and < to >= and <=. Are not 'A' and 'Z' valid characters?
When using the modulo as you are, for a Caesar Cipher, you want the index of the character in the alphabet. So in the case it's a capital letter, you want to subtract 'A' (or as you so aptly know, 65 in ASCII) like so : `int c= (ptext[i] - 'A' + key) % 26;'.
Change char ptext[40]; to char *ptext;
The GetString() function from cs50.h dynamically allocates some memory and returns a pointer to it. In C it is not possible to assign to an array, nor to return an array.
When you have finished accessing the string's contents, do free(ptext); to release the memory used.
I want to convert a char array[] like:
char myarray[4] = {'-','1','2','3'}; //where the - means it is negative
So it should be the integer: -1234
using standard libaries in C. I could not find any elegant way to do that.
I can append the '\0' for sure.
I personally don't like atoi function. I would suggest sscanf:
char myarray[5] = {'-', '1', '2', '3', '\0'};
int i;
sscanf(myarray, "%d", &i);
It's very standard, it's in the stdio.h library :)
And in my opinion, it allows you much more freedom than atoi, arbitrary formatting of your number-string, and probably also allows for non-number characters at the end.
EDIT
I just found this wonderful question here on the site that explains and compares 3 different ways to do it - atoi, sscanf and strtol. Also, there is a nice more-detailed insight into sscanf (actually, the whole family of *scanf functions).
EDIT2
Looks like it's not just me personally disliking the atoi function. Here's a link to an answer explaining that the atoi function is deprecated and should not be used in newer code.
Why not just use atoi? For example:
char myarray[4] = {'-','1','2','3'};
int i = atoi(myarray);
printf("%d\n", i);
Gives me, as expected:
-123
Update: why not - the character array is not null terminated. Doh!
It isn't that hard to deal with the character array itself without converting the array to a string. Especially in the case where the length of the character array is know or can be easily found. With the character array, the length must be determined in the same scope as the array definition, e.g.:
size_t len sizeof myarray/sizeof *myarray;
For strings you, of course, have strlen available.
With the length known, regardless of whether it is a character array or a string, you can convert the character values to a number with a short function similar to the following:
/* convert character array to integer */
int char2int (char *array, size_t n)
{
int number = 0;
int mult = 1;
n = (int)n < 0 ? -n : n; /* quick absolute value check */
/* for each character in array */
while (n--)
{
/* if not digit or '-', check if number > 0, break or continue */
if ((array[n] < '0' || array[n] > '9') && array[n] != '-') {
if (number)
break;
else
continue;
}
if (array[n] == '-') { /* if '-' if number, negate, break */
if (number) {
number = -number;
break;
}
}
else { /* convert digit to numeric value */
number += (array[n] - '0') * mult;
mult *= 10;
}
}
return number;
}
Above is simply the standard char to int conversion approach with a few additional conditionals included. To handle stray characters, in addition to the digits and '-', the only trick is making smart choices about when to start collecting digits and when to stop.
If you start collecting digits for conversion when you encounter the first digit, then the conversion ends when you encounter the first '-' or non-digit. This makes the conversion much more convenient when interested in indexes such as (e.g. file_0127.txt).
A short example of its use:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int char2int (char *array, size_t n);
int main (void) {
char myarray[4] = {'-','1','2','3'};
char *string = "some-goofy-string-with-123-inside";
char *fname = "file-0123.txt";
size_t mlen = sizeof myarray/sizeof *myarray;
size_t slen = strlen (string);
size_t flen = strlen (fname);
printf ("\n myarray[4] = {'-','1','2','3'};\n\n");
printf (" char2int (myarray, mlen): %d\n\n", char2int (myarray, mlen));
printf (" string = \"some-goofy-string-with-123-inside\";\n\n");
printf (" char2int (string, slen) : %d\n\n", char2int (string, slen));
printf (" fname = \"file-0123.txt\";\n\n");
printf (" char2int (fname, flen) : %d\n\n", char2int (fname, flen));
return 0;
}
Note: when faced with '-' delimited file indexes (or the like), it is up to you to negate the result. (e.g. file-0123.txt compared to file_0123.txt where the first would return -123 while the second 123).
Example Output
$ ./bin/atoic_array
myarray[4] = {'-','1','2','3'};
char2int (myarray, mlen): -123
string = "some-goofy-string-with-123-inside";
char2int (string, slen) : -123
fname = "file-0123.txt";
char2int (fname, flen) : -123
Note: there are always corner cases, etc. that can cause problems. This isn't intended to be 100% bulletproof in all character sets, etc., but instead work an overwhelming majority of the time and provide additional conversion flexibility without the initial parsing or conversion to string required by atoi or strtol, etc.
So, the idea is to convert character numbers (in single quotes, e.g. '8') to integer expression. For instance char c = '8'; int i = c - '0' //would yield integer 8; And sum up all the converted numbers by the principle that 908=9*100+0*10+8, which is done in a loop.
char t[5] = {'-', '9', '0', '8', '\0'}; //Should be terminated properly.
int s = 1;
int i = -1;
int res = 0;
if (c[0] == '-') {
s = -1;
i = 0;
}
while (c[++i] != '\0') { //iterate until the array end
res = res*10 + (c[i] - '0'); //generating the integer according to read parsed numbers.
}
res = res*s; //answer: -908
It's not what the question asks but I used #Rich Drummond 's answer for a char array read in from stdin which is null terminated.
char *buff;
size_t buff_size = 100;
int choice;
do{
buff = (char *)malloc(buff_size *sizeof(char));
getline(&buff, &buff_size, stdin);
choice = atoi(buff);
free(buff);
}while((choice<1)&&(choice>9));