Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

Help me with using scanf in C

Status
Not open for further replies.

techie

Advanced Member level 3
Joined
Feb 5, 2002
Messages
839
Helped
58
Reputation
116
Reaction score
9
Trophy points
1,298
Location
Pakistan
Activity points
7,799
I have the following variables

int number;
char text[100];

I have a text string as follows

CMGL: 9,"REC READ","0137443256780",,149,8

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
Joined
May 17, 2006
Messages
9
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,328
Re: Using scanf in C

techie said:
I have the following variables

int number;
char text[100];

I have a text string as follows

CMGL: 9,"REC READ","0137443256780",,149,8

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

Advanced Member level 5
Joined
Apr 7, 2002
Messages
3,942
Helped
636
Reputation
1,270
Reaction score
88
Trophy points
1,328
Location
USA
Activity points
33,183
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
    Helpful Answer Positive Rating

techie

Advanced Member level 3
Joined
Feb 5, 2002
Messages
839
Helped
58
Reputation
116
Reaction score
9
Trophy points
1,298
Location
Pakistan
Activity points
7,799
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

Advanced Member level 5
Joined
Apr 7, 2002
Messages
3,942
Helped
636
Reputation
1,270
Reaction score
88
Trophy points
1,328
Location
USA
Activity points
33,183
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
    Helpful Answer Positive Rating

techie

Advanced Member level 3
Joined
Feb 5, 2002
Messages
839
Helped
58
Reputation
116
Reaction score
9
Trophy points
1,298
Location
Pakistan
Activity points
7,799
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

Advanced Member level 4
Joined
May 22, 2003
Messages
1,350
Helped
126
Reputation
252
Reaction score
32
Trophy points
1,328
Location
Turkey
Activity points
13,461
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
    Helpful Answer Positive Rating

techie

Advanced Member level 3
Joined
Feb 5, 2002
Messages
839
Helped
58
Reputation
116
Reaction score
9
Trophy points
1,298
Location
Pakistan
Activity points
7,799
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

Advanced Member level 4
Joined
May 22, 2003
Messages
1,350
Helped
126
Reputation
252
Reaction score
32
Trophy points
1,328
Location
Turkey
Activity points
13,461
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

Advanced Member level 3
Joined
Feb 5, 2002
Messages
839
Helped
58
Reputation
116
Reaction score
9
Trophy points
1,298
Location
Pakistan
Activity points
7,799
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

Advanced Member level 4
Joined
May 22, 2003
Messages
1,350
Helped
126
Reputation
252
Reaction score
32
Trophy points
1,328
Location
Turkey
Activity points
13,461
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
    Helpful Answer Positive Rating

techie

Advanced Member level 3
Joined
Feb 5, 2002
Messages
839
Helped
58
Reputation
116
Reaction score
9
Trophy points
1,298
Location
Pakistan
Activity points
7,799
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

Advanced Member level 5
Joined
Apr 7, 2002
Messages
3,942
Helped
636
Reputation
1,270
Reaction score
88
Trophy points
1,328
Location
USA
Activity points
33,183
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!
http://download.yousendit.com/642F45F05E823E27

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.
Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top