scanning a string to hex char array - c

Here is my sample code :
char a;
char str [20];
unsigned char b[8] ;
unsigned char c[8];
int argsread;
int i;
init_8051();
while(1)
{
printf("\n enter a 64 bit operation \n");
argsread = scanf("%s", str);
sscanf(str, "0x%x%c0x%x", b, &a, c);
printf("\n %d arguments read \n",argsread);
for(i=0;i<8;i++)
{
printf("\n %#x %c %#x\n",b[i],a,c[i]);
}
}
}
The problem here is that when i enter for example in the terminal the following input :
0x1234567890abcdef+0x1234567890abcdef
this leads to an error where output for char array is totally wrong and most of the numbers are traced into a , which should have been the plus sign , am ai doing something fundamentally wrong ?
Update:
I changed my code to the following :
while(1)
{
printf("\n enter a 64 bit operation \n");
argsread = scanf("%s", str);
sscanf(str, "0x%s%c0x%s", b, &a, c);
printf("\n %d arguments read \n",argsread);
printf("\n %s \n",b);
}
and i increased size of str to 30 the problem is the output of the program is :
1 arguments read
abcdef+0xabcdef
so the value of b instead of being just abcdef it the the whole string!!
Update2:
Found this code which works perfect but i wanted to use scanf instead of cin here is the code
:`#include <iostream>
using namespace std;
int main()
{
float a, b, result;
char oper, clear;
cout << "Please enter an equation: i.e 5+5 " << endl;
for (;;) {
cin >> a;
cin >> oper;
cin >> b;
if (oper == '+')
result = a + b;
else if (oper == '-')
result = a - b;
else if (oper == '*')
result = a * b;
else if (oper == '/')
result = a / b;
cout << "= " << result << endl << endl;
cin.clear();
cin.ignore();
}
} `

User input and error handling much easier if code starts with fgets().
Then use sscanf(), strtol(), etc. to parse.
printf("\n enter a 64 bit operation \n");
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_IOErrororEOF();
char a;
char b[17]; // use right size arrays
char c[17];
// use width of 16 and %[]
if (sscanf(buf, " 0x%16[0-9abcdef] %c 0x%16[0-9abcdef]", b, &a, c) != 3) {
Handle_Bad_Input();
}
OTOH, just use an integer format specifier that allows hex input "%x" or "%i"
unsigned long long b,c;
if (sscanf(buf, "%lli %c%lli", &b, &a, &c) != 3) {
Handle_Bad_Input();
}
Why char str [20]; scanf("%s", str); has trouble:
"%s" does 3 things:
1) scans, but does not save, all preceding (0 or more) white-space (' ', '\t', '\n ', etc.).
2) scans and saves all non-white-space.
3) Finally reaching a white-space. it stops scanning and puts that white-space back into stdin.
The "%s" specifier lacks a width, like "%19s", so it can easily overfill str
sscanf(str, "0x%s%c0x%s", b, &a, c); has trouble too.
Input has no white-space between the end of the first number and the '+', so "%s" continues scanning. Code does not check the return value from sscanf() and then uses a, b, c. So a, b, c may not be properly scanned nor initialized - leading to potential undefined behavior .

You are reading a string using scanf and storing it in an integer. I think that is what is causing you the problem.
Also, from the MAN Page
AME
scanf, fscanf, sscanf, vscanf, vsscanf, vfscanf
...
RETURN VALUE
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in the
event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error indicator
for the stream (see ferror(3)) is set, and errno is set indicate the
error.

