how to get multiple character in one input in C - c

I'm new to C programming so i'm trying to write a piece of code where i need to take ip address in hexadecimal but i couldn't figure out how to do. as far as i know i can't get multiple input with char but with int when user enters 'A' for example it turns out huge number.
for decimal inputs i wrote something like this
int main(){
int IP_1,IP_2,IP_3,IP_4;
printf("Enter the IP address:\n");
scanf("%d.%d.%d.%d",&IP_1,&IP_2,&IP_3,&IP_4);
i used 4 variables because later i will use those numbers for conversion.
edit: sorry for not adding this i can't use either hexadecimal %x or arrays/strings

What's the problem ?
The huge value when you enter a letter is because scanf() doesn't recognize the letter as valid input for an int, and stops reading, leaving the remaining variables unassigned.
How to solve it ?
First you should check if you've read as many variables as you've expected:
if (scanf("%d.%d.%d.%d",&IP_1,&IP_2,&IP_3,&IP_4)<4) {
printf ("Error: invalid format !\n");
}
You may then want to read the integer in hexadecimal format:
scanf("%x.%x.%x.%x",&IP_1,&IP_2,&IP_3,&IP_4);
You'll find more about the input formatting with scanf() here
Important remark: The convention for an IPv4 address, is to use dots to separate decimal components. For an hexadecimal notation, the digits are in principle consecutive, each component being 2 digits.
Edit
If you're not allowed to use %x, nor arrays, nor strings, then you can only input hex digits as char. Assuming that every hex part is entered on 2 digits, you may then have to input 8 chars:
char c1, c2, c3, c4, c5, c6, c7, c8;
scanf("%c%c.%c%c.%c%c.%c%c",&c1, &c2, &c3, &c4, &c5, &c6, &c7,&c8);
// are you sure you have to enter the dots ?
To convert two hex chars into an int, without using strings and arrays you can do:
if (c1>='A' && c1<='F')
IP_1 = c1-'A';
else if (c1>='0' && c1<='9')
IP_1 = c1-'0';
else
IP_1 = 0; // OUCH! THIS IS AN ERROR
IP_1 = IP_1 *16;
if (c2>='A' && c2<='F')
IP_1 = IP_1 + c2-'A';
else if (c2>='0' && c2<='9')
IP_1 = IP_1 + c2-'0';
else
IP_1 = 0; // OUCH! THIS IS AGAIN AN ERROR
I let as an exercise for you to add the case where the digits are lower case. I let you complete for all the characters, since you are not allowed to create functions.
FInal remark
Giving exercises that force students to massacre worldwide accepted IP address conventions, and then forcing students to copy paste code seems to me obvious signs of a completely incompetent teacher.
In your interest, you should not be as transparent and open as I am here. However, I feel obliged to warn you: go for some nice tutorials on the web. Or buy a K&R and do all the exercices contained therein. You'll learn real skills, instead of taking bad habits.

#include <stdio.h>
int main()
{
unsigned int IP_1,IP_2,IP_3,IP_4;
printf("Enter the IP address:\n");
scanf("%x %x %x %x",&IP_1,&IP_2,&IP_3,&IP_4); //storing in Hex format
printf("%x %x %x %x",IP_1,IP_2,IP_3,IP_4);
}

I think the best way is to read a string and then use the functions that already exist for converting string to IP (namely, inet_aton()).
Also, I would avoid scanf for strings, is insecure.
See https://ideone.com/aO9Nll for a live demo and the code.

Related

How to convert string representation of octal number to decimal?

I want to make a program that converts binary number to decimal, octal and hexadecimal.
While taking input I am considering their standard representation. For example: octal is "o10"
So I convert 10 into decimal, which gives 8.
Here's my code for inputting string and converting it to decimal:
int main()
{
int ch=0;
char str[1000];
printf("Enter the number\n");
scanf(" %s",str);
l=strlen(str);
for(int j=0;j<l;j++)
{
if(str[j]>=48 && str[j]<=57)
n=n*10+(str[j]-48);
}
}
But the problem is that it doesn't work for octal. How to take the input correctly?
On the post you are taking about creating Binary/Octal/Hexadecimal to Decimal converter, but you code only address Octal, My answer will try to be generic so you could implement the other cases with it, but will focus on Octal.
First of all, your code has some minor issues not related to the algorithm itself:
You call printf and strlen function, which does not come built in with C and need to be included with their respective libraries:
#include <stdio.h>
#include <string.h>
You assign l to the length of the string, but you never declare it type, so this is needed:
l = strlen(str);
Same problem for n, which is never declared. Not only that, you say n=n*10 ... so noy only not declaring it, you use it value.. what do you think n*10 will return? My guess is garbage. Since you use it in the loop, you should declare it outside the loop itself, so I would suggest:
int l = strlen(str), n = 0;
Okay not that we got this out of the way, your Octal converted code is actually almost done.
Only problem with the algorithm, is the n*10 ... part. If you multiply n by 10, you acually get decimal converted.. so Decimal to Decimal converted, if you input for example 48 you will get 48 as output. What do we need to fix it? change it to 2 for Binary converted, 8 for Octal, and 16 for Hexa. Your code only speak about octal, so if you change this line to:
n = n * 8 + (str[j] - 48);
You will get a working Octal converted. For example, if run the program and input 10, you will get 8 which is what we want.
Now as I mentioned earlier, if you want to make it more generic you should have a variable called int base = 10; which you can set according to the first character, for example:
int base = 10; // default value
if (str[0] == 'o')
{
base = 8;
}
Of course you can do the same for other bases, and it will pretty much work the same. Finally, you never did actually with the value of n after you calculated it, So someting like that would work to check the answer we got:
printf("In Decimal => %d\n", n);
This kinda works, but we still need to check digit boundaries. For example, octal number can't have a digit larger then 7, and Hexa number can have A as a digit. In the for loop, we do not check for anything like that. For example, if you input o48 in your code it will print an answer, 40, which is not correct since 48 is not an octal number.
So you in order to complete the program, you need to check if boundaries, and implement the rest of the bases check (h for hexa, b for binary), This I will leave to you.
GOOD LUCK~!

Limiting the type length of the user on C

My code asks a the 10 digit number, it reads it as a string, pass it to another function that checks if the user's input is a real number and has no characters or symbols with ASCII, and then if it's good, with atof it changes the string into a number for a variable.
I want the user to only introduce 10 digits/characters on the input console, I mean, if the user would put a 11 character for example, the console just don't grab it, or in the case this is impossible for C, make that if the user put more than 12 characters on the input, then the program launches an error message saying it exceeds the limit, the problem is, when i tried to use this method, for example if i put some big numbers like a 40 digit number, then the program goes crazy and send just incomprehensible results like "1.#J", or if I put a character in middle of the numbers, then it sends the corresponding error message i set for the user to not put characters, but it still grabs part of the number and accept it as it is nothing wrong, here's the main of code I tried:
int main() {
char chain[10];
float N;
int valid=0;
do{
printf("introduce real numbers: ");
fgets(chain, sizeof(chain), stdin);
if( chain[strlen(chain)-1] == '\n')
chain[strlen(chain)-1] = '\0';
valid=validate_numbers(chain);
}while(valid==0);
N=atof(chain);
printf("float number is: %.2f", N);
getche();
return 0;
}
Here's the rest of the code for more extense check: Pastebin
And sorry if there's some novice errors or the question is plain simple, im quite new programing.
Change this:
char chain[10];
to this:
char chain[11]; // +1 for the NULL terminator
since C-strings should be NULL terminated, thus we need one cell reserved for the NULL-terminator in our array (which will store our string).
I mean, if the user would put a 11 character for example, the console just don't grab it
Not possible in C.
or in the case this is impossible for C, make that if the user put more than 12 characters on the input, then the program launches an error message saying it exceeds the limit.
Yes, let's do that! Read the string, and if the length of it is more than 10 characters, then print an error message.
Allow chain array to be of size 12 (10 for the maximum length of the valid input, 1 for an extra character (if any) and 1 for the NULL-terminator), so that we can store the extra character, if any.
Example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char chain[12];
printf("introduce real numbers:\n");
fgets(chain, sizeof(chain), stdin);
chain[strcspn(chain, "\n")] = '\0';
if(strlen(chain) > 10)
{
printf("Error: Maximum length of chain is 10! Exiting..\n");
return 1;
}
return 0;
}
Note: You could use EXIT_SUCCESS and EXIT_FAILURE, instead of plain numbers (1 and 0 respectively): Should I return 0 or 1 for successful function?
Irrelevant to OP's question: In the full version of your code though, there is a plethora of problems, such as this top line of code int valid=validate_numbers(char number[]);, which wishes to declare the method. It should be just validate_numbers(char number[]);. The same holds true for the definition of the method too. Make sure you go through all your code again, and read the messages the compiler gifts to you. :)
What about using scanf instead of fgets? This should read 9 characters and save them as a string:
scanf("%9s" , &chain)
I'd suggest reading https://en.m.wikipedia.org/wiki/Scanf_format_string and man pages as well.

