Comparing input character to an array of ints in C - c

I am kinda new to C and I am having trouble using If statements to compare character input from the user to an int stored in an array.
Eg:
int i[2] = {1,2};
char input[3];
printf("Select option:");
fgets(input,3,stdin);
if(strcmp(*input,i[0]) == 0)
printf("1 chosen");
if(strcmp(*input,i[1]) == 0)
printf("2 chosen");
When compiling I get a warning for both compare statements saying:
warning: passing argument 1 of 'strcmp' makes pointer from integer without cast
warning: passing argument 2 of 'strcmp' makes pointer from integer without cast
I understand that this maybe because Im comparing non-string elements, but how will I cast them then compare them?
When executing I get:
Segmentation fault(core dumped)
Can somebody help?

Nobody yet has explained why what you are doing is incorrect, apart from saying that it is "wrong".
A string in C is just a bunch of consecutive characters in memory, where the last character in the string has a value of zero. You can store a string in a char array, or you can point to somewhere in memory by using a char pointer (char*).
When you input a decimal number, you are reading individual characters that happen to be in the range '0' through to '9', maybe prefixed by an optional '-'. You read these as a string, and if you want to treat them as integers you need to convert them to an integer data type (instead of a series of char values).
That's where something like atoi helps, although it is no longer fashionable. You should use strtol. [There is a whole family of these functions for dealing with unsigned, long long, or combinations thereof, as well as double and float types].
That tackles roughly half of your question. Now, you are using strcmp and expecting it to work. There are a couple of things wrong with what you are doing. The major error is that you can't treat an integer as a string. If you really want to use string comparison, you have to convert the integer to a string. That means you do the reverse of what strtol does.
That's a bigger discussion, and in your case it is not the correct way so I won't go into it. But I'd like to point out that, all things being equal, you are sending the wrong types to strcmp. It expects two char* pointers (const char *, really). What you have done is dereferenced your input pointer to a char for the first element, and then pass an int for the second.
strcmp(*input,i[0])
A pointer is basically just a number. It gives the memory address of some data. In this case, the data is expected to be char type (single bytes). The strcmp function is expecting valid memory addresses (stuff that's actually in your stack or heap). But what you give it is *input (the value of the first character in your input string) and i[0] (the number 1).
Those compiler warnings were telling you something quite important, you know! =)
So, just for completeness (although others have answered this already), you should forget the string comparisons (and make a mental note to learn more about strings in C), and do this:
int value = strtol( input, NULL, 10 );
if( value == i[0] )
printf("1 chosen");
if( value == i[1] )
printf("2 chosen");
There are other ways to go about this. I could talk about how to convert single-digit numbers from a string, but I think I have already ranted for long enough. Hope this is of some help.

Apart from the various methods listed as answers to your qn.
Why don't you take the user input as int??
#include<stdio.h>
int main()
{
int i[2] = {1,2};
int input;
printf("Select option:");
scanf("%d",&input);
if(input==i[0])
printf("1 chosen");
if(input==i[1])
printf("2 chosen");
return 0;
}

You must use scanf instead of fgets:
int input;
printf("Select option:");
scanf("%d", &input);
if (input == i[0])
etcetera.
See http://en.wikibooks.org/wiki/C_Programming/Simple_input_and_output#Input_using_scanf.28.29

Better convert input char to int using atoi function.
http://www.cplusplus.com/reference/cstdlib/atoi/
int i[2] = {1,2};
char input[3];
int opt=0;
printf("Select option:");
fgets(input,3,stdin);
opt = atoi(input);
if(opt== i[0])
printf("1 chosen");
if(opt == i[1])
printf("2 chosen");

You need to compare the input string vs. some known strings. But you're comparing the first character vs. some ints. strcmp() will do what you need if you pass it the right arguments: two strings.

here you are trying to compare a string to an integer using strcmp:
if(strcmp(*input,i[0]) == 0)
that won't work.
you could do that way:
const char *numbers[2] = {"1", "2"};
char input[3];
printf("Select option:");
fgets(input,3,stdin);
if(strcmp(*input, numbers[0]) == 0)
printf("1 chosen");
if(strcmp(*input, numbers[1]) == 0)
printf("2 chosen");
where you compare two strings, instead of comparing a number to a string
or you could convert the input string to an int using sscanf or atoi
int i[2] = {1,2};
char input[3];
int num;
printf("Select option:");
fgets(input,3,stdin);
sscanf(input, "%d", &num);
if(num == i[0])
printf("1 chosen");
else if(num == i[1])
printf("2 chosen");
i didn't compile them though, maybe there's sth which i am missing but that's the general idea