I think you missplaced the assignment, if you want to know how many arguments matched, then change this
argsread = scanf("%s", str);
sscanf(str, "0x%x%c0x%x", b, &a, c);
to this
scanf("%s", str);
argsread = sscanf(str, "%x%c%x", b, &a, c);
According to your comments, you should change some other things, may be this code will work
char a;
char str [64];
unsigned int b;
unsigned int c;
char B[11];
char C[11];
int argsread;
while(1)
{
printf("\n enter a 64 bit operation \n");
scanf("%s", str);
argsread = sscanf(str, "0x%x%c0x%x", &b, &a, &c);
if (argsread == 3)
{
printf("\n %d arguments read\n", argsread);
snprintf(B, sizeof(B), "0x%08X", b);
snprintf(C, sizeof(B), "0x%08X", c);
printf("\n %s%c%s\n", B, a, C);
}
}
return 0;

Related

How to check if input string is in correct format in C?

A want to check if input string is in right format
"%d/%d"
For example, when the input will be
"3/5"
return 1;
And when the input will be
"3/5f"
return 0;
I have idea to do this using regex, but I had problem to run regex.h on windows.
How to check if input string is in correct format ... ?
A simple test is to append " %n" to a sscanf() format string to store the offset of the scan, if it got that far. Then test the offset to see if it is at the end of the string.
int n = 0;
int a, b;
// v---v----- Tolerate optional white spaces here if desired.
sscanf(s, "%d /%d %n", &a, &b, &n);
if (n > 0 && s[n] == '\0') {
printf("Success %d %d\n", a, b);
} else {
printf("Failure\n");
}
It is not completely clear what you mean by the format "%d/%d".
If you mean that the string should be parsed exactly as if by sscanf(), allowing for 2 decimal numbers separated by a /, each possibly preceded by white space and an optional sign, you can use sscanf() this way:
#include <stdio.h>
int has_valid_format(const char *s) {
int x, y;
char c;
return sscanf(s, "%d/%d%c", &x, &y, &c) == 2;
}
If the format is correct, sscanf() will parse both integers separated by a '/' but not the extra character, thus return 2, the number of successful conversions.
Here is an alternative approach suggested by Jonathan Leffler:
#include <stdio.h>
int has_valid_format(const char *s) {
int x, y, len;
return sscanf(s, "%d/%d%n", &x, &y, &len) == 2 && s[len] == '\0';
}
If you mean to only accept digits, you could use character classes:
#include <stdio.h>
int has_valid_format(const char *s) {
int n = 0;
sscanf(s, "%*[0-9]/%*[0-9]%n", &n);
return n > 0 && !s[n];
}

How to make scanf stop reading from input based on the first char?

I am stuck with scanf()
Can somebody help me please and tell me how can I read the first character in scanf() and based on that character decide whether I want to read 1 or 2 or 3 inputs:
For example :
scanf( char , int int int) if character
S , how do I make it stop after input :
S 45
For this kind of problem, and to easier error recovery in general, you should read one line of input at a time with fgets() and use sscanf() to parse the line.
Here is an example:
#include <stdio.h>
int main() {
char line[128];
printf("Enter letter and values:\n");
if (fgets(line, sizeof line, stdin)) {
if (*line == 'A') {
int a, b, c;
if (sscanf(line, "A %d %d %d", &a, &b, &c) == 3) {
printf("A code, a=%d, b=%d, c=%d\n", a, b, c);
} else {
printf("A code requires 3 integers\n");
}
} else
if (*line == 'S') {
int a;
if (sscanf(line, "S %d", &a) == 1) {
printf("S code, a=%d\n", a);
} else {
printf("S code requires 1 integer\n");
}
} else
{
/* handle other input codes... */
}
}
return 0;
}

How to loop scanf_s() until success?

