C Newbie Help: Strings, Arrays, Getline() & Sscanf() - Urgent (Due Monday)

AI Thread Summary
The discussion focuses on using getline() and sscanf() in C to read and process input data into arrays. The user is required to validate and store specific formatted data from standard input, including checking character ranges and ensuring numerical values meet certain criteria. Suggestions include using a loop to process each line immediately after reading it, rather than overwriting previous data, and employing functions like isalpha and isdigit for character validation. The user also seeks guidance on ensuring that price values have two decimal places and are positive, with advice to handle this validation while the data is still in string format. Overall, the conversation emphasizes proper data handling and validation techniques in C programming.
subwaybusker
Messages
47
Reaction score
0
I am required to use getline() and sscanf() somewhere in my function to read standard input and store it into arrays.
I have input like this:

10/10/08 12:00
A1:2.31:1:P
2B:1.98:2:g
2b:1.82:3:b

the first line is the time, which i used strcpy to copy it to an array called time[]
the second to fourth lines i am required to check that the first two characters before the colon are between a-z, A-Z, 0-9, plus i need to store it in a two dimensional array which i have no idea how. The characters after the first colon need to be to 2 decimal places only and positive, the characters after the second colon need to be positive, and the character after the third colon can only be chosen from a few specific characters.
So far i have this in my function:

int c;
int a=0;
while((getline(line, NUM))>0)
if (line[2]=='/')
strcpy(time, line);
else strcpy(purchaseline, line);
/*don't know how to filter out the characters that don't meet the requirements. maybe use a for loop? maybe i could declare 5 new int/chars so that sscanf can store the input there, and then i could test the condition of the values stored in these int/chars and choose to store them in the actual name, price, quantity, taxtype arrays?*/
sscanf(purchaseline, "%c%c:%0.2lf:%d:%c", name+a, name+a+1, price+a, quantity+a, taxtype+a);

/*name, price, quantity, and purchaseline are all arrays*/

this is basically the boiled down version of the assignment i think
if anyone has time to read more about the assignment, the link is here:
http://www.megaupload.com/?d=D9BDOK1N
 
Last edited by a moderator:
Physics news on Phys.org
You need to store what in a 2d array?
3d arrays aren't directly part of 'c' - you can either make an array of arrays, or if you know how many elements are on each line you can make a struct to hold these values and then make an array of these structs. Or you can store separate 1d arrays for each element in the line.

To find out if a character is in a range you can either compare the character values directly to the values A-Z or you can see the isalpha,isnum and isalphanum() functions.

Your sscanf line is completely wrong. You might want to find an example of scanf() on the net.

hint - put your code in CODE tags - it makes it much easier to read.
Code:
int a
 
thanks for the quick reply

i am given an array called name[NUM][2]
for a given input line, I am to store the first two letters, eg. A1, such that

Code:
name[0][0]='A';
name[0][1]='1';

and i am also not sure what is wrong with my sscanf. i was given the following example in class:

Code:
char c;
int i;
double db;
char s[80], outstring[80],
*instring=“a 100 -1.23 This is a sample data”;
sscanf(instring,“%c%d%lf%s”, &c, &i, &db, s);
//Then c=‘a’, i=100, db=-1.23, s=“This”

however, i made some changes to it just now and now it looks like this:

Code:
 int c;
 int a=0,b=0;
 char name1;
 char name2;
 double price1=0;
 unsigned int quantity=0;
 char taxtype;


 while((getline(line, NUM))>0){
    if (line[2]=='/')
        strcpy(time, line);
    else strcpy(purchaseline, line);
 }
sscanf(purchaseline, "%c%c:%0.2lf:%d:%c", &name1, &name2, &price1, &quantity, &taxtype);

 if ((name1>='a'&& name1<='z')||(name1>='A'&& name1<='Z')||(name1>='0'&& name1<='9')){
    if ((name2>='a'&& name2<='z')||(name2>='A'&& name2<='Z')||(name2>='0'&& name2<='9')){
        if (price1>0){
            name[a][0]=name1;
            name[a][1]=name2;
            price[a]=price1;
            if (taxtype=='g' || taxtype=='G')
                tax_type[a++]=taxtype;
            else if (taxtype=='p' || taxtype=='P')
                tax_type[a++]=taxtype;
            else if (taxtype=='b' || taxtype=='B')
                tax_type[a++]=taxtype;
            else
                tax_type[a++]='N';
        }
    }
 }
 
