# Help me with using scanf in C

Status
Not open for further replies.

#### techie

I have the following variables

int number;
char text[100];

I have a text string as follows

I want to read the text

number = 9
text = 0137443256780 without the "" quotes

Will the following work,

sscanf(string,"CMGL:%u,\"%s\",,",&number,text);

or any other suggestions.

#### ptuser_eda

##### Newbie level 5
Re: Using scanf in C

techie said:
I have the following variables

int number;
char text[100];

I have a text string as follows

I want to read the text

number = 9
text = 0137443256780 without the "" quotes

Will the following work,

sscanf(string,"CMGL:%u,\"%s\",,",&number,text);

or any other suggestions.
It looks good

#### echo47

Re: Using scanf in C

No, your sscanf format string will scan 'text' after the first quote, which isn't what you want.

Test code:
Code:
#include <stdio.h>
int main(void)
{
int number;
char text[100];
char *string = "CMGL: 9,\"REC READ\",\"0137443256780\",,149,8";

printf("%s\n", string);
if (2 == sscanf(string, "CMGL:%u,\"%s\",,", &number, text))
printf("number=%d text=%s\n", number, text);
else
printf("Trouble!\n");
return 0;
}
the output:
Code:
CMGL: 9,"REC READ","0137443256780",,149,8
number=9 text=REC
Try this instead. The %99[0-9]s scans up to 99 numeric digits (otherwise a long input string could overflow your 100-byte 'text' buffer and crash the program). I also changed %u to %d to match your 'int' variable.
Code:
#include <stdio.h>
int main(void)
{
int number;
char text[100];
char *string = "CMGL: 9,\"REC READ\",\"0137443256780\",,149,8";

printf("%s\n", string);
if (2 == sscanf(string, "CMGL:%d,\"REC READ\",\"%99[0-9]s", &number, text))
printf("number=%d text=%s\n", number, text);
else
printf("Trouble!\n");
return 0;
}
the output:
Code:
CMGL: 9,"REC READ","0137443256780",,149,8
number=9 text=0137443256780

### techie

points: 2

#### techie

Using scanf in C

Looks Great. Except that the "REC READ" may not alway be "REC READ". It can be any text between the quotes. Would the following work ? I have put 2 commas between %d and %99[0-9]s.

Code:
char *string = "CMGL: 9,\"Anything 1234\",\"0137443256780\",,149,8";

sscanf(string, "CMGL:%d,,\"%99[0-9]s", &number, text);   // skip the middle string

#### echo47

Re: Using scanf in C

Oh.

No, your modification won't work. Don't you have a compiler to try these experiments yourself? Reading a C manual and experimentation are the best way to learn!

