Jump to content


 


Register a free account to unlock additional features at BleepingComputer.com
Welcome to BleepingComputer, a free community where people like yourself come together to discuss and learn how to use their computers. Using the site is easy and fun. As a guest, you can browse and view the various discussions in the forums, but can not create a new topic or reply to an existing one unless you are logged in. Other benefits of registering an account are subscribing to topics and forums, creating a blog, and having no ads shown anywhere on the site.


Click here to Register a free account now! or read our Welcome Guide to learn how to use this site.

Photo

Novice C(++), Need Help On Error.


  • Please log in to reply
17 replies to this topic

#1 zyrolasting

zyrolasting

  • Members
  • 45 posts
  • OFFLINE
  •  
  • Local time:05:07 AM

Posted 03 July 2008 - 12:01 PM

Since I am still fairly new to this, please bear with me if I missed something obvious.
I am working on a program that is meant to return values to another app based on certain chars entered into the program. It is not important what they do, since that is off topic.
What I do need to know is why my conditional operator isn't being evaluated. This condition is only meant to check if a value of argv[1 through argc-1] in a nested loop, and set an array value called "flag" to 1 that is incremented in the base loop.

This is the header for my program. quosym.h

#include <stdio.h>
char file_quosym[10]={'@','$','#','&','x','[','(','s','*'};

Just a simple 2 lines, array intended to be global obviously.
And here is the program.

#include "quosym.h"int main(int argc,char *argv[]){     int flag[10]={0}, i=0, j, ret;     while (argc--) //Until argvs last valid index is reached     {          for (j=0; j<9; j++) //Run through fil_quosym array for every char in argv          {                   flag[j]+=((char)argv[i]==file_quosym[j]) ? (1) : (0);          }          i++;//Head to next value in argv     }     return 0; //Ignore this. Still pondering proper way to return it.}

This was my error message from the compiler (Dev C++)
ISO C++ forbids comparison between pointer and integer
This was indifferent whether the char typecast was there or not.

Changing the ?: to an if ((char)argv[i]==file_quosym[j]) was no different.
Am I unable to get char values from argv? What's my best course of action here?

Edited by zyrolasting, 03 July 2008 - 12:04 PM.


BC AdBot (Login to Remove)

 


m

#2 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 03 July 2008 - 10:08 PM

Youre problem is that you are refrencing a pointer. argv contains an array of pointers, which themselves point to arrays of null terminated character arrays. Argv does not contain the actual values.

Each seperate command parameter from the command line is passed as a seperate array. And each pointer is to a null terminated string of the command line option.

So if I do
program.exe -yes -something -two

Then argv will contain four memmory addresses. The first points to a null terminated string "program.exe". The next points to a null terminated string "-yes". And the next "-something", and "-two" after that.

Do you know what a pointer is?

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#3 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 03 July 2008 - 10:10 PM

Also, what is "fil_quosym" and array of? Integers, characters, floats?

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#4 zyrolasting

zyrolasting
  • Topic Starter

  • Members
  • 45 posts
  • OFFLINE
  •  
  • Local time:05:07 AM

Posted 04 July 2008 - 01:08 AM

I am not able to get to my compiler right now, so I'm just running off what is available here.

I do know about pointers, but I did not yet grasp the concept of an array of pointers. Simply because I am novice and all that did was make me a bit disoriented. Mostly due to how I assign and access deeper values.
By the way, you just read a typo in a comment. It's file_quosym, and if you look at my first post again you see it in the header, above the codebox (Just 2 lines). It's char.

Alright, so what if I just add another asterisk to argv[i] in my for loop? If I were to make a guess, it would seem it's just stepping down a hierarchy.
Please let me know if that's a mistake. Also, I saw some weird banner ad embed in my first post. I have not seen that happen in this kind of forum. What's that about?

#5 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 04 July 2008 - 06:08 AM

Ads are embeded for some user accounts. If you wern't logged in, you might of seen it.

