Thread: Strings and white space

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    23

    Strings and white space

    Is it possible to scan strings with spaces, and then other unlike int variables. For instance, if I wanted to input the name of a tool, then it's price, how would I differentiate between the two in the scan line?

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Strings and white space

    I don't quite understand what you're asking. Example, please?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    23
    Here's a sample of code:
    Code:
    void newrecord(FILE *fptr)
    {
    	struct inventory tool = {0, "", 0, 0.0};
    
    	int recordnum;
    
    	printf("Enter new record (1-100): ");
    	scanf("%d", &recordnum);
    
    	fseek(fptr, (recordnum - 1) * sizeof(struct inventory), SEEK_SET);
    
    	fread(&tool, sizeof(struct inventory), 1, fptr);
    
    	if(tool.recordnum != 0){
    		printf("Record #%d already contains information.\n", tool.recordnum);
    	}
    	else{
    		printf("Enter Tool Name, Quantity and Cost: ");
    		scanf("%s%d%lf", &tool.toolname, &tool.quantity,
    			&tool.cost);
    		tool.recordnum = recordnum;
    
    		fseek(fptr, (tool.recordnum - 1) * sizeof(struct inventory), SEEK_SET);
    
    		fwrite(&tool, sizeof(struct inventory), 1, fptr);
    	}/*end else*/
    }
    My problem is that I can't get scanf to differentiate beween the variables for 'toolname' and 'quantity'.

  4. #4
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by ginom71 View Post
    Is it possible to scan strings with spaces, and then other unlike int variables. For instance, if I wanted to input the name of a tool, then it's price, how would I differentiate between the two in the scan line?
    If I got your question right, yes it is possible to scan strings with spaces, using fgets. For differentiating the name will be string and price would be int or float. In that case using a structure is advisable.
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> My problem is that I can't get scanf to differentiate beween the variables for 'toolname' and 'quantity'.

    Why? Aren't you entering the values separated by spaces? It should work fine. Oh and one more thing, you should be checking return values (scanf, fseek, fread, etc).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Jul 2009
    Posts
    23
    I am, but the problem is with input like "Sledge Hammer" and then 7.50 for cost. I need to figure out how to enter strings that have spaces, and then input value for other variables.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> the problem is with input like "Sledge Hammer" and then 7.50 for cost.

    I see. In that case, you'll either need to input them separately (eg: one variable per line) or else use fgets and split the input "manually".
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    1 - Read the FAQ.
    2 - Read a line from the file using fgets.
    3 - Split it using sscanf.

    Actually... it looks like you're reading records one whole structure at a time. In which case, you shouldn't need to do any of this. Just fwrite the whole structure, and then later fread it back in.

    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Here's a quick-and-dirty example using fgets and sscanf:

    Code:
    int main( void )
    {
    	const int
    		size = 1024;
    	char
    		buffer[ size + 1 ];
    	char
    		name[ size + 1 ];
    	int
    		index = 0, 
    		quantity = 0;
    	double	
    		cost = 0;
    	printf( "Enter name, quantity, and cost >" );	
    	if( fgets( buffer, size, stdin ) )
    	{
    		while( buffer[ index ] != 0 && !isdigit( buffer[ index + 1 ] ) )
    			++index;
    		strncpy( name, buffer, index );
    		name[ index ] = 0;
    		if( sscanf( &buffer[ index ], "%d%lf", &quantity, &cost ) == 2 )
    		{
    			printf( "Name: %s\nQuantity: %d\nCost: %lf\n", name, quantity, cost );
    		}
    		else
    		{
    			puts( "Error: invalid input" );
    		}
    	}
    	else
    	{
    		puts( "Error: input error" );
    	}
    	return 0;
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Registered User
    Join Date
    Jul 2009
    Posts
    23
    Thanks for that. Why do you set name[index] to zero?

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Why do you set name[index] to zero?

    Just to be sure that it gets null terminated (strncpy doesn't guarantee it).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  12. #12
    Registered User
    Join Date
    Jul 2009
    Posts
    23
    Thanks again for the help. OK, I've changed your code around a little to fit my program. This is the new function prototype to insert a new record. See below:

    Code:
    void newrecord(FILE *fptr)
    {
    	struct inventory tool = {0, "", 0, 0.0};
    
    	int recordnum, i = 0;
    	char temp[30];
    
    	printf("Enter new record (1-100): ");
    	scanf("%d", &recordnum);
    
    	fseek(fptr, (recordnum - 1) * sizeof(struct inventory), SEEK_SET);
    
    	fread(&tool, sizeof(struct inventory), 1, fptr);
    
    	if(tool.recordnum != 0){
    		printf("Record #%d already contains information.\n", tool.recordnum);
    	}
    	else{
    		printf("Enter name, quantity, and cost: ");
    		fgets( temp, 30, stdin );
    		
    		while(temp[i] != 0 && !isdigit(temp[i + 1])){
    			++i;
    		strncpy(tool.toolname, temp, i);
    		tool.toolname[i] = 0;
    		}
    		sscanf( &temp[i], "%d%lf", &tool.quantity, &tool.cost);
    		printf( "Name: %s\nQuantity: %d\nCost: %lf\n", tool.toolname, tool.quantity, tool.cost);
    
    		tool.recordnum = recordnum;
    	}/*end else*/
    }
    Below is a shot of the program when running.

    Press 1 to begin a new file, 2 to use existing data: 1

    Enter your choice
    1 - store a formatted text file of the inventory called
    "storeinv.txt" for printing
    2 - update a record
    3 - add a new record
    4 - delete a record
    5 - end program
    ? 3
    Enter new record (1-100): 3
    Enter name, quantity, and cost: Name:

    Quantity: 0
    Cost: 0.000000

    Enter your choice
    1 - store a formatted text file of the inventory called
    "storeinv.txt" for printing
    2 - update a record
    3 - add a new record
    4 - delete a record
    5 - end program
    ?
    So what happens between the time I enter a new record number and the time I'm supposed to enter data for the record?

  13. #13
    Registered User
    Join Date
    Jul 2009
    Posts
    23
    I have also tried the following:

    Code:
    void eatnewline(void) {
        int x;
        
        do {
            x = getchar();
        } while(x != '\n' && x != EOF);
    }
    Code:
    void newrecord(FILE *fptr)
    {
    	struct inventory tool = {0, "", 0, 0.0};
    
    	int recordnum, tmprcd, i = 0;
    	char temp[30];
    
    	printf("Enter new record (1-100): ");
    	scanf("%d", &recordnum);
    	tmprcd = recordnum;
    
    	fseek(fptr, (recordnum - 1) * sizeof(struct inventory), SEEK_SET);
    
    	fread(&tool, sizeof(struct inventory), 1, fptr);
    
    	if(tool.recordnum != 0){
    		printf("Record #%d already contains information.\n", tool.recordnum);
    	}
    	else{
    		printf("Enter name, quantity, and cost: ");
    		eatnewline();
    		fgets( temp, 30, stdin );
    		
    		while(temp[i] != 0 && !isdigit(temp[i + 1])){
    			++i;
    		strncpy(tool.toolname, temp, i);
    		tool.toolname[i] = 0;
    		}
    		sscanf( &temp[i], "%d%lf", &tool.quantity, &tool.cost);
    		printf( "Name: %s\nQuantity: %d\nCost: %lf\n", tool.toolname, tool.quantity, tool.cost);
    
    		tool.recordnum = tmprcd;
    	}/*end else*/
    }
    which is supposed to take care of the newline character. Only this happens when I run the program. I can't figure it out.

    Press 1 to begin a new file, 2 to use existing data: 1

    Enter your choice
    1 - store a formatted text file of the inventory called
    "storeinv.txt" for printing
    2 - update a record
    3 - add a new record
    4 - delete a record
    5 - end program
    ? 3
    Enter new record (1-100): 3
    Enter name, quantity, and cost: Electric sander 7 57.98
    Name: Electric sander
    Quantity: 7
    Cost: 57.980000

    Enter your choice
    1 - store a formatted text file of the inventory called
    "storeinv.txt" for printing
    2 - update a record
    3 - add a new record
    4 - delete a record
    5 - end program
    ? 2
    Enter record to update(1-100): 3
    Record has no information.

    Enter your choice
    1 - store a formatted text file of the inventory called
    "storeinv.txt" for printing
    2 - update a record
    3 - add a new record
    4 - delete a record
    5 - end program
    ?

  14. #14
    Registered User
    Join Date
    Jul 2009
    Posts
    23
    Sorry, I forgot the code to write the new data into the file. It works now.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. compare function ignoring leading white space
    By mc72 in forum C Programming
    Replies: 5
    Last Post: 11-23-2008, 01:33 PM
  2. loops with incrementing strings .... ?
    By twomers in forum C++ Programming
    Replies: 1
    Last Post: 12-12-2005, 11:29 AM
  3. strings and loops...
    By twomers in forum C Programming
    Replies: 5
    Last Post: 12-12-2005, 11:28 AM
  4. question about reading in strings from a file :>
    By bball887 in forum C Programming
    Replies: 8
    Last Post: 04-13-2004, 06:24 PM
  5. Scanning Strings till no white space is found?
    By HomerJ in forum C++ Programming
    Replies: 3
    Last Post: 05-01-2002, 02:02 PM