Use atoi. it will convert your string to integer
int i[2] = {1,2};
char input[3];
printf("Select option:");
fgets(input,3,stdin);
if(atoi(input)==i[0]))
printf("1 chosen");
if(atoi(input)==i[1]))
printf("2 chosen");

Related

Warning: comparison b/w pointer and integer in C.

int main()
{
char name[10], food[10], color[10], ans[10];
int height, year, age, date;
/* Ask for user inputs and do stuff here */
/* ------------------------------------- */
printf("Would you like me to repeat this?\n");
scanf("%c", ans);
/* its giving me a warning for the if condition on the line */
/* below saying warning: comparison b/w pointer and integer. */
if (ans == 'y')
printf("ok I will\n");
else
printf("fine.\n");
return 0;
}
At the end of the program, I wrote an IF statement where if user types "y" then it'll say "ok I will" ELSE say "fine" -nothing fancy.
But when I run it, the program would ask me "Would you like me to repeat this?" and even though I type "y" the program will output "fine" instead of "ok I will"... please help.
The variable ans is an array, and can decay to a pointer to the first element. You compare it to a character.
You should change to e.g. ans[0] == 'y'.
Or even better, since you only read a single character, why us an array at all? Just declare ans as a single character, and use the address-of operator in the scanf call:
char ans;
scanf(" %c", &ans);
if (tolower(ans) == 'y') ...
You're comparing ans which is regarded as pointer ,to 'y' which is regarded as integer. change char ans[10] to char ans.

How to add a string to a 2D array in C