#include <stdio.h>
int main(){
float x,y;
printf("Enter 2 numbers: \n");
scanf_s("%f %f", &x, &y);
if (getchar() == '\n')
{
printf("Division: %f\n", x / y);
printf("Product: %f\n", x * y);
printf("Sum: %f\n", x + y);
printf("Difference: %f\n", x - y);
}
else
{
printf("no Float-Value!");
}
getchar();
return 0;
}
we need to get a loop in so if we enter the wrong format the program should ask again to enter two numbers
The best way of checking the validity of the input is to check the return value of scanf_s which tells you the number of variables that were successfully set. In your case, if it's 2 then all is well; otherwise you need to repeat.
In other words
do {
int c;
while ((c = getchar()) != '\n' && c != EOF); // clear the input stream
printf("Enter 2 numbers: \n");
} while (scanf_s("%f %f", &x, &y) != 2);
is an appropriate control structure, rather than if (getchar() == '\n'), which you should drop.
What I don't like about using scanf family of functions is that it will go berserk and crash your program when you input something wrong. For example, if you have scanf("%f", &a), try inputing stack overflow. It goes nuts!
So, as I said in the comments, I think you should build your own validating function, and get user input as just a string using fgets.
Here is a simple code that will get you started in it. This is very ugly code and you should refactor it.
#include <stdio.h> /* printf, fgets */
#include <ctype.h> /* isdigit, isspace */
#include <string.h> /* strlen */
int is_valid_float(char *s, int len)
{
int i;
for(i = 0; i < len; i++) {
/* floats may have a decimal point */
if(s[i] == '.') continue;
/* spaces should be ignored, since they separete the nubmers */
if(isspace(s[i])) continue;
/* is there's anything besides a number, we abort */
if(!isdigit(s[i])) return 0;
}
/* if we got here, then the input contains two valid floats.
*
* Does it? Test it!
*/
return 1;
}
int main(void)
{
float a, b;
char buf[100];
int len;
do {
fprintf(stderr, "Enter A and B: ");
fgets(buf, sizeof buf, stdin);
/* fgets will store a newline at the end of the string, we
* just overwrite it with a null terminator
*
* Thanks to #chux for the strcspn() suggestion.
*/
buf[strcspn(buf, "\n")] = 0;
} while(!is_valid_float(buf, len));
/* now, after we know the string is valid and won't cause scanf to go
* berserk, we can use it in our validated string.
*
* Here is where you should really take a moment and look at the
* validation function and improve it. Not valid strings will cause
* your program to go nuts.
*/
sscanf(buf, "%f %f", &a, &b);
/* Did it scan the numbers correctly? */
printf("A: %f\n", a);
printf("B: %f\n", b);
return 0;
}

scanf doesn't work properly for third time

