Thread: Weird problem with sscanf

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476

    Weird problem with sscanf

    Hi, I've got a weird problem here:

    I have a routine of reading from a file and getting some values for the variables from it. Here's the problem:

    Code:
    ...
    	sscanf ( buffer,"%d : %d : %d : %d : %d",&mWidth, &mHeight, &mTransCol.transR, &mTransCol.transG , &mTransCol.transB);
    ...
    and the buffer's value (from debug) is:
    Code:
    buffer = "22 : 21 : 1 : 2 : 3\r\n\000..."
    the value of variables are:
    Code:
    mWidth=0 
    mHeight=21
    mTransCol.transR=1
    mTransCol.transG=2
    mTransCol.transB=3
    I'm confused. Why does the mWidth is 0 whereas in the buffer string it's clearly 22 ?? Can anybody help me with this?

  2. #2
    Registered User SKeane's Avatar
    Join Date
    Sep 2006
    Location
    England
    Posts
    234
    What type is mWidth, how are you printing the results? What is sscanf returning?

  3. #3
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Quote Originally Posted by SKeane
    What type is mWidth, how are you printing the results? What is sscanf returning?
    mWidth is an int. And when I cout-ed the buffer, it displays the same as the value of buffer. And sscanf returned 5 (so I guess all the variables are successfully read).

  4. #4
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    BTW, before the troublesome line, there's a sequence of reading with fgets and sscanf. And the pervious sequence worked fine.

    Code:
            int scanBuff;
    
    	fgets (buffer, 255, fp);
            //looping through comments (#)
    	while (buffer[0] == '#' || buffer[0] == '\r' || buffer[0] == '\0' || buffer[0] == '\n' || strlen(buffer) == 0)
    	{
    		fgets (buffer, 255, fp);
    	}
    
    	scanBuff = sscanf ( buffer, "%s : %s : %s : %s : %d", nametemp, dirName, filename, widthfile, &mNumFonts);
    	
    	fgets (buffer, 255, fp);
            //looping through comments (#)
    	while (buffer[0] == '#' || buffer[0] == '\r' || buffer[0] == '\0' || buffer[0] == '\n' || strlen(buffer) == 0)
    	{
    		fgets (buffer, 255, fp);
    	}
    	scanBuff = sscanf ( buffer, "%d : %d : %d : %d : %d : %d : %d : %d", &mIndexLargeA, &mIndexSmallA, &mIndex0, &mIndexKoma, &mIndexDot, &mIndexDot2, &mIndexEq, &mIndexEs);
    
    	fgets (buffer, 255, fp);
            //looping through comments (#)
    	while (buffer[0] == '#' || buffer[0] == '\r' || buffer[0] == '\0' || buffer[0] == '\n' || strlen(buffer) == 0)
    	{
    		fgets (buffer, 255, fp);
    	}
    	scanBuff=sscanf ( buffer,"%d : %d : %d : %d : %d",&mWidth, &mHeight, &mTransCol.transR, &mTransCol.transG , &mTransCol.transB);

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    How did you declare buffer?

    What is the value in scanBuff when it appears wrong?
    It should be the number of conversions AND assignments, which in this case would seem to be 5.

    Also, fgets() returns a status which you should check.

    > buffer[0] == '\r' || buffer[0] == '\0' || strlen(buffer) == 0
    Unless you're using fgets() to read a binary file (not a good idea), none of these will be true
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Quote Originally Posted by Salem
    How did you declare buffer?

    What is the value in scanBuff when it appears wrong?
    It should be the number of conversions AND assignments, which in this case would seem to be 5.

    Also, fgets() returns a status which you should check.

    > buffer[0] == '\r' || buffer[0] == '\0' || strlen(buffer) == 0
    Unless you're using fgets() to read a binary file (not a good idea), none of these will be true
    buffer is:
    char buffer[255];

    In the wrong line, scanBuff read 5 (so I guess the problem is not in in sscanf).

    The status returned from fgets is never NULL (so I guess the fgets is not faulty either)

    And for the "buffer[0] == '\r' || buffer[0] == '\0' || strlen(buffer) == 0", it worked fine and my file is opened in text mode. It just check whether a linefeed is found or not.

    So, I'm curious what is the matter with this code?

    EDIT:
    I tried to add a bogus variable so now the faulty line is:
    Code:
    	scanBuff=sscanf ( buffer,"%d : %d : %d : %d : %d : %d",&bogusVar, &mWidth, &mHeight, &mTransCol.transR, &mTransCol.transG , &mTransCol.transB);
    And guess what, in didn't work. The scanBuff showed 5, the mWidth is still 0 and the bogusVar is undetermined. How weird is that?
    Last edited by g4j31a5; 10-03-2006 at 07:56 PM.

  7. #7
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    You know, I've solved the problem with a little bit of tinkering. I defined a local temporary variable and then used it in the sscanf. After that the I set mWidth equivalent the temporary variable like so:
    Code:
            int tempW;
    	scanBuff=sscanf ( buffer,"%d : %d : %d : %d : %d", &tempW, &mHeight, &mTransCol.transR, &mTransCol.transG , &mTransCol.transB);
    
    	mWidth= tempW;
    And it worked (At last!!!!!!). BTW, I forgot to mention that mWidth is a private member variable (as well as mHeight and mTransCol in that matter). But still, the cause of the problem isn't solved and I'm still curious. But I'm happy with that, for now.

  8. #8
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Well, now that you got that solved... may I suggest using stringstreams or lexical_cast instead? This is C++, after all, and sprintf is a very C solution... those very acceptable.
    Sent from my iPadŽ

  9. #9
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Quote Originally Posted by SlyMaelstrom
    Well, now that you got that solved... may I suggest using stringstreams or lexical_cast instead? This is C++, after all, and sprintf is a very C solution... those very acceptable.
    Yeah, that's what I thought too. But alas, the code was already in C (my application is in the most part C++, but in a few exceptions still in C like this one). And I kind of lazy to rewrite in in C++ style :P

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    Can you post a small and complete program which demonstrates the problem.

    Your answer doesn't solve anything, it sweeps it under the carpet for it to reappear later on.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Quote Originally Posted by Salem
    Can you post a small and complete program which demonstrates the problem.

    Your answer doesn't solve anything, it sweeps it under the carpet for it to reappear later on.
    Well, this is not the complete program, just the faulty function:

    Code:
    int CFont::init(char *infoPath, char *infoFile)
    {
    	char buffer[255];
    	char *strState; 
    	char filename[255], filename2[255];
    	char dirName[255];
    	char nametemp[255];
    	char widthfile[255];
    
    	//int bogusVar;
    	FILE *fp; //buffer config file
    
    
    	//Path&filename config file
    	strcpy(filename,infoPath);
    	strcat(filename,"/");
    	strcat(filename,infoFile);
    
    	int scanBuff, tempW;
    	
    	//open config file
    	if((fp=fopen(filename, "r")) == NULL)
    	{
    		printf("ERROR opening file %s\n\n", filename);
    		return -1;
    	}
    
    	//Reading configuration
    	strState = fgets (buffer, 255, fp);
            //looping through comments (#)
    	while (buffer[0] == '#' || buffer[0] == '\r' || buffer[0] == '\0' || buffer[0] == '\n' || strlen(buffer) == 0)
    	{
    		strState = fgets (buffer, 255, fp);
    	}
    
    	scanBuff = sscanf ( buffer, "%s : %s : %s : %s : %d", nametemp, dirName, filename, widthfile, &mNumFonts);
    	
    	strState = fgets (buffer, 255, fp);
            //looping through comments (#)
    	while (buffer[0] == '#' || buffer[0] == '\r' || buffer[0] == '\0' || buffer[0] == '\n' || strlen(buffer) == 0)
    	{
    		strState = fgets (buffer, 255, fp);
    	}
    	scanBuff = sscanf ( buffer, "%d : %d : %d : %d : %d : %d : %d : %d", &mIndexLargeA, &mIndexSmallA, &mIndex0, &mIndexKoma, &mIndexDot, &mIndexDot2, &mIndexEq, &mIndexEs);
    
    	strState = fgets (buffer, 255, fp);
            //looping through comments (#)
    	while (buffer[0] == '#' || buffer[0] == '\r' || buffer[0] == '\0' || buffer[0] == '\n' || strlen(buffer) == 0)
    	{
    		strState = fgets (buffer, 255, fp);
    	}
    	scanBuff=sscanf ( buffer,"%d : %d : %d : %d : %d",&mWidth, &mHeight, &mTransCol.transR, &mTransCol.transG , &mTransCol.transB);
    
    	//mWidth= tempW;
          	fclose(fp);
    }
    The class itself:
    Code:
    class CFont  
    {
    public:
    	CPicFont* getPicFont(int no);
    	int getCharWidth(char nama);
    	string getName();
    	void draw(int xx, int yy, char huruf);
    	void createFont(char* folder, char* nama, SDL_Rect blit_Reg, char huruf);
    	CFont();
    	CFont(char *fontInfoPath, char *fontInfoFile, CSurface* screen);
    	int getHeight();
    	int getWidth();
    	virtual ~CFont();
    
    private:
    	CSurface* mScreen;
    	int init(char *infoPath, char *infoFile);
    	int mNumFonts;
    	string mNamaFont;
    	TransparentColor mTransCol;
    	int mWidth;
    	int mHeight;
    	lstFontName mFontName;
    	lstFontHandle mFontHandle;
    	int mIndexLargeA; 
    	int mIndexSmallA; 
    	int mIndex0; 
    	int mIndexKoma;
    	int mIndexDot; 
    	int mIndexDot2;
    	int mIndexEq; 
    	int mIndexEs; 
    };
    The init function is called under the constructor.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    > just the faulty function:
    Doesn't help much - where it crashes does not necessary mean that's where the problem is.

    It's only possible to find such things with complete programs, I can't find such problems from random snippets.

    IE, I want to be able to do copy / paste / compile / run / examine crash without having to guess at what you missed out or provide my own wrappers around your snippets just to make it work.

    Given that it crashes in the ctor / init(), then (with a copy of the code) snip out every other member function and every other unused member variable and see if the problem persists. Your main() should just have a single CFont and then construct it.

    If that fails in the way you describe, then you can post the whole lot and we have something to go at.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,688
    On a side note, it is not usually a good idea to mix C and C++ code. Either do it one way or the other

  14. #14
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    Quote Originally Posted by swgh
    On a side note, it is not usually a good idea to mix C and C++ code. Either do it one way or the other
    Yeah, I know that. The code is done because I didn't know the proper way to do it in C++. And because my application is getting bigger, I somewhat reluctant to rewrite it. After all, there's still many things to do than tweaking the code.

  15. #15
    In the Land of Diddly-Doo g4j31a5's Avatar
    Join Date
    Jul 2006
    Posts
    476
    2 Salem:

    Okay, I've made a new app with only the class, the constructor of the class, and the init function. And guess what, it didn't show any error and worked fine. BTW, the faulty code was actually worked fine at first. Then I added five more integer input before mWidth (the IndexKoma to IndexEs) and after that the code always read mWidth = 0 regardless of the actual value in the file.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Weird problem on '02 3.4L V6 auto
    By VirtualAce in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 01-12-2006, 12:05 AM
  2. Really Weird itoa Problem
    By Grantyt3 in forum C++ Programming
    Replies: 8
    Last Post: 12-20-2005, 12:44 AM
  3. very weird problem (pointers I think)
    By hannibar in forum C Programming
    Replies: 2
    Last Post: 10-11-2005, 06:45 AM
  4. Replies: 6
    Last Post: 05-12-2005, 03:39 AM
  5. Weird class problem!
    By aker_y3k in forum C++ Programming
    Replies: 2
    Last Post: 09-25-2002, 06:12 AM