Mostly the right idea:

You are looping over all the input lines but only processing the last one after the loop exits.
You need to put the parsing code inside the loop inplace of the secondstring copy.
Or better, put it in a function that takes a string as the input and call it from inside the loop.

ps. You haven't defined time or purchase line.
pps. time isn't a good name - there is a library call called time() that returns the time!
It doesn't matter to your code butwill confuse people.
 
sorry, i have no idea what you meant by

"You need to put the parsing code inside the loop inplace of the secondstring copy.
Or better, put it in a function that takes a string as the input and call it from inside the loop."

i put the huge chunk from sscanf onwards inside the while loop. and time and purchaseline were also given arrays. they are declared as static arrays along with name, price, quantity, etc.
 
What you are doing is

1, read line
2, copy line into purchaseline, overwriting previous purchase line
3, repeat from 1
4, When all lines done split purchaseline (note this is just the last purchaseline)

What you meant to do is
1, read line
2, copy line into purchaseline, split purchaseline
3, repeat from 1
 
does this look good now? this is my entire function

Code:
void purchase(void)
{
 int c;
 int a=0,b=0;
 char name1;
 char name2;
 double price1=0;
 unsigned int quantity=0;
 char taxtype;


 while((getline(line, NUM))>0){
    if (line[2]=='/')
        strcpy(time, line);
    else strcpy(purchaseline, line);

 sscanf(purchaseline, "%c%c:%0.2lf:%d:%c", &name1, &name2, &price1, &quantity, &taxtype);

 if ((name1>='a'&& name1<='z')||(name1>='A'&& name1<='Z')||(name1>='0'&& name1<='9')){
    if ((name2>='a'&& name2<='z')||(name2>='A'&& name2<='Z')||(name2>='0'&& name2<='9')){
        if (price1>0){
            name[a][0]=name1;
            name[a][1]=name2;
            price[a]=price1;
            if (taxtype=='g' || taxtype=='G')
                tax_type[a++]=taxtype;
            else if (taxtype=='p' || taxtype=='P')
                tax_type[a++]=taxtype;
            else if (taxtype=='b' || taxtype=='B')
                tax_type[a++]=taxtype;
            else
                tax_type[a++]='N';
        }
    }
 }

 }
}

but when i run my program, this function for some reason doesn't terminate. I know this because i have a couple other functions as well. If i have purchase run before the other functions, the other functions are never executed.

also, how do i enter standard input? i am told to use a unix command like:

./receipt < input.txt

but I am using an IDE called Codeblocks, so I have no idea how to enter input to check my program.
 
Looks good, you could print the line read by getline immediately after the while line to check what is read.
Either in codeblocks there will be an option to set commandline arguements.
Or you can find where it puts the output executable and from the command line run the above command.
Codeblocks runs on lots of platforms- what OS are you using?

ps. getline() is gcc addition to the language, the more standard way is to use fgets(line, NUM, stdin)
getline() can expand the string memory if the line is too long, but that isn't a problem here.
 
Last edited:
mmm, i don't know how to do the commandline arguments and such, so i just tested my program by manually inputting the data and then using EOF to end it.
My OS is Vista.
for the program, i am supposed to make sure the standard input of price[] only has 2 decimal places and is positive. how do i do this?
I tried using

Code:
if (price>0.01 && (100*price - (int)100*price)==0)
    then blah blah blah
but then i know i can't compare the double value 100*price with and integer
 
  • #10
You can't tell how many places a number has once you convert it into floating point.
The computer stores floating point as an approximation.

To count the number of digits you would have to do it while it is still a string - so find the position of the '.' and the second ':' characters in the string and count the number of characters between them.
 
  • #11
thanks to mgb phys for all your help!
 
Last edited:

Similar threads

Back
Top