why i have exc_bad_access doing cast?

i am programming in C and i have a problem while casting an int into a char.
I am using my mac with Xcode to program c.
The code is:
int main(){
int t = 2;
printf("test %s\n", (char)t); //EXC_BAD_ACCESS
return 0;
}
I tried all I found in many post, I really don't know what is going on... any suggestion?
Please include the goal of your code in your question not in a comment below.
If you want the output
test 2
your have to change %s to %d
printf("test %d\n", t);
I guess you got the wrong idea about the %s. It does not tell the printf that you want to have the int as string, it does tell printf that the parameter is a string! It is obviously not, so you got the exception.
if you use %c you tell the printf function that you want to output your number as character from your current ASCII table. For example 65 is 'A'.
If you have a concatenation situation like
strcpy(str_buscar, "controlID='");
strcat(str_buscar, (char) t);
strcat(str_buscar, "'");
you need itoa instead of the cast:
strcat(str_buscar, (char) t);
you need the follow:
char buffer[32]; // enough space for a "number as string"
itoa(t,buffer,10);
strcat(str_buscar, buffer);
a (IMHO) shortcut is to "print" to a buffer with sprintf
sprintf(str_buscar,"controlID='%d'",t);
instead of printing to a console sprintf prints into the given buffer. Make shure that your buffer str_buscar is big enough.
The %s format specifier represents a string, not an individual character. Printf thinks that the number 2 you're passing it is a string's address. It tries to access the memory address 2 and fails, because that address doesn't exist.
If you want to print a character, you'll want the %c specifier. This tells printf to print the character whose ASCII code is 2. The ASCII character number 2 is, according to the ASCII table, a control character that cannot be printed, which is why you're getting strange output.
If you actually want to print the character '2' (which has a different code, 50), you will want to use something like:
printf("test: %c", (char)('0' + c));
This example leverages the fact that all ASCII characters have consecutive codes, starting with 48 ('0'). This way, if you wanted to print the digit 0, you'd end up printing the '0' character (ASCII code 48 = 48 + 0). If you want to print the digit 2, you'll end up printing the '2' character (50 = 48 + 2).
This way, however, is a bit clunky and fails when encountering numbers larger than 9 (i.e. it only works with digits). The easier way consists of no longer working with characters at all and, instead, using the '%d' specifier (used for printing whole number):
int t = 0;
printf("test: %d", t);