i am starting to learn C and I have ran into the problem of adding a string input to a 2D array, i am able to get the string input correctly but when i try and add the string element to the array it is not working as expected.When printing the array(which is how i test the program) it will assign each index in the array a single character instead of the entire string.
And here is my code for viewing, thank you very much in advance i appreciate any help that is posted.
#include <stdio.h>
main()
{
char c_array[3][3];
int x;
int y;
int z=10;
int i_user_input;
char c_name[256];
for(x=0;x<=+2;x++)
{
for(y=0;y<=2;y++)
{
printf("\nPlease enter a name to the system:");
scanf(" %s",&c_array[x][y]);
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d",&i_user_input);
if(i_user_input==1)
continue;
if(i_user_input==2)
for(x=0;x<=2;x++)
{
for(y=0;y<=2;y++)
{
printf("c_array[%d][%d]=%c\n",x,y,c_array[x][y]);
}
}
}
}
}
The output looks as follows with the sample input 'Penelope!'
c_array[0][0]=P
c_array[0][1]=e
c_array[0][2]=n
c_array[1][0]=e
c_array[1][1]=l
c_array[1][2]=o
c_array[2][0]=p
c_array[2][1]=e
c_array[2][2]=!
When you declare:
char c_array[3][3];
This means that each element of your 2D array is a "char" (a single character); not a "string of characters".
To have each element be a string of characters, you need to declare your array in the following way:
char string_array[3][3][256];
I am not sure this is what you want to do though. Mw feeling is that you want an array of 3 elements where each element is a string. In that case, [3] is hardly enough, your strings will have to be less than two characters (the third being reserved for the terminating zero).
Strings aren't a type. They're a value pattern, like if you say an int stores a multiple of ten, then it ends in 0... If you say an array of char stores a string, then it ends at the first '\0', see? We can store multiples of ten in different kinds of integer variables, and likewise for strings.
Strings are patterns of values, not types. When choosing which integer type we want to use, we consider the range for integers. We choose int for small integer values (less than 32768), long for larger values (less than 2147483648) or long long for values larger than that. As a result, we choose the correct type of integer depending on the multiple of ten we expect. Likewise for strings, we need to make sure we have enough memory for the characters in the string followed by the '\0' at the end.
The character &c_array[x][y] only has enough memory for 0 characters followed by a '\0' at the end; it's only useful for storing an empty string. Perhaps you meant to declare c_array like this:
char c_array[3][3][256];
In this case, scanf expects %s to correspond to an argument of the type char *... but as your compiler will probably warn you, &c_array[x][y] will have the type char (*)[256]. If you want to fix that warning, you'll need to remove the & from your scanf code:
if (scanf("%s", c_array[x][y]) != 1) {
/* XXX: Handle an error here, *
* e.g. by exiting or returning or something */
}
While we're on that topic, you'll notice that I removed the redundant space; %s already performs the functionality that the format directive would perform. I also wrote code to check the return value of scanf, as you should...
Remember how we spoke about choosing the types of integers that we use to store data? One other consideration is whether or not the data we intend to store can be negative. Consider this: In your code, should x and y be able to store negative values? What sense does a negative array index make? It is advisable that all array indexes be declared as size_t. When you use printf to print a size_t value, you'll want to use the %zu format specifier rather than %d.
char c_name[256];
/* ... */
printf("The string is %s\n",c_name);
Now, if the string is stored into c_array[x][y], then what is the point of c_name? That's an unnecessary variable. Use c_array[x][y], instead.
printf("\nPlease enter a name to the system:");
Common implementations will often refrain from printing characters until a '\n' is written; the line is printed all at once rather than character by character. As a result, you might see some strange behaviour such as this line not appearing at the right time. Fix this problem by putting the '\n' on the end of the line, rather than the beginning:
printf("Please enter a name to the system:\n");
... or use puts, which adds a '\n' for you automatically:
puts("Please enter a name to the system:");
... or use fflush, which will write all pending unwritten data even if there is no '\n':
fflush(stdout);
In your code
scanf(" %s",&c_array[x][y]);
printf("The string is %s\n",c_name);
both the statements are wrong.
%s expects a pointer to an array, not a single char. To scan a single char, you need %c format specifier.
c_name, as used in the printf() is uninitialised. Using uninitialised value invokes undefined behaviour.
Solution: To take input element by element, you can do do something like
for(x=0; x<=2 ;x++)
{
printf("Start entering the name, one character at a time\n");
for(y=0; y< 2; y++) //note only '<' here
{
scanf(" %c", &c_array[x][y]); // note the leading space
}
c_array[x][y] = 0; //null termination of array to be used as string
}
If you want to assign a string to each index in the array, then create the array as follows :
#include<stdio.h>
int main(void)
{
char a[2][10];
int i=0;
char temp[20];
for(i=0;i<2;i++)
{
scanf("%s",temp);
strcpy(a[i],temp);
}
printf("%s",a[0]);
return 0;
}
Each string that you enter will be stored in each index of the array.
#include <stdio.h>
#include <string.h>
int main(void){
char c_array[3][3];
int x;
int y;
//int z=10;//unused
int i_user_input;
char c_name[256];
printf("\nPlease enter a name to the system:");
scanf("%255s",c_name);
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d", &i_user_input);
if(i_user_input==1)
;
else if(i_user_input==2){
memcpy(c_array, c_name, sizeof(c_array));
for(x=0;x<3;x++){
for(y=0;y<3;y++){
printf("c_array[%d][%d]=%c\n", x, y, c_array[x][y]);
}
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3
int main(void){
char *c_array[SIZE][SIZE] = { NULL };
int x;
int y;
//int z=10;//unused
int i_user_input;
char c_name[256];
for(x=0;x<SIZE;x++){
for(y=0;y<SIZE;y++){
printf("\nPlease enter a name to the system:");
scanf("%255s", c_name);
printf("The string is %s\n", c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d", &i_user_input);
c_array[x][y] = strdup(c_name);
if(i_user_input==1){
continue;
}
if(i_user_input==2){
int x, y;//local variable
for(x=0;x<SIZE;x++){
for(y=0;y<SIZE;y++){
if(c_array[x][y] != NULL)
printf("c_array[%d][%d]=%s\n", x, y, c_array[x][y]);
}
}
}
}
}
for(x=0;x<SIZE;x++)
for(y=0;y<SIZE;y++)
free(c_array[x][y]);
}
Why not use pointers in you array/matrix?
#include <stdio.h>
#include <string.h>
main()
{
char *c_array[3][3];
int x;
int y;
int z=10;
int i_user_input;
char c_name[256];
for(x=0;x<=+2;x++)
{
for(y=0;y<=2;y++)
{
printf("\nPlease enter a name to the system:");
scanf(" %s",c_name);
new_string = malloc(strlen(c_name)+1)
if (new_string == NULL) {
print("error allocating string\n")
exit(-1);
}
strcpy(new_string, c_name);
c_array[x][y] = new_string
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d",&i_user_input);
if(i_user_input==1)
continue;
if(i_user_input==2)
for(x=0;x<=2;x++)
{
for(y=0;y<=2;y++)
{
printf("c_array[%d][%d]=%c\n",x,y,c_array[x][y]);
}
}
}
}
for(x=0;x<=2;x++) {
for(y=0;y<=2;y++) {
free(c_array[x][y])
}
}
}
The code above stores the input string in each cell of the array, if that is your goal.
Note: I have no tried it, so there may be subtle errors. My point is to show you how to use pointers and their equivalence to arrays. Using C without pointers is pointless. :)

How to use char data type with if in C?

The code is,
#include <stdio.h>
#include <string.h>
main()
{
int a, b, s;
char ch;
LOOP:
printf("enter digits \t");
scanf("%d %d", &a, &b);
s = a + b;
printf("\n answer is %d", s);
printf("\n add another no.? (yes/no) : \t");
scanf("%c", &ch);
if (ch == "yes")
goto LOOP;
if (ch == "no")
printf("\n Okay bye !!! ");
exit(0);
return 0;
}
Can someone tell why this ain't working? When it asks:
Add another no.?
I cant type anything, I type but nothing gets print.
Thx in advanced.
First if you want to store "yes" you will need a char array, not a single char.
Then you can not compare char arrays with string literals like this: ch == "yes", you have to use "string compare", strcmp or strncmp.
"yes" is a char*(or pointer to char), which can't be compared using ==. In this case you need to use the library function strncmp() which compares two strings. Also a char is a data type which typically holds one byte of information in which case a single char cannot contain the 3 character string "yes". In your use of scanf to populate &ch, ch will end up only containing the first char of the input due to char's size.
Your code says to input 1 for yes and 0 for no, whereas you are checking for ch=="yes" and ch =="no".
You can initialize an integer, say, int choice; and then:
printf("\n add another no.? 1 for yes / 0 for no : \t");
scanf("%i", &choice);
if (choice == 1)
goto LOOP;
if (choice == 0){
printf("\n Okay bye !!! ");
exit(0);
}
NOTE that the exit(0) should be inside the if() statement, i.e. between {curly brackets}. When we don't use {curly brackets} with if() statement, only the first piece of code after the if(), that is printf(); in this case, is taken with the if().
Secondly, if you want to use yes and no instead of 1 and 0, then in that case you cant compare a string with == operator. To compare two string you use strcmp function, which returns 0 if the strings are same and some positive or negative value if not same. (that's why we have to use ! operator with strcmp, so that in case strings are same, and the strcmp return 0, !0 becomes 1 which means true and if statement is executed.)
We initialize ch, a string as char ch[5]; and then:
printf("\n add another no.? yes for yes / no for no : \t");
scanf("%s", ch);
if (!strcmp(ch,"yes"))
goto LOOP;
if (!strcmp(ch,"no")){
printf("\n Okay bye !!! ");
exit(0);
}

C treats char as a letter, not a one-byte integer

So let's say I need to take a number from user input, only from 0 to 9. Everything else is out of bounds.
I figure this number ought to fit within a one-byte integer, a char (0-255). Typically I see people use int here, but that's wasteful, isn't it? 32 bits (or whatever the implementation is) just to store the numbers 0-9?
What I find is that the code below (which uses shorts) works, but when I change it to use only a one-byte char, not a two-byte short, it begins to treat the user input as a string, so if a user enters 235, convert() no longer catches the error condition. It just returns the first digit of their number.
I'm aware that C implements strings as arrays of characters. Is there a way to use char to represent a single one-byte integer without treating it like a string? Should I just abandon the idea of using one-byte integers as numbers?
(I shortened this to test for 0-1, not 0-9, for the sake of brevity)
#include <stdio.h>
char *convert(short digit)
{
char *english;
switch (digit) {
case 0:
english = "zero";
break;
case 1:
english = "one";
break;
default:
english = "";
break;
}
return english;
}
void main(void)
{
short digit;
char *english;
printf("Enter a digit between 0 and 9: ");
scanf("%hu", &digit);
english = convert(digit);
if (english[0] == '\0') {
printf("\nYour number was invalid\n");
} else {
printf("\nYou entered the number %s\n", english);
}
}
Update:
Here's the attempted version that accepts a char, not a short:
#include <stdio.h>
char *convert(char digit)
{
char *english;
switch (digit) {
case 0:
english = "zero";
break;
case 1:
english = "one";
break;
default:
english = "";
break;
}
return english;
}
void main(void)
{
char digit;
char *english;
printf("Enter a digit between 0 and 9: ");
scanf("%c", &digit);
english = convert(digit);
if (english[0] == '\0') {
printf("\nYour number was invalid\n");
} else {
printf("\nYou entered the number %s\n", english);
}
}
The observed behavior of the above is that any number entered is flagged as invalid.
Change scanf("%c", &digit); to scanf("%hhd", &digit);
%c is the specifier to read a character and store that character. %d is the specifier to read a number written as base-10 digits and convert that to an integer (with hh meaning to write the answer into a char).
It is nothing to do with how "C treats a char", it is to do with how you instructed the scanf function to treat its input. A char is a one-byte integer.
Also, your code short digit; scanf("%hu", &digit); is incorrect; %hu is the specifier for unsigned short. Either use %hd or unsigned short digit;.
There is no way to use scanf to input a one byte integer. If you mean your format string is "%c" this is an (ascii) character, not a one byte integer. If you wish to treat it as a one byte integer you need to convert it yourself. c = c - '0'; will work find if a value 0-9 was provided.
If instead your intention is to scan in values within the full 8 bit range, you must scan in at least a short and you can take the lower 8 bits if you wish.
Typically I see people use int here, but that's wasteful, isn't it? 32 bits (or whatever the implementation is) just to store the numbers 0-9?
Using char instead of short won't save space and will be most likely counter productive in most cases.
For function parameters, the compiler will generate code that passes chars as ints (otherwise the stack will become unaligned which generates a fault on most platforms and severly slows down the machine on most others.
For most arithmetic operations on chars, the compiler will be forced to do integer promotion (extend char to int, do the operation and truncate the result).

Convert hex scanned (scanf) from an unsigned int array into decimal

I'm here trying to convert 4-digit hexa into dec but didn't succeed.
Here is a my code.
unsigned int array[4];
printf("Type in 4-digit hexa: \n");
scanf("%x", &array);
while(getchar() != '\n');
printf("Your number in dec is %u \n", array);
I don't know what's wrong with it but it just wouldn't give out the correct dec output.
Like when I put in EEFF, it's supposed to give out 61183 but the program kept on printing out 65518.
Where's this number from? What's wrong with my code? I used unsigned int according to my consideration that FFFF is equals to 65385 and the range for unsigned int is 0 to 65535. There should be no problem with the range of data and I also used %u with it.
The only thing I can think of right now after I've done some searching is that this problem might has sth to do with the size of unsigned int to int or sth.
I read the explanation but didn't quite understand.
I know, this might be a duplication but I'm here asking for an easier explanation
of why this doesn't work. To be honest, I'm an absolutely newby for both this site and programming so please go easy on me with the coding. FYI, I don't really know anything outside of stdio.h .
You are passing a pointer, array, to printf(). There is no need for an array here, what you're trying to scan and print is a single number.
unsigned int number;
printf("Type in 4-digit hex:\n");
if (scanf("%x", &number) == 1)
printf("Your number in dec is %u \n", number);
Also note that it's considered a good idea to check if scanf() succeeds or not, by inspecting the return value.
You don't need an array for that:
unsigned int val;
printf("Type in 4-digit hexa: \n");
scanf("%x", &val);
printf("Your number in dec is %u \n", val);
a. print array[0], not array.
(optional) b. scan to array, not to &array.
c. what is the point of the getchar()?
No, you must input as string to a point of characters. After that, you convert to number.
Ex
char *str=char[10];
int i=0,num=0;
printf("Type in 4-digit hexa: ");
scanf("%s",str);
for(i=0;str[i]!='\0';i++)
if(str[i]>='0' && str[i]<='9') num=16*num+str[i]-'0';
else if(str[i]>='a' && str[i]<='f') num=16*num+str[i]-'a';
else if(str[i]>='A' && str[i]<='F') num=16*num+str[i]-'A';
printf("Dec is %d",num);

Resources