I'm trying to write a simple C program. The input format is like this:
Enter a: <a>
I want to input a, b, c and d but the scanf doesn't work for c and d and the program crashes on that point.
#include <stdio.h>
#include <math.h>
int main(){
int a, b, c, d;
char ch;
printf("Enter a:");
scanf("%c%d%c", &ch, &a, &ch);
printf("Enter b:");
scanf("%c%d%c", &ch, &b, &ch);
printf("Enter c:");
scanf("%c%d%c", &ch, &c, &ch);
printf("Enter d:");
scanf("%c%d%c", &ch, &d, &ch);
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>", ans);
return 0;
}
There are 3 format conversion specifiers which do not skip leading white space. They are %c (which you're using), %[…] scansets, and %n.
When you type:
Enter a:<1>
Enter b:<2>
The first < satisfies the first %c; the 1 matches the %d, the > matches the second %c, so all is fine so far.
The second lot of input, though, reads the newline from the first line into the first %c, then fails to convert the < to an integer and stops, leaving the < for the next input to process.
The Enter c: prompt is given, but the <2> is processed because it is in the correct format, so the Enter d: prompt is given.
There are multiple ways to fix this, including:
Insert a blank before the first %c in the format strings. This will skip white space, including newlines, and give you the expected behaviour. It is probably the simplest fix.
Read lines and use sscanf() to process them. This is generally the best solution. (Use fgets() to read the line.)
In either case, check that the scanf() family function returns the correct value (3). And use two variables int c1, c2; to read the characters and validate that the user typed what you require.
A bare minimum fixup is:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a, b, c, d;
char c1, c2;
printf("Enter a: ");
if (scanf(" %c%d%c", &c1, &a, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter b: ");
if (scanf(" %c%d%c", &c1, &b, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter c: ");
if (scanf(" %c%d%c", &c1, &c, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter d: ");
if (scanf(" %c%d%c", &c1, &d, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
I'm being lazy with the comma operators after the if statement. It would be better, though, to use a function to manage the inputs:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static void get_number(int *var, const char *name)
{
char c1, c2;
printf("Enter %s: ", name);
if (scanf(" %c%d%c", &c1, var, &c2) != 3 || c1 != '<' || c2 != '>')
{
fprintf(stderr, "Bogus input!\n");
exit(1);
}
}
int main(void)
{
int a, b, c, d;
get_number(&a, "a");
get_number(&b, "b");
get_number(&c, "c");
get_number(&d, "d");
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
And better still to use:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static int get_number(const char *name)
{
char buffer[4096];
printf("Enter %s: ", name);
if (fgets(buffer, sizeof(buffer), stdin) == 0)
{
fprintf(stderr, "EOF or error on input\n");
exit(1);
}
char c1, c2;
int val;
if (sscanf(buffer, " %c%d%c", &c1, &val, &c2) != 3 || c1 != '<' || c2 != '>')
{
/* buffer contains a newline unless you typed more than 4095 characters before the newline */
fprintf(stderr, "Bogus input (does not match <number>): %s", buffer);
exit(1);
}
return val;
}
int main(void)
{
int a = get_number("a");
int b = get_number("b");
int c = get_number("c");
int d = get_number("d");
double ans = fabs((a*b/c + c*d/a) / (b*a/c + d*b/a));
printf("Inputs: a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
Note how the code uses fgets() plus sscanf() which means that the error message can tell the user what they entered that was not what was expected. It also uses the function to return the value, leading to the simpler code shown. And the output includes the input values for inspection. That may not be needed for your submission system, but it surely helps you while you're developing the code.
You can work on the upgrade to process double values as inputs; it isn't hard.
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
The C language doesn't take into account what you do with a result when it determines its type. So the fact that you assign the results of this operation to a double don't have any effect on the way the result is computed, it just converts the integer result to a double. When you divide integers by integers, you get integer division.
You could do something like this:
ans=(a*1.0*b/c + c*1.0*d/a)/(b*1.0*a/c + d*1.0*b/a);
The multiplication by a non-integer forces non-integer multiplication, addition, and division to be used.

Work With Char Using If else in C Language

Whenever I use if Statement to make a decision by comparing a character using char and %d, then it results in false always.
example:
#include<stdio.h>
#include<conio.h>
int main(void) {
int a, b;
float r;
char op;
printf("Enter 1st num : ");
scanf("%d", & a);
printf("Enter 2nd Num : ");
scanf("%d", & b);
printf("Enter Operator ( +, - , * , /) : ");
scanf("%c", & op);
if (op == '+') {
r = a + b;
printf("Ans = %f", r);
getche();
} else if (op == '-') {
r = a - b;
printf("Ans= %f", r);
}
//same as above for remaining 2 functions of * and /
else
printf("Error Occurred");
}
After typing the second number you press enter, right? %c in scanf accepts the first character it finds, so it returns the line break character corresponding to you pressing enter.
An easy fix is to add a space character before %c. It makes scanf skip any whitespace.
scanf(" %c",&op);
From the scanf documentation (http://www.cplusplus.com/reference/cstdio/scanf/):
Whitespace character:
The function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
Because %d ignore white-spaces and special characters. White-spaces and special characters are chars. So, %c has to take white-spaces and special characters as inputs.
You can test the output of the code below.
#include <stdio.h>
int main(void)
{
char p = 'w';
char l = 'x';
char t = 't';
printf("Give one, two or three chars: ");
scanf("%c%c%c", &p, &l, &t);
printf("p = %c, l = %c, t = %c \n", p, l, t); //
scanf("%c", &t);
printf("plt = %c%c%c \n", p,l,t);
return 0;
}

Resources