incompatible types in assignment of `float' to `char[3]'

trying to figure out what is going on here. I'm just learning C, so go easy on me. :P I was assigned to create a unit converter from centimeters to inches. I've got it. Now I want to spice it up a little by creating options. My compiler isn't enjoying what I have. this is the first few lines....
main(void)
{
float centimeter;
char cnv[3];
float entry;
float oz;
float lb;
float cm;
float lb1;
centimeter=2.54;
lb1=2.2;
printf("Hello. Please type exactly, the type of conversion you would like to do.\n\n1. cm to in\n\n2. lb to kg\n");
scanf("%3c",&cnv);
if (strcmp(cnv=cm));
{
printf("Please enter your length in centimeters:\n");
scanf("%f",&entry);
printf("with %.0f centimeters in length, that converts to %.2f inches.",entry,entry/centimeter);
}
if (strcmp(cnv=lb));
{
printf("Please enter your weight in pounds:\n");
scanf("%f",&entry);
printf("with %.0f Pound(s) of weight, that converts to %.2f Kilogram(s).",entry,entry/lb1);
}
}
and it's giving me the error in the title. How can I fix this?
1) You're confusing = (assignment) with == (test for equality)
2) You can't compare a numeric value directly to a character array. You need to convert one or the other to a type which can be compared -- convert the number to string, if your using strcmp() (and understand how that function returns its results, which aren't what you've assumed here), or convert the string to a numeric type and compare that way.
The '=' operator is used for assigning values not comparison. You should use '==' for comparisons.
The values that you are of different types. You should convert one of the variables to the other type to compare.
Strings must be compared with some string comparison function like strcmp() as you have done, but strcmp() is a function and therefore the you should pass the parameters in with a comma separating them.
As an aside strcmp() returns 0 when the strings that you pass in are equivalent, so using a syntax more like this would be appropriate: if(!strcmp(cnv, cm)) or if(strcmp(cnv, cm) == 0)
If I might take a guess what you really were looking to do was something like: if(strcmp(cnv, "cm") == 0) cm is a name of a variable whereas "cm" is a zero terminated string with the characters 'c' and 'm'
The next thing that you will need to worry about is reading in the 3 characters from scanf, because if the input was "cm" and the user pressed enter to enter the text. The program scanned 3 characters one of which was the newline character '\n'. So when you go to do the strcmp() the program will compare each character up till it reaches a byte that has been zeroed out. With just 3 characters being read I am not sure if the string you are capturing is zero terminated, but I am sure that the string could contain a '\n' which would throw the results of strcmp() way off.
Thestrcmp syntax is not correct. For more about string compare function please check this link
http://www.tutorialspoint.com/ansi_c/c_strcmp.htm