Try this. The %*[^\"] matches any string of characters except for quote, and doesn't store it. However, it will misbehave if the string between the two quotes contains zero characters - I don't think scanf can handle that situation.
Code:
#include <stdio.h>
int main(void)
{
int number;
char text[100];
char *string = "CMGL: 9,\"Anything 1234\",\"0137443256780\",,149,8";

printf("%s\n", string);
if (2 == sscanf(string, "CMGL:%d,\"%*[^\"]\",\"%99[0-9]", &number, text))
printf("number=%d text=%s\n", number, text);
else
printf("Trouble!\n");
return 0;
}
the output:
Code:
CMGL: 9,"Anything 1234","0137443256780",,149,8
number=9 text=0137443256780
OOPS! My previous example contained a mistake. I should have used %99[0-9] instead of %99[0-9]s. By luck, it was harmless in that situation.

### techie

points: 2

#### techie

Using scanf in C

Thanks. I have used the scanf very rarely so wanted some code to work on before trying it out on a compiler. There will always be some text between the first 2 sets of quotes so I think there should be no problem.

The 3 or 4 books on C that I have describe the scanf function in a very bad manner and I could not figure out the usage of %*[^\"]\",\"%99[0-9]s as you have mentioned. Can you post some file or tell me some website which describes the scanf in details.

#### artem

Using scanf in C

sscanf is memory consuming and very general . Parameters in nmea (added : and in mobile phones) are separated by comas , number of commas show parameter number in message . It is better for optimization to not to use sscanf , but write small parser counting commas and skipping quotas

### techie

points: 2

#### techie

Using scanf in C

Artem, I would appreciate if you could post some parser code in C for that. I dont have much experience in string manipulation so am struggling with that. You are right about the limitations of scanf and the advantage of counting comma's.

Another thing that I am struggling with is to How to scanf a string transmitted by a weight indicator like "\2- 12.345Kg ST\r\n" to obtain the numeric part of the string in a format like "-12.345".

#### artem

Using scanf in C

It should not be a problem to parse anything as far as things to be parsed have unambiguous syntax. Do you have weight indicator data sheet where output syntax stated? Or does it send only one string like this ?
Code:
"\2- 12.345Kg ST\r\n"

#### techie

Using scanf in C

I am making a device that has to be interfaced with a vareity of weight indicators. While all of them transmit weigth in a similar fashion (begin with \2 and end with \r\n), they have small differences in number of spaces and the end units. Following are the different types of data

\2- 234.45Kg ST\r\n
\2 1234.45Kg ST\r\n
\2 234.45 Lbs\r
\2234.5 Kg\r\n
\2- 234.45Kg US\r\n
\2 12345Kg T\r\n

etc

#### artem

Using scanf in C

i assume \2 is the 0x02 valued character:

Code:
#include <ctype.h>
#include <stdio.h>

unsigned char strings[][20] =
{
{"\2- 234.45Kg ST\r\n"},
{"\2 1234.45Kg ST\r\n"},
{"\2 234.45 Lbs\r"},
{"\2234.5 Kg\r\n"},
{"\2- 234.45Kg US\r\n"},
{"\2 12345Kg T\r\n"}
};

double give_me_number(unsigned char *str_p)
{
double digit;
char dot_flag;
unsigned char count;

// scan string for '2' character
while(*str_p++ != '\2')
;

// Scan string for first digit
while(!isdigit(*str_p))
str_p++;

// Convert digit to number starting from found in one in previous loop
for(digit = 0, dot_flag = 0, count = 0 ; ; str_p++)
{
if(isdigit(*str_p))
{
digit = digit*10 + *str_p - 48;
if(dot_flag == 1)
count++;
}
else if(*str_p == '.')
dot_flag = 1;
else
break;
}

while(count-- !=0)
digit /= 10.0;

return digit;
}

void main(void)
{

unsigned char temp;

for(temp = 0 ; temp < 6; temp++)
{
printf("\n\nnumber from string %s \n\t is %lf \n", strings[temp], give_me_number(strings[temp]));
}
}

### techie

points: 2

#### louisnells

##### Full Member level 4
Re: Using scanf in C

There is a simple solution for this use the PCRE library with your C-code. You write complex text parsing functions with it. http://www.php.net/manual/en/reference.pcre.pattern.syntax.php contains the syntax with PCRE.

PCRE takes more memory than the ordinary C string functions. So use it only when necessary.

#### techie

Re: Using scanf in C

The following routine that I wrote seems to work fine. Any suggestions for improvements.

Code:
/*******************************************************************
Simple Comma Separated String Parser.

Input String = something like  "START: 123,"ABCD",EFGH,345,1,,9\r\0"
1. Matches the Start HEADER with strtstr (matches "START:")
2. Counts Commas upto the required parameter (0 is the first param)
3. Copies the parameter text till comma, ", \r or \0 to desination string
4. Removes the starting and ending quotes "" if any.
5. Returns 1 if successfull, 0 if Unsucessfull

Use like : result = csv_str_parse(string,"+CMGL:",i,outstring);

*******************************************************************/
int csv_str_parse(char * instr, char * strtstr, int para_no, char * outstr) {
int index;
int j;
char cc;

index = strlen(strtstr);
if (strncmp(strtstr,instr,index) != 0) return 0;    // start does not match

while (para_no != 0) {             // start of the required parameter
cc = instr[index++];
if (cc == '\0') return(0);
if (cc == ',') para_no--;
}

if (instr[index] == '\"') index++;   // ignore the start quote "

j = 0;
cc = instr[index++];
while (cc!=',' && cc!='\r' && cc!= '\"' && cc!='\0') {
outstr[j++] = cc;
cc = instr[index++];
}
outstr[j] = '\0';      // add a terminator
return (1);
}

#### echo47

Re: Using scanf in C

Can you post some file or tell me some website which describes the scanf in details.
My favorite C book is the standard itself, although it is not a tutorial. The most recent version I've seen is ISO/IEC 9899 second edition dated 1999-12-01. Someone uploaded this copy - grab it quickly because the link will disappear soon!

Yes, scanf is a bulky function. That's usually no problem in Windows/Linux apps, but it could be a big problem if you are trying to squeeze your project into a small microcontroller.

scanf is handy, but it has limitations and wasn't designed to be a general purpose parsing function. Oftentimes it's more efficient to write your own parsing function, as you are now doing.

Status
Not open for further replies.