471,086 Members | 1,159 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,086 software developers and data experts.

strtok question

10
If I understand it correctly, strtok scans from the first character after the separator. The code below:
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4.  
  5. void main()
  6. {
  7.     char *rules[50];
  8.     int priority[50];
  9.     int i=0;
  10.     char line[100]=" (arule, 12), (brule, 21), (zrule, 70), (drule, 25), (erule, 10)(frule, 3)(grule, 20), (srule, 100)";
  11.  
  12.     char *tok = strtok(line,"(");
  13.     rules[i]=strtok(NULL,",");
  14.  
  15.     tok=strtok(NULL,")");
  16.     priority[i]=atoi(tok);
  17.     i++;
  18.  
  19.     while((tok=strtok(NULL,"("))!=NULL)
  20.     {
  21.         rules[i]=strtok(NULL,",");
  22.         tok=strtok(NULL,")");
  23.         priority[i]=atoi(tok);
  24.         i++;
  25.     }
  26.  
  27.     for(int j=0;j<i;j++)
  28.     {
  29.         cout<<rules[j]<<endl;
  30.         cout<<priority[j]<<endl;
  31.     }
  32. }
gives an output like this:

arule
12
brule
21
zrule
70
drule
25
erule
10

However, if I remove the space between " and (arule, 12) so the line would look like:

Expand|Select|Wrap|Line Numbers
  1.     char line[100]="(arule, 12), (brule, 21), (zrule, 70), (drule, 25), (erule, 10)(frule, 3)(grule, 20), (srule, 100)"; //there's no space between " and (arule, 12)
then the output would become:

brule
21
zrule
70
drule
25
erule
10

