sscanf not reading numbers - c

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.

Related

Reading a file containing multiple lines of strings, integers and floats

I'm trying to read a file containing a line containing a string, integer and float. The data is separated by commas and I've seen a tonne of information about how best to approach this. I've simplified by problem by first trying to read in one line, and then work on implementing multiple lines.
I've managed to read the first two pieces of data. It's the float that's giving me issues.
Here is an example of what it is I'm trying to read:
CHANNEL_1, 0, 0.453
char CHANNEL_NAME_[BUF_SIZE];
uint32_t val1_;
double val2_;
FILE *fp;
int c;
fp = fopen("E:\\read_from_file\\config.cfg", "r");
if (fp < 1)
{
printf("Failed to open file = %d\n", fp);
fclose(fp);
}
c = fscanf(fp, "%[^,], %u[^,], %lf", CHANNEL_NAME_, &val1_, &val2_);
printf("[%s] [%u] [%lf]\n", CHANNEL_NAME_, val1_, val2_);
printf("C = %d\n", c);
I'm able to print the string and integer correctly, however, it's the float that's giving me issues. It comes out as a random float, something like 34534524524523452345.0000000. I expect to see the float as per above, 0.453.
When I print C, which is the result of the fscanf, I get 2 which is incorrect as I'd expect to read 3, due to 3 data types being read in.
What am I doing wrong?
There's no such specifier as "%u[^,]". That format is treated as a separate "%u" followed by a separate "[^,]".
The %[ format only reads strings, it doesn't have any type-prefix (and it's not needed as scanf will stop reading integers at the first non-digit character in the input). Which means you can use only "%u" for the middle specifier:
c = fscanf(fp, " %[^,], %u, %lf", CHANNEL_NAME_, &val1_, &val2_);
Note that I added a leading space in the format string. That's because the "%[" format does not skip leading spaces (like any possible newlines after the previous line).
With the format specifier "%u[^,]", the function actually tries to match the exact sequence "[^,]" in the input, which it won't find, leading to the last value not being read. Hence the value of c being 2 (as fscanf only matched two values, the initial string and the first unsigned integer).

Sscanf and Sprintf convert string to decimal?

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);

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);

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

What is the use of the %n format specifier in C?

What is the use of the %n format specifier in C? Could anyone explain with an example?
Most of these answers explain what %n does (which is to print nothing and to write the number of characters printed thus far to an int variable), but so far no one has really given an example of what use it has. Here is one:
int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");
will print:
hello: Foo
Bar
with Foo and Bar aligned. (It's trivial to do that without using %n for this particular example, and in general one always could break up that first printf call:
int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");
Whether the slightly added convenience is worth using something esoteric like %n (and possibly introducing errors) is open to debate.)
Nothing printed. The argument must be a pointer to a signed int, where the number of characters written so far is stored.
#include <stdio.h>
int main()
{
int val;
printf("blah %n blah\n", &val);
printf("val = %d\n", val);
return 0;
}
The previous code prints:
blah blah
val = 5
I haven't really seen many practical real world uses of the %n specifier, but I remember that it was used in oldschool printf vulnerabilities with a format string attack quite a while back.
Something that went like this
void authorizeUser( char * username, char * password){
...code here setting authorized to false...
printf(username);
if ( authorized ) {
giveControl(username);
}
}
where a malicious user could take advantage of the username parameter getting passed into printf as the format string and use a combination of %d, %c or w/e to go through the call stack and then modify the variable authorized to a true value.
Yeah it's an esoteric use, but always useful to know when writing a daemon to avoid security holes? :D
From here we see that it stores the number of characters printed so far.
n The argument shall be a pointer to an integer into which is written the number of bytes written to the output so far by this call to one of the fprintf() functions. No argument is converted.
An example usage would be:
int n_chars = 0;
printf("Hello, World%n", &n_chars);
n_chars would then have a value of 12.
So far all the answers are about that %n does, but not why anyone would want it in the first place. I find it's somewhat useful with sprintf/snprintf, when you might need to later break up or modify the resulting string, since the value stored is an array index into the resulting string. This application is a lot more useful, however, with sscanf, especially since functions in the scanf family don't return the number of chars processed but the number of fields.
Another really hackish use is getting a pseudo-log10 for free at the same time while printing a number as part of another operation.
The argument associated with the %n will be treated as an int* and is filled with the number of total characters printed at that point in the printf.
The other day I found myself in a situation where %n would nicely solve my problem. Unlike my earlier answer, in this case, I cannot devise a good alternative.
I have a GUI control that displays some specified text. This control can display part of that text in bold (or in italics, or underlined, etc.), and I can specify which part by specifying starting and ending character indices.
In my case, I am generating the text to the control with snprintf, and I'd like one of the substitutions to be made bold. Finding the starting and ending indices to this substitution is non-trivial because:
The string contains multiple substitutions, and one of the substitutions is arbitrary, user-specified text. This means that doing a textual search for the substitution I care about is potentially ambiguous.
The format string might be localized, and it might use the $ POSIX extension for positional format specifiers. Therefore searching the original format string for the format specifiers themselves is non-trivial.
The localization aspect also means that I cannot easily break up the format string into multiple calls to snprintf.
Therefore the most straightforward way to find the indices around a particular substitution would be to do:
char buf[256];
int start;
int end;
snprintf(buf, sizeof buf,
"blah blah %s %f yada yada %n%s%n yakety yak",
someUserSpecifiedString,
someFloat,
&start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);
It doesn't print anything. It is used to figure out how many characters got printed before %n appeared in the format string, and output that to the provided int:
#include <stdio.h>
int main(int argc, char* argv[])
{
int resultOfNSpecifier = 0;
_set_printf_count_output(1); /* Required in visual studio */
printf("Some format string%n\n", &resultOfNSpecifier);
printf("Count of chars before the %%n: %d\n", resultOfNSpecifier);
return 0;
}
(Documentation for _set_printf_count_output)
It will store value of number of characters printed so far in that printf() function.
Example:
int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);
The output of this program will be
Hello World
Characters printed so far = 12
Those who want to use %n Format Specifier may want to look at this:
Do Not Use the "%n" Format String Specifier
In C, use of the "%n" format specification in printf() and sprintf()
type functions can change memory values. Inappropriate
design/implementation of these formats can lead to a vulnerability
generated by changes in memory content. Many format vulnerabilities,
particularly those with specifiers other than "%n", lead to
traditional failures such as segmentation fault. The "%n" specifier
has generated more damaging vulnerabilities. The "%n" vulnerabilities
may have secondary impacts, since they can also be a significant
consumer of computing and networking resources because large
guantities of data may have to be transferred to generate the desired
pointer value for the exploit. Avoid using the "%n" format
specifier. Use other means to accomplish your purpose.
Source: link
In my opinion, %n in 1st argument of print function simply record the number of character it prints on the screen before it reach the the %n format code including white spaces and new line character.`
#include <stdio.h>
int main()
{
int i;
printf("%d %f\n%n", 100, 123.23, &i);
printf("%d'th characters printed on the screen before '%%n'", i);
}
output:
100 123.230000
15'th characters printed on the screen before '%n'(with new character).
We can assign the of i in an another way...
As we know the argument of print function:-
int printf(char *control-string, ...);
So, it returns the number the number of characters output. We can assign that return value to i.
#include <stdio.h>
int main()
{
int i;
i = printf("%d %f\n", 100, 123.23);
printf("%d'th characters printed on the screen.", i);
}
%n is C99, works not with VC++.

Resources