C - formatting MAC address

I am currently working with parsing some MAC addresses. I am given an output that does not include leading zeros (like so).
char* host = "0:25:25:0:25:25";
and I would like to format it like so
char* host = "00:25:25:00:25:25";
What would be the easiest way to go about this?
For those wondering, I am using the libpcap library.
I may be missing something in the question. Assuming you know it is a valid MAC, and the input string is thus parsable, have you considered something as simple as:
char* host1 = "0:25:25:0:AB:25";
char *host2 = "0:1:02:3:0a:B";
char result[19];
int a,b,c,d,e,f;
// the question sample
if (sscanf(host1, "%x:%x:%x:%x:%x:%x", &a,&b,&c,&d,&e, &f) == 6)
sprintf(result, "%02X:%02X:%02X:%02X:%02X:%02X", a,b,c,d,e,f);
printf("host1: %s\n", result);
// a more daunting sample
if (sscanf(host2, "%x:%x:%x:%x:%x:%x", &a,&b,&c,&d,&e, &f) == 6)
sprintf(result, "%02X:%02X:%02X:%02X:%02X:%02X", a,b,c,d,e,f);
printf("host2: %s\n", result);
Output
host1: 00:25:25:00:AB:25
host2: 00:01:02:03:0A:0B
Obviously for the ultra-paranoid you would want to make sure a-f are all < 255, which is probably preferable. The fundamental reasons I prefer this where performance isn't a critical issue are the many things you may not be considering in your question. It handles all of
Lead values of "n:", where n is any hex digit; not just zero. Examples: "5:", "0:"
Mid values of ":n:", again under the same conditions as (1) above. Examples: ":A:", ":0:"
Tail values of ":n". once more, under the same conditions as (1) above. Examples: ":b", ":0"
Hex-digit agnostic when reading; it works with both upper and lower case digit chars.
Most important, does nothing (except upper-case the hex values) if your input string is already properly formatted.
Roughly like this:
Allocate an output string to hold the reformatted MAC address.
Iterate over the input string and use strtok with : delimiter. In each iteration convert the beginning of the string (2 bytes) into a numerical value (e.g., with atoi). If the result < 16 (i.e., < 0x10), set "0" into the output string at current position and the result in hex at the following position; otherwise copy the 2 bytes of input string. Append : to the output string. Continue till end of the input.

Resources