The asterisk is basicly what it boils down to. The one line inside the while loop can be something like this:
char tempchar;
tempchar = *(argv[i]); //Since a pointer to an array is a pointer to the first element in the array, we don't have to subscript it.
if (tempchar == file_quosym[j]) flag[j]++;

I put in the extra char variable so you could see what's going on easier. Of course, you could put *(argv[i]) in for tempchar in the if statement and save a few lines ;)

Hope that helps!

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#6 zyrolasting

zyrolasting
  • Topic Starter

  • Members
  • 45 posts
  • OFFLINE
  •  
  • Local time:05:07 AM

Posted 04 July 2008 - 11:03 AM

I'm thrilled to say I got some response from the program, but it's still being a bit argumentative. (heh) Your suggestion has fixed the issue of evaluating and returning an expression, but apparently
my issue now resides in argv. I looked up that the valid argument I tested "@$#" only had @ printed back to me (printf added to source). I recall that these arguments can be split by white spaces,
so I need to access one level deeper to grab the characters I need. In other words, I only need the chars in argv[1]. Now that that is cleared, I probably should remove the i increment, but I figured I'd try to find another use for it. I could do "@ $ #" but that would be cumbersome for the app this is intended for.

#include "quosym.h"int main(int argc,char *argv[]){     int flag[10]={0}, i=0, j, ret;     while (argc--) //Until argvs last valid index is reached     {          for (j=0; j<9; j++) /*Run through file_quosym array for every char in argv*/          {                   flag[j]+=(*(*argv[1])+i==file_quosym[j]) ? (1) : (0); /*Changed here, w and w/o parenthesis.                                                                                                      Attempts to step down in char array in argv[1] to ind i.*/                   if (flag[j]) printf("Quosym %c detected",file_quosym[j]);                   i++; //Moved to nested, and also tried just below at the original line.          }     }     return 0;}

That crashed and burned. To be honest, again I have no clue what I'm doing when it comes to accurately accessing an array of pointers.
So can you tell me anything about accessing the char array of argv[1]?

Edited by zyrolasting, 04 July 2008 - 11:04 AM.


#7 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 04 July 2008 - 04:07 PM

argv <-- array of pointers
argv[1] <-- Access the second element in the array of pointers, or the second command line string (We want to skip the first argument, which is always the name of the program itself.
*(argv[1]) <- Now we have a pointer to a null teriminated character array of the characters
*(argv[1] + 1) <-- Add the width of one character to the memory address before getting the value, this will get the next char.
(*(argv[1]))[1] <-- Same as above using sub scripting instead of pointer arithmetic
*(argv[1] + 2) <---+-- Access the third character in the array
(*(argv[1]))[2] <--/

It should be noted that C allows access to random ram when you, for example, read beyond the end of a null terminated character string. Because the string ends with a null (a zero, not the ascii equivelent but \0), if you want to loop the string you can typically do this:

char *charPointer;
charPointer = argv[1];
while(*charPointer) {
//Do something using *(charPointer) as the current character
charpointer++;
}

Does that help?

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#8 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 04 July 2008 - 04:09 PM

Oh, let me throw in that pointer arithmatic is usually MUCH faster ;)

I suggest you read this:
http://www.cplusplus.com/doc/tutorial/pointers.html

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#9 zyrolasting

zyrolasting
  • Topic Starter

  • Members
  • 45 posts
  • OFFLINE
  •  
  • Local time:05:07 AM

Posted 05 July 2008 - 01:58 AM

Alright, we've got progress but we're still not in the clear. Thanks so much for input thus far!
The code is now reading in one entry, but the read and what I am told is found is erratic.
Right now my only concern is that the program is understanding the set chars for file_quosym
in order.

My header remains unchanged

#include <stdio.h>
char file_quosym[10]={'@','$','#','&','x','[','(','s','*'};

Say if my passed argument was @#$. Indexes 1, 3 and 2 respectively.
Printf tells me...