Why is a space needed between " and the first separator in order for the program to work correctly? Am I doing something incorrectly?
Mar 23 '07 #1
8 1888
horace1
1,510 Expert 1GB
the first token is framed with (, so try
Expand|Select|Wrap|Line Numbers
  1.     char line[100]="(arule, 12), (brule, 21), (zrule, 70), (drule, 25), (erule, 10)(frule, 3)(grule, 20), (srule, 100)";
  2.     char *tok; 
  3.     rules[i]=strtok(line,"(,");
  4.  
Mar 23 '07 #2
cting76
10
the first token is framed with (, so try
Expand|Select|Wrap|Line Numbers
  1.     char line[100]="(arule, 12), (brule, 21), (zrule, 70), (drule, 25), (erule, 10)(frule, 3)(grule, 20), (srule, 100)";
  2.     char *tok; 
  3.     rules[i]=strtok(line,"(,");
  4.  
Thank you. That fixes the problem.

I then modified the input into:

Expand|Select|Wrap|Line Numbers
  1. char line[100]="(arule, 12), (brule, 21), (zrule, 70), (drule, 25), (erule, 10)(frule, 3)(grule, 20), (srule, 100)";
Notice that there's no "," between "(erule, 10)", "(frule, 3)", and "(grule, 20)". What I want to do is, let the program read from "(arule, 12)" until "(erule,10)", pause right before "(frule,3)", do something, then continue reading "(frule, 3)", pause before "(grule, 20)", do something, then continue reading "(grule,20), (srule, 100)".

So far I've tried adding:

Expand|Select|Wrap|Line Numbers
  1. char next[2]=")";
and then changing the while loop to:

Expand|Select|Wrap|Line Numbers
  1.     while((num=strtok(NULL,"("))!= NULL && (num=strtok(NULL,"("))!=next)
  2.     {
  3.         rules[i]=strtok(NULL,",");
  4.         num=strtok(NULL,")");
  5.         priority[i]=atoi(num);
  6.         i++;
  7.     }
but the output becomes:

arule
12
zrule
70
erule
10
srule
100

I figured everytime a strtok is called it changes the beginning token so I then changed the while loop into:

Expand|Select|Wrap|Line Numbers
  1.     while((num=strtok(NULL,"("))!= NULL)
  2.     {
  3.         rules[i]=strtok(NULL,",");
  4.         num=strtok(NULL,")");
  5.         priority[i]=atoi(num);
  6.         i++;
  7.  
  8.         if(num==next)
  9.             cout<<"pause"; //to test if the condition works
  10.     }
but the output becomes:
arule
12
brule
21
zrule
70
drule
25
erule
10
grule
20
srule
100

What am I doing wrong?

Thank you.
Mar 24 '07 #3
cting76
10
Will someone be so kind to point out why my program hangs? It doesn't give out any error message other than "<program_name has stopped working>".

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4.  
  5. void main()
  6. {
  7.     ifstream infile;
  8.     char c[256],str[64];
  9.     char *rules[50];
  10.     int priority[50];
  11.     int i=0;
  12.     char *num;
  13.  
  14.     cout<<"Enter the name of input file: ";
  15.     cin.get(str, 64);
  16.  
  17.     infile.open(str);
  18.  
  19.     for(i=0;i<256;i++)
  20.     {
  21.         c[i]=infile.get();
  22.         cout<<c[i];
  23.     }
  24.  
  25.     cout<<endl;
  26.     i=0;
  27.  
  28.     rules[i]=strtok(c,"(,");
  29.     num=strtok(NULL,")");
  30.     priority[i]=atoi(num);
  31.  
  32.     cout<<endl;
  33.     cout<<rules[i];
  34.     cout<<endl;
  35.     cout<<priority[i];
  36.     cout<<endl;
  37.  
  38.     i++;
  39.  
  40.     while((num=strtok(NULL,"("))!=NULL)
  41.     {
  42.         rules[i]=strtok(NULL,",");
  43.         cout<<rules[i]<<endl;
  44.         num=strtok(NULL,")");
  45.         priority[i]=atoi(num);
  46.         cout<<priority[i]<<endl;
  47.         i++;
  48.     }
  49. infile.close();
  50. }
The input file has only one line:
(R10, 10), (R20, 20), (R90, 90), (R75, 75), (R35, 35), (R60, 60).

The program works just fine if I include the input line in the program (in other words: char c[100]="(R10, 10), (R20, 20), (R90, 90), (R75, 75), (R35, 35), (R60, 60)"; works just fine). But it would hang at the while loop when the input is reading from a file. It would output

R10
10
R20
20
R90
90
R75
75
R35
35
R60
60

but hangs right after 60. Looks to me it is unable to "satisfy" the !=NULL condition but I can't why.

Any advice appreciated.

Thank you.
Mar 25 '07 #4
horace1
1,510 Expert 1GB
your program works fine with GNU C++.
The problem may be in your the loop where you read a line from the file
Expand|Select|Wrap|Line Numbers
  1.     for(i=0;i<256;i++)
  2.     {
  3.         c[i]=infile.get();
  4.         cout<<c[i];
  5.     }
  6.  
in that the string is not being properly null terminated with your compiler.
try
Expand|Select|Wrap|Line Numbers
  1.     infile.get(c,256);
  2.  
so you read up to 256 characters or until a newline is found
Mar 25 '07 #5
cting76
10
Expand|Select|Wrap|Line Numbers
  1. infile.get(c,256);
  2.  
so you read up to 256 characters or until a newline is found
Thank you! I wasn't aware of the difference between c[i]=infile.get() and infile.get(c,256). Now the program can read the line just fine. However, it hangs again if the input is like this:

(arule, 10), (brule,20)(crule, 30)(drule, 40), (erule, 50)(frule, 60)

I use Visual Studio and it simply says the program (the one I wrote) has stopped working. The output would look like this:

arule
10
brule
20
drule
40
erule
50

(crule, 30) and (frule, 60) are both missing. I think it's got something to do with how the delimiter is set up. What I am trying to do is, let the program read block "(arule, 10), (brule, 20)", do something, read (crule, 30), do something, read block "(drule, 40), (erule, 50)", do something, then read (frule, 60) and do something. So how do I make a condition that says if current token ends with ")" and there's a "(" immediately follows, then do something before continue reading next block?

Thank you.
Mar 25 '07 #6
horace1
1,510 Expert 1GB
it gives a segmentation error with Visual; C++ on my machine
the problem is if strtok() returns NULL within your loop - you need to check and if so exit the loop, e.g.
Expand|Select|Wrap|Line Numbers
  1.     while((num=strtok(NULL,"("))!=NULL)
  2.     {
  3.         if((rules[i]=strtok(NULL,","))==NULL)break;
  4.         cout<<rules[i]<<endl;
  5.         if((num=strtok(NULL,")"))==NULL)break;
  6.         cout << "num " << num <<endl;
  7.         priority[i]=atoi(num);
  8.         cout<<priority[i]<<endl;
  9.         i++;
  10.     }
  11.  
Mar 25 '07 #7
cting76
10
it gives a segmentation error with Visual; C++ on my machine
the problem is if strtok() returns NULL within your loop - you need to check and if so exit the loop, e.g.
Expand|Select|Wrap|Line Numbers
  1.     while((num=strtok(NULL,"("))!=NULL)
  2.     {
  3.         if((rules[i]=strtok(NULL,","))==NULL)break;
  4.         cout<<rules[i]<<endl;
  5.         if((num=strtok(NULL,")"))==NULL)break;
  6.         cout << "num " << num <<endl;
  7.         priority[i]=atoi(num);
  8.         cout<<priority[i]<<endl;
  9.         i++;
  10.     }
  11.  
Shouldn't num=strtok(NULL,"(")) return NULL if there's no more element after the last ")"?
Mar 25 '07 #8
cting76
10
Alright I have modified my code into this:

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. using namespace std;
  5.  
  6. #define index 5
  7.  
  8. struct am{
  9.     string rule;
  10.     int priority;
  11. }set[index];
  12.  
  13. void printset(am amg)
  14. {
  15.     cout<<amg.rule<<endl;
  16.     cout<<amg.priority<<endl;
  17. }
  18.  
  19. void main()
  20. {
  21.     ifstream infile;
  22.     char c[256],str[32];
  23.     char *rules[50];
  24.     int priority[50];
  25.     int i=0;
  26.     char *num;
  27.  
  28.     cout<<"Enter the name of input file: ";
  29.     cin.get(str, 32);
  30.  
  31.     infile.open(str);
  32.     infile.get(c,256);
  33.  
  34.     set[i].rule=strtok(c,"(,");
  35.  
  36.     for(i=0;i<index;i++)
  37.     {
  38.         num=strtok(NULL,")");
  39.         set[i].priority=atoi(num);
  40.         num=strtok(NULL,"(");
  41.         set[i+1].rule=strtok(NULL,",");
  42.     }
  43.     for(int n=0;n<index;n++)
  44.         printset(set[n]);
  45.  
  46. infile.close();
  47. }
That solves the while loop problem. But another problem still stands: the program reads just fine with input of (arule, 10), (brule,20), (crule, 30), (drule, 40), (erule, 50), (frule, 60). But if the input is (arule, 10), (brule,20)(crule, 30)(drule, 40), (erule, 50)(frule, 60), the program will hang.

Please advise on how to tell the strtok to separate ") from "(", or pause at ")" if the immediate element is "(". Thank you.
Mar 25 '07 #9

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

5 posts views Thread by tvn007 | last post: by
7 posts views Thread by Fernando Barsoba | last post: by
13 posts views Thread by ern | last post: by
17 posts views Thread by bofh1234 | last post: by
5 posts views Thread by Kelly B | last post: by
11 posts views Thread by Lothar Behrens | last post: by
3 posts views Thread by krista | last post: by
8 posts views Thread by Stu Cazzo | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.