Sscanf and Sprintf convert string to decimal? - c

I need to solve the following exercise:
"Write a program that acquires the first characters of a string an integer octal and write it on another string previously empty, then display the contents of this second string in decimal, using the functions sscanf and sprintf.
For example, if the user enters 12 (octal) the system must show 10 (decimal)."
After my scanf, the array seconda is ="12325".
The problem is that I do not know how to make understand that this string is an octal number and how to convert it to decimal with sprintf.
This is my current code:
#include <stdio.h>
int main(void) {
char prima[] = "12325dsdfa";
char secodna[500];
sscanf_s(prima, "%[0123456789]o", secodna, 500);
}

You're mis-using %o, mixing it with the character set format %[] and also passing too many arguments.
You should just use %o, it will convert an unsigned integer octal for as many characters as possible.
Then convert back to decimal string using %u with sprintf().
Something like this:
#include <stdio.h>
int main(void) {
unsigned int x;
if(sscanf("12foo", "%o", &x) == 1)
printf("%u\n", x);
return 0;
}
Note that the above outputs the decimal string to stdout rather than keeping it around (i.e. it uses printf() instead of sprintf()), but that's trivial to change. It prints "10".

Once it has been converted to a binary integer variable (with sscanf()) use sprintf() with a %u format to output it to the appropriate string.
Make sure you have the appropriate buffers defined first.
sscanf reference
sprintf reference
unsigned int intbuf;
char myinput[80];
char myoutput[80];
strcpy(myinput, "12345");
sscanf(myinput, "%o", &intbuf);
sprintf(myoutput, "%u", intbuf);

Related

sscanf not reading numbers

A newbie in C is trying to extract two numbers from a string using sscanf(). The numbers shall be parsed from strings formatted like "7-12", which should result in firstNode = 7and secondNode = 12. So I want to get the numbers, the minus sign can be understood as a number seperator. My current implementation is similar to the example I found on this SO answer:
void extractEdge(char *string) {
int firstNode = 123;
int secondNode = 123;
sscanf(string, "%*[^0123456789]%u%*[^0123456789]%u", &firstNode, &secondNode);
printf("Edge parsing results: Arguments are %s, %d, %d", string, firstNode, secondNode);
}
But if I execute the code above, there always is retourned the inital value 123 for both ints. Note that the output of string gives the correct input String, so I think an invalid string can't be a probable cause for this problem.
Any ideas why the code is not working? Thanks in advance for your help.
%*[^0123456789] requires one or more non-digit character, but the first character of you input 7-12 is a digit. This makes sscanf() stop there and read nothing.
Remove that and use "%d%*[^0123456789]%d" as format specifier to deal with 7-12.
Also note that correct format specifier for reading decimal int is %d, not %u. %u is for reading unsigned int.

Convert subsections of array of char to int

Is there a strtol() or sscanf() equivalent where you can specify the no. of chars to convert?
I have a use case where I need to convert sub sections of an array of chars to ints, so I don't have the terminating null char present
In other words, I'd like the equivalent of strncmp() in relation to strcmp()
i.e. strntol() or snscanf() but they don't seem to exist
I imagine i'll just have to copy and append a '\0' and use strtol() or sscanf() but just wanted to check I hadn't missed an existing function for this purpose
question is really do they exist? am i just searching for the wrong thing?
There is no equivalent for strtol, but you can use format specifier to limit the number of characters considered by sscanf:
char *str = "1234567890";
int n;
sscanf(&str[3], "%3d", &n);
printf("%d\n", n);
The %3d specifier instructs sscanf to take only three digits from str, while &str[3] tells sscanf to start at the index 3.
The above code prints 456 (demo).

Copying binary data with memcpy in c

I have the following problem when using memcpy:
Suppose that an hexadecimal data must be copied in binary, e.g.: 203800000E820006, then apply the following instruction:
unsigned char buffer[8];
memcpy(buffer,"\x20\x38\x00\x00\x0E\x82\x00\x06",8);
However, when I write the data in binary, it only prints the 2 first bytes in binary, because \x00 is interpreted as a string terminator. How to avoid or fix this in order to represent the 16-char string in a 8-char binary format?
The buffer you have is not a string. You can't treat it like one by passing it to functions expecting a string such as strcat, strcpy, strcmp, or the %s format specifier of printf.
You have an array of characters, so print them as such:
int i;
for (i=0;i<sizeof(buffer);i++) {
printf("%02hhX ", buffer[i]);
}
printf("\n");

