• Welcome to Valhalla Legends Archive.
 

c++ string manipulation

Started by ArticMoogle, October 08, 2003, 05:02 PM

Previous topic - Next topic

ArticMoogle

Im currently working on an input that allows a user to enter multiple variables at a time, in sets of two.

An example would be: 1d 2a 3e 4a 5d 6t

What needs to happen then is the values must be assorted according to their corresponding character type, say d represented dogs.

So how would i take all that input and break it down, and would i use a switch to distribute the data according to its corresponding type?

Please let me know what you think, or if you need a better explanation.

Adron

#1

char buf[] = "1d 2a 3e 4a 5d 6t";
char *p = buf;
while(*p && p[1]) {
  switch(p[1]) {
      case 'd':  printf("%d dogs\n", *p-'0');
          break;
      // insert more cases...
  }
  p += 2;
  while(*p == ' ') p++;
}


That's all using C string manipulation, and assuming that the values follow the pattern <digit><char><space(s)>.


ArticMoogle


ArticMoogle

I just want to definitely make sure I understand what you've given me, so let me break it down...

char buf[] = "1d 2a 3e 4a 5d 6t";

The above stament declares buf as an array and sets its value to "1d 2a 3e 4a 5d 6t"

char *p = buf;

I think this means that *p points to the address of buf???

while(*p && p[1]) {
This initiates the loop, and the middle stuff im not too sure about.

switch(p[1]) {
     case 'd': printf("%d dogs\n", *p-'0');
     case 'D':
        break;


These statements start the switch while in the loop, and printf is some kind of formatting i guess, and again im unsure about the things in parenthesis.

I'm sure this gives you a pretty good view of my knowledge in c++, I'd appreciate whatever you decide to elaborate on, some of it, none of it. Thanks! :)

iago

buf is a pointer to a list of characters (ie, your string).  *p dereferences the address of buf, which would return the character.

One note about adron's code: if one of the numbers is >10, it won't work right.  
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Adron

#5
Which is why I noted that it worked if the format was <digit><char>, as opposed to <number><char> :P

*p and p[1] verifies that there are at least two more non \0 characters in the string.

printf, well, that's too complex a function - you should just look up how the formatting strings work in the online help.

ArticMoogle

Ok, i've think got the way of it now...Thanks much!

But now i have another question  ;D

Inside the switch im sending the data to a struct, say pet. So one of the cases would be...

case d: pet.dogs=p[1]

also. if i used double buf[] it would work with >10 as well?

Sorry if im exasperating you all :)

iago

No, because the *p line (which, in my opinion, shoudl be if p[0] && p[1] for the sake of consistancy) returns a single character.  To do any more would take a little more effort to parse; in fact, I'm not sure if there's any good way unless you force them to put a space between the number and letter, such as "1 d 2 c ..."etc. or on seperate lines, like this:
-----
1 d
2 c
4 b
-----

In that case, you could do this (assuming that the string is coming from a file):
int num;
char code;
FILE *File = fopen("pets.dat", "r");
// error checking goes here if File is NULL fail
while(fscanf(File, "%d %c", &num, &code) == 2)
{
 switch code:
case 'd':
 mything.dogs += num;
 break;
// case ....
}
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


iago

#8
Another (in my opinion, better) way to do it, instead of using a struct, would be like this:

enum AnimalTypes { Dog, Cat, Beaver, Hippo, Giraffe, Oprah, NUM_ANIMALS };

int MyAnimals[NUM_ANIMALS];

bool CountAnimals(char *Filename)
{
 int Num;
 char Type;
 FILE *File = fopen(Filename, "r");
 if(File == NULL)
  return false;
 
 while(fscanf(File, "%d %c", &Num, &Type) == 2)
 {
    switch(Type)
    {
    case 'd':
      MyAnimals[Dog] += Num;
      break;
    case 'c':
      MyAnimals[Cat] += Num;
      break;
   //...etc.
    }
 }
 return true;
}


Note that this is untested, but I'm reasonably sure it should work (logically anyway, I may have made a typo).
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Kp

You could instead use strtoul to convert the number into internal representation; doing so permits you to have one or multiple digits, and to express it in any base between 2 and 36 inclusive.  Further, doing so gets rid of the need for a space to separate the count and the type specifier.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

iago

Quote from: Kp on October 08, 2003, 11:51 PM
You could instead use strtoul to convert the number into internal representation; doing so permits you to have one or multiple digits, and to express it in any base between 2 and 36 inclusive.  Further, doing so gets rid of the need for a space to separate the count and the type specifier.

aah, you're right.. atoi (or itoa.. I forget) would also work, and is a little easier to use.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Kp

Quote from: iago on October 08, 2003, 11:59 PMaah, you're right.. atoi (or itoa.. I forget) would also work, and is a little easier to use.
itoa makes internal representations printable; atoi converts strings to internal representation.    However, it is inferior in that a) it does not allow you to specify base and b) it does not provide a mechanism of locating  the first non-parsed character in the string.  strtoul suffers neither of these problems.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

iago

atoi() is obviously the one I was looking for.

In this case, 1) he'll always be using base 10, and 2) the pointer will always be at the beginning of the string anyway, and 3) he's a newb to programming, and int itoa(char *num) is a lot easier to use :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


ArticMoogle

Thanks for all the different solutions guys, I was just trying to make sure I understood what was going on instead of copying code you gave me.

Thanks again!

iago

Quote from: ArticMoogle on October 09, 2003, 08:31 AM
Thanks for all the different solutions guys, I was just trying to make sure I understood what was going on instead of copying code you gave me.

Thanks again!

That's the impression I got, which is why I posted a couple different solutions.  You seemed like you were trying to learn, so I had no problem with writing a little code for you :-)

You're welcome!!
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*