detected @
detected @
detected #
Indexes 0,0,2 were read out of the run.

I assumed that values could interfere with printf's control string (doubt it) so I messed around with values.
Please check these returns below.

$$#
detected $
detected $
Indexes 1,1, no attempt to continue.

$@#
detected $
detected @
detected $
Indexes 1,0,1. Offset/Innacurate 3rd run, defies cPoint++ in code below.

Here is my updated source, following your recent advice. I hit another block, since I believe there is something wrong with the position of the
char array of argv[1]. Of course, with starting at it's first char and incrementing by 1 I have no idea where it flops. Please inform me of my error.

I read the link you sent. I did still grasp the first few sections, but the pointer arithmetic and everything following was useful to know. Thanks!
Oh, and just in case the above mentioned index 0 is blurring things, it's just making sure that only file_quosym and flag remain parallel. I'm sure you caught that, but I'm just mentioning as a precaution.

#include "quosym.h"
int main(int argc,char *argv[])
{
	 int flag[10]={0}, j;
	 char *cPoint;
	 cPoint=argv[1];
	 while (argc--) //Until argvs last valid index is reached
	 {
		  for (j=0; j<9; j++) /*Run through file_quosym array for every char in argv*/
		  {
				   flag[j]+=((*(cPoint))==file_quosym[j])?(1):(0);
				   if (flag[j])
					   printf("%c detected.\n",file_quosym[j]);
		  }
		  cPoint++;
	 }
	 return 0;
}

Edited by zyrolasting, 05 July 2008 - 02:08 AM.


#10 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 05 July 2008 - 09:01 AM

Change this line:
flag[j]+=((*(cPoint))==file_quosym[j])?(1):(0);
to this:
flag[j] = ((*(cPoint))==file_quosym[j])?(1):(0);.

You can't add to values in flag because you don't know what they are. You only initialized the first index of flag, not the other ones. So, flag[0] = 0, flag[1] = ?????

See if that works.

Also, please let me know exactly what you're trying to do. I will write a function that does what you're trying to do and walk through it with you, if you wish ;)

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#11 zyrolasting

zyrolasting
  • Topic Starter

  • Members
  • 45 posts
  • OFFLINE
  •  
  • Local time:05:07 AM

Posted 05 July 2008 - 01:00 PM

The program began reading correctly, but is now always stopping after two checks of char.
Such as @#$ prints @# or $#@ to $#

Alright, I'll explain my function as best I can.

I have a homebrew video game that is managed by an engine I designed in another language. It communicates with the file system by loading copies for the game, and manipulating them as it is loaded with characters assigned to the file. These are what I called the quosyms, which is just a fictitious name I based on something. Each character is checked, and a flag is toggled to 1 every time one of these chars is found. This prepares the game for the altered loaded file, since the host game is the app that does the manipulating. This app is meant to return the flags set, which I am pondering how since arrays can't be exported easily. I do have a script that can pull values by separation in string.

For example, if I made a return "1|0|1|0|0|1|" (a string) the script outside I wrote would read this and get 101001, even though that was all of the flag elements.
So since I understand a complete array return is impossible I would like to return a string version of them all added together.
I was thinking another for loop and typecast values, but I did not know how exactly to combine them.

So to summarize
-Flag array zeroed out before read begins.
-Reads chars that flag a file.
-Compares the next char to the index. If there is a match, a flag with the same element as the char is toggled to 1. Everything else is ignored.
-This is done by a for loop doing a sequential step through both flag and file_quosym.
-Returns a string version of all flag elements.

I really would appreciate a walk through for the sake of learning a better way, but you really don't have to do that. Just some advice and suggestions on my return issue along with the one index early stop would be great. Thanks so much for your help thus far!

#12 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 05 July 2008 - 01:34 PM

Does the order of the members matter? In other words, if I pass #$?, should that return the same result as ?#$ in your result string-ized array?

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#13 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 05 July 2008 - 05:46 PM