How to tell "1.0" is a float but an integer in C language?

I have a program that accept orders by reading commands from a file.
In this file some commands are "float string", like "1.0","2.0", but they are invalid, what the program need is integer, like "1","2". So, how can I make the program understand the commands like "1.0" is invalid? Is there any neat way to do this?
char buf[CMDSIZE];
if(fgets(buf, CMDSIZE, stdin)) //buf likes this: "1.0 \n"
{
*prio = 1; *command = -1; *ratio =1.0;
// I need to make sure that command is not "1.0" or something like this
sscanf(buf, "%d", command);
switch(*command){....blahblah......}
}
Thank you.
It's easier to use strtol.
This will parse a base-10 integer. The pointer e will point to the first character after the integer. You can check to make sure it's a NUL byte and signal an error otherwise. (You also have to check that the input isn't empty.)
If you want to allow spaces / newlines after the number, you can do that too. Note that strtol eats leading whitespace -- but not trailing whitespace.
long v;
char *e;
v = strtol(buf, &e, 10);
if (!buf[0] || *e) {
error();
}
// v has number
Footnote: Checking for overflow and underflow with strtol is a little weird. You have to set errno to 0 first, call strtol, then check if the result is LONG_MIN or LONG_MAX and if errno is set to ERANGE.
Both scanf("%d"....) and scanf("%f"....) will succeed and return 1 when reading the input 1.0. (sscanf works the same way.) It's just that with "%d", it will stop reading before the decimal point.
You can use the format specifier %n with sscanf to see how many characters were read, and then look if the buffer contains more stuff afterwards.
Or, which might be easier, just look at the contents in the buffer with your own code, instead of sscanf, to see if there are only digits there.
in your special case, just to check difference between 1 and 1.0
use the code:
int ret = scanf("%d.%d",&i,&j);
if inputs is 1, the scanf only assign one value, the ret is 1
if inputs is 1.0, the scanf assign two value, the ret is 2.
if inputs is abcd, the scanf can't assign any value, the ret is 0
and regarding the return value of scanf, fscanf etc.
In C99 standard 7.19.6.4 The scanf function
The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure
You can use scanf with %f to store it as a floating point value
example or scan with %d to store it as an integer but it will not count the decimal
#include<stdio.h>
main()
{
float i;
int a;
printf("Enter a number which is a floating point value");
scanf("%f,%d",&i,&a);
}
here using scanf and %f we are storing it in a float variable i so 1.5,1.0
or any number with a decimal will be stored or if we only use the %d it will only store 1,2,3,4 any number without the decimal i.e if we give 2.5 it will only take 2

How store a number starting with 0 in C

Id just thought id ask this question to see whether it can actually be done.
if i want to store a number like "00000000000001", What would be the best way?
bearing in mind that this also has to be incrememted on a regular basis.
Im thinking either there is a way to do this with the integer or i have to convert to a char array somewhere along the line. This would be fine but its a pain to try and increment a string.
I would store it as an integer and only convert to the formatted version with leading zeros on demand when you need to produce output, for example with printf, sprintf etc.
It's far easier that way than storing a string and trying to perform arithmetic on strings. Not least because you have extra formatting requirements about your strings.
If for some reason it is awkward to store an integer as your master data do it like this.
Store the string as your master data.
Whenever you need to perform arithmetic, convert from string to integer.
When the arithmetic is complete, convert back to string and store.
You should simply store the number using an appropriate type (say, unsigned int), so that doing operations like 'increment by one' are easy - only bother worrying about leading zeros when displaying the number.
sprintf can actually do this for you:
unsigned int i = 1;
char buffer[64];
sprintf( buf, "%014u", i );
This prints '00000000000001'.
You could store it in a integer variable (provided there's an integer type that's wide enough for your needs). When printing, simply format the number to have the correct number of leading zeros.
#include <stdlib.h> // for itoa() call
#include <stdio.h> // for printf() call
int main() {
int num = 123;
char buf[5];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", buf);
return 0;
}

Resources