Have fun with this:
[codebox]#include <iostream> //required for cout
#include <cstdlib> //required for strlen and the EXIT_SUCESS macro

using namespace std;

char file_quosym[]="@$#&x[(s*"; //file_quosim is a null terminated character array who's size is determined at compile time by the compiler

int main(int argc,char *argv[])
{
char *flags, *workingFileQuosym;
workingFileQuosym = file_quosym;
flags = new char[strlen(file_quosym) + 1]; //create another null terminated string
flags[strlen(file_quosym)] = '\0'; //we want a result of a null terminated string, so null the thing out.
while(*(workingFileQuosym)) { //loop through each character we're searching for
flags[workingFileQuosym-file_quosym] = '0'; //zero out the character we're in.
for (int idx = 1; idx < argc; idx++) { //loop through each argument, starting with the second index (Skip program name)
bool stop = false; //this is just a holder variable so that we can break out of both loops at once
char *currentArg = argv[idx]; //get the current null terminate
while (*(currentArg)) { //loop through the null terminated string
if (*currentArg == *workingFileQuosym) {
cout << "Found character: " << *workingFileQuosym << endl; //Do you really need a comment for this?
flags[workingFileQuosym-file_quosym] = '1'; //we've found a character, so set this character to 1
stop = true; //tell the if below to break us out of this while
break; //break out of the while loop we're in
}
currentArg++;
}
if (stop) { break; } //if we need to get out of the for loop because we've found the character, we need to stop looping and start looking for the next character. This breaks out of the for loop.
}
workingFileQuosym++;
}
cout << flags;
delete [] flags;
return EXIT_SUCCESS;
}[/codebox]

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image

#14 zyrolasting

zyrolasting
  • Topic Starter

  • Members
  • 45 posts
  • OFFLINE
  •  
  • Local time:05:07 AM

Posted 06 July 2008 - 04:57 AM

Thank you so very much for the app! Works beautifully. (It did spit back out * and & strangely, obviously can't be helped there. =P) However, I would still like to learn my mistakes or limits with my last attempt.
But I must ask, is this many lines necessary? I'd like to learn what you've got here, so I can keep trying this kind of thing on my own.

#15 Billy O'Neal

Billy O'Neal

    Visual C++ STL Maintainer


  • Malware Response Team
  • 12,301 posts
  • OFFLINE
  •  
  • Gender:Male
  • Location:Redmond, Washington
  • Local time:02:07 AM

Posted 06 July 2008 - 07:28 AM

It can be done in fewer lines, however, lots of those lines allow easier configuration. For example, since none of the array sizes are hard coded, you can do this:

Change this line:
char file_quosym[]="@$#&x[(s*";

to this:

char file_quosym[]="@$#somemorechars&x[(s*";

and recompile. The program still operates correctly, and will not require modification.

Also, even though there are a lot of lines, it will probably run faster than the sub scripted function, because sub scripting requires the compiler to add x amount of memory addresses to the pointer that holds the array each time you reference it. By simply moving the pointer manually up the array, using the VERY fast and efficient increment operator (++), you cant really make anything run much faster.

This program relies on two fundamental concepts to c(++). Pointers, which I already showed you earlier, and Null Terminated Strings.
See here for info on those:
http://www.cplusplus.com/doc/tutorial/ntcs.html

C relies much more on pointers than at first glance. All arrays are pointers. All arrays can be accessed by pointers, and are usually looped with pointers.

I would also like to highly recomend Visual Studio as your ide, which is free here:
http://www.microsoft.com/express/vc/

The debugger is much better put together :thumbsup:. When you can step through the program line by line and read the variables in the process to see what's going on, it makes things MUCH easier :flowers:

Billy3
Twitter - My statements do not establish the official position of Microsoft Corporation, and are my own personal opinion. (But you already knew that, right?)
Posted Image




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users