Hex editor

Hi.

I've got a project to do but can't get through with some things.

My program so far takes a binary number converts it to dec and then from dec to hex and writes it a screen.

It has to replace some bytes of a hex number with different ones using command line. I was thinking of puting the hex to number to a char array and then replacing the values. My problem with it is how to put it in an array.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip>  

using namespace std;

long dec(long bin);
void  hex();


int main()
{

	hex();

	system("pause");//i know that's wrong and resources hungry
	return 0;
}

void hex()
{

	long bin;
	ifstream plik;
	plik.open("X:\\projekt\\dane.txt");
	plik >> bin;

	cout << hex << dec(bin) << endl;

}


long dec(long bin)
{
	long zmienna = 1;
	long suma = 0;

	while (bin != 0)
	{
		suma += (bin % 10) * zmienna;
		bin /= 10;
		zmienna *= 2;
	}
	return suma;
}
Hello kubanm3,

Welcome to the forum.

Your program woks and it does not.

The "dec()" function has worked with everything I have tried. I am guessing that the "dane.txt" file is just a decimal number containing "1's" and "0;s", at least that worked for my testing.

The "hex()" function dos not print out a usable hex number. Line 29 cout << hex ... hex here will only print the address of the function "hex" not the hex number that you want. Try this search link https://www.google.com/#safe=strict&q=c%2B%2B+binary+to+hex for information and code to convert from binary to hex and decimal.

You have a good start, but are missing some code.

Hope that helps,

Andy
It is a decimal number with 1's and 0's.

I've tried to change it to something like that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void hex()
{

	int bin;
	ifstream plik;
	plik.open("X:\\projekt\\dane.txt");
	plik >> bin;

	char hexString[20];
	_itoa_s(dec(bin), hexString, 16);

	for (int i = 0; i < 20; i++)
	{
		cout << hexString[i] << endl;
	}
}


but it returns wrong number. If i put a dec number not a function dec(bin) it does work.
Hello kubanm3,

I do not use "using namespace std;" in my programs, so it took me awhile and some research to figure out how "hex" worked after that it all came together.

"hex", "oct" and "dec" are all format specifiers for "cout". Once i qualified "hex" with "std::" it worked properly. This is how I changd the "hex()" function:

1
2
3
std::cout << "Binary: " << bin << std::endl;
std::cout << "Hex = " << std::hex << std::uppercase << dec(bin) << std::endl;
std::cout << std::nouppercase <<std::dec << "Dec = " << dec(bin) << std::endl;

Leaving "std::" in the above code will not make any difference in your original code. I redid the output to show each bit of information. This is just a rework of your original line 29. The beginning of line 3 is to reset the output to normal before showing the decimal number.

The only drawback is the the variable "bin" does not keep leading "0's".

Not sure how your fix will work. I will have to try it out.

The changes I made are simple, but work.

Hope that helps,

Andy
Last edited on
The problem was a drive letter in a path to txt file. I am on a different PC now and there is no drive X here.

itoa function works and it puts the hex string in an array so it should be easier to have it replaced now.


Could you give me a hand with how the parsing could work here. I have to use switches->(-d, -s, etc.) from command line to operate the program.

For example:
"hexedit -r 10 -s A2F3"
has to replace 2 bytes, 10th and 11th byte with A2 and F3 accordingly.
Hello kubanm3,

Sorry for the delay.It was late when I found you message and it took awhile to reason it out.

I am thinking that you are using some version of Windows and either Visual Studio or Visual C++. I will help to know the correct information and if you are using a network.

"-r 10 -s A2F3" is not used by the program. The program has no way of using this information, so I am thinking it is used by the operating system or a network to allow the program to run.

I do not know what the "-r" and "-s" stand for or why you need to replace something with "A2F3".

I will do my best to help you figure it out, but I need more information to know what to look for.

Andy
Hi.

This is my school project. I have to make a hex editor which will take bin number from a file and convert it to hex. It is supposed to be opened from cmd.
"-r 10 -s A2F3" this is an example use from cmd as to what our program can be able to do.
-
One is replacing some bytes with others and the second thing is 0'ing array from given byte.

I am using visual studio.

-r i guess is meant to trigger some function that will replace those bytes.
Hello kubanm3,

Visual Studio is mostly a given because of the "stdafx.h" file and if you are using a school computer it is most likely on a network. The "-r 10 -s A2F3" could be an identifier for the computer or lab you are using, a routing identifier or something to do with scheduling what order the program runs. Your teacher could best answer this. I do not see why it would change anything in the program as that could cause the program to crash. And there is no indication that it works on the file that the program uses.

I have used computer on a network, but I do not know enough about networks to understand how they work. Maybe someone else here might know.

I do know that in general schools have a funny way of doing things that is different from the norm.

Ask your teacher and let me know what you find out.

Andy
We don't understand each other correctly. I am doing this project on my PC. I am not using school network.

Those -r, -s are parsing switches/indicators/options-don't know how it's called.

This program has to be opened from command line with those parsing switches*.

For example:
"hexedit -r 10 -s A2F3"
has to replace 2 bytes, 10th and 11th byte with A2 and F3 accordingly.

I'm assuming you're calling your program "hexedit". If that's the case, it's your responsibility to parse those parameters in your program.

In order to access those parameters, you must specfy main() as:
 
int main (int argc, const char * argv[])

http://www.cplusplus.com/articles/DEN36Up4/
It's up to you to implement the logic to interpret each parameter.

Hello kubanm3,

I believe I understand you now. In the past year since I have been crating programs with Visual Studio I have not had the need to use switches or whatever they may be called from the command line. Today I have tried using what you have used on both the release and debug version of programs and could see no difference nor did I have to use them.

I did find this web page from Microsoft that might help https://msdn.microsoft.com/en-us/library/windows/hardware/ff539058(v=vs.85).aspx . It gives some explanation, but could be better.

Next question, are you trying to run "hexedit" from the debug build or the release build? I have run both the debug and release versions of a program from the command prompt and both run fine, so I am not sure how to duplicate what you are doing or what to expect.

Have you tried running the program with out the "-r -s"? And what happened?

Andy
Andy

Those -r -s are just an example of how the program SHOULD run. It hasn't been implemented yet.

My problem is that i don't know how to use switches to replace those bytes.
Here's a start on parsing the parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
using namespace std;

string hex_to_ascii (const char * hexstr)
{   string  result;
    //  Up to you to convert the hex representation to to a string
    return result;
}
    
int main (int argc, const char * argv[])
{   int     replace_col;
    string  replace_string;
    
    if (argc != 5)
    {   //  argv[0] is always the program name
        cout << "4 arguments required" << endl;
        return 1;
    }
    //  Check for the -r switch
    if (strcmp(argv[1], "-r") != 0)
    {   cout << "-r expected" << endl;
        return 1;
    }
    //  Get the starting column to replace
    replace_col = atoi (argv[2]);
    //  Check for the -s switch
    if (strcmp(argv[3], "-s") != 0)
    {   cout << "-s expected" << endl;
        return 1;
    }
    //  Get the replacement hex representation
    replace_string = hex_to_ascii(argv[4]);
    //  Up to you to use replace_col and replace_string 
    //  to edit the input file.
    return 0;    
}                    


Note: argument parsing can be relatively simple (as above), or can get complicated. You haven't specified the full syntax of the command line arguments. For example, can -r and -s appear multiple times? Can -r and -s appear in any order?
Last edited on
Thanks. That's great. I'll post the solution when i finish it. Or if I get stuck somewhere.

One question can a few funtions be assigned to one argv[]? Not in one line but if I were to make argv[1] a function to delete bytes and in other argv[1] to replace those bytes?

first:
hexedit -r 10 -s A2F3

second
hexedit -e 12 -s 5
where -e deletes five bytes from 12th column.
Both to have argv[1] argv[2] argv[3] argv[4]?
argv[] is positional. The program name is always in argv[0]. The first argument is in argv[1], the second argument in argv[2], etc.

Command line switches typically have a single purpose. You're trying to use -s for two different purposes, (a hex string, a delete length). Not a good idea.

It's important to define your command line syntax up front so that it is unambiguous. That will make coding your command line parser much easier.

Here's a simple suggested command syntax:

hexedit <arguments>

<arguments> ::= <replace>
::= <delete>
::= <insert>

<replace> ::= -r <startcol> -s <hex-string>

<delete> ::= -d <startcol> -l <delete-length>

<insert> ::= -i <startcol> -s <hex-string>

Last edited on
The code complies but it breaks after running with arguments. I think I've messed up a lot with data types.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip> 
#include <string>
#include <stdlib.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
using namespace std;

int dec(int bin);
string hex2bin(string sciezka);
string hex_zamiana(string wartosc_zamiany, int kol_zamiany, string hexpierwsza);
string sciezka;

int main(int argc, const char * argv[])
{
	int kol_zamiany;
	string hexpierwsza;
	string hexdruga;

	if (argc != 7)
	{
		cout << "7 argumentow oczekiwane" << endl;
		return 1;
	}
	if (strcmp(argv[1], "-d") != 0)
	{
		cout << "-d oczekiwane" << endl;
		return 1;
	}

	string sciezka(argv[2]); // char to string
	hexpierwsza = hex2bin(argv[2]); 
	cout << hexpierwsza;
	if (strcmp(argv[3], "-r") != 0)
	{
		cout << "-r oczekiwane" << endl;
		return 1;
	}

	kol_zamiany = atoi(argv[4]); //number of col, replace to int

	if (strcmp(argv[5], "-s") != 0) 
	{
		cout << "-s oczekiwane" << endl;
		return 1;
	}

	string wartosc_zamiany(argv[6]); //char to string

	hexdruga = hex_zamiana(wartosc_zamiany, kol_zamiany, hexpierwsza); 
	cout << hexdruga;

	system("pause");
	return 0;
}

string hex2bin(string sciezka)
{

	int bin;
	ifstream plik;
	plik.open(sciezka); 
	plik >> bin;

	char hexString[33];
	_itoa_s(dec(bin), hexString, 16); //zamiana z bin na 10 na hex

	return hexString;


}

string hex_zamiana(string wartosc_zamiany, int kol_zamiany, string hexpierwsza)
{
	string hexarray;
	int bin;
	
	
	
	for (int i=0;i<33;i++)
	{
		hexarray[i] = hexpierwsza[i];
	}
	
	
	int k = 0;
	int ilosc_znakow = kol_zamiany + wartosc_zamiany.length();
	for (int i = kol_zamiany; i < ilosc_znakow; i++)
	{
		hexarray[i] = wartosc_zamiany[k];
		k++;
	}

	
	return hexarray;
}

int dec(int bin)
{
	int zmienna = 1;
	int suma = 0;

	while (bin != 0)
	{
		suma += (bin % 10) * zmienna;
		bin /= 10;
		zmienna *= 2;
	}

	return suma;
}
Last edited on
You haven't explained what your command syntax is, so I can't really comment your command parsing. I'm going to assume you're trying to implement what I suggested in my previous post.

Line 23: How did you get to 6 arguments (ignoring program)? In the sample command syntax I suggested, insert, delete and replace all take 4 arguments.

Line 28: You're assuming the first command is always "-d", I presume for delete. If you're implementing the syntax I suggested, then the first argument can be "-d", "-i", or "-r".

It's a nice convention for programs that require arguments, to display the argument syntax if no arguments are found.

Line 37: You're requiring a -r argument. That doesn't make sense for delete. In my suggested syntax, delete (-d) takes a length (-l) argument.

Here's some help on command parsing. I've left the impementation of insert_hexstring(), repleace_hexstring() and delete_hexstring() to you. Note that I've enhanced the syntax to accept multiple commands. Each command having exactly 4 arguments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <string>
using namespace std;

//  Function prototypes
void insert_hexstring (int startcol, const string & hexstr);
void replace_hexstring (int startcol, const string & hexstr);
void delete_hexstring (int startcol, int length);

//  Display program syntax
//  Does not return
void Syntax ()
{   cout << "Program syntax: " << endl;
	cout << "hexedit <arguemnt-set> [ ... <argument-set> ]" << endl;
	cout << "Where <arguemnt-set> is one of: " << endl;
	cout << "\tTo insert: -i <startcol> -s <hexstring>" << endl;
	cout << "\tTo replace: -r <startcol> -s <hexstring>" << endl;
	cout << "\tTo delete: -d <startcol> -l <length>" << endl;
	exit (0);	
}

//  Process a set of 4 arguments
void process_arguments (const string & arg1, const string & arg2, const string & arg3, const string & arg4) 
{   char    cmd1;
    char    cmd2;
    int     startcol;
    int     length;
    
    if (arg1[0] != '-')
    {   cout << "First argument must start with '-'" << endl;
        Syntax ();  //  Does not return;
    }
    if (arg1.size() != 2)
    {   cout << "First argument must be two characters" << endl;
        Syntax ();  //  Does not return
    }        
    if (arg3[0] != '-')
    {   cout << "Third argument must start with '-'" << endl;
        Syntax ();  //  Does not return;
    }
    if (arg3.size() != 2)
    {   cout << "Third argument must be two characters" << endl;
        Syntax ();  //  Does not return
    }        
    cmd1 = arg1[1];
    cmd2 = arg3[1];
    startcol = atoi (arg2.c_str());
    switch (cmd1)
    {
    case 'i':   if (cmd2 != 's')
                {   cout << "Expeting -s in third argument" << endl;
                    Syntax ();  //  Does not return
                }
                insert_hexstring (startcol, arg4);
                break;
                
    case 'r':   if (cmd2 != 's')
                {   cout << "Expeting -s in third argument" << endl;
                    Syntax ();  //  Does not return
                }
                replace_hexstring (startcol, arg4);
                break;
                
    case 'd':   if (cmd2 != 'l')
                {   cout << "Expecting -l as third argument" << endl;
                    Syntax ();
                }
                length = atoi (arg4.c_str());
                if (length == 0)
                {   cout << "Length argument must be non-zero" << endl;
                    Syntax ();  //  Does not return
                }                    
                delete_hexstring (startcol, length);                
                break;
                
    default:    cout << "switch must be -i -d or -r" << endl;    
                Syntax ();      //  Does not return            
    }                
}
              
int main(int argc, const char * argv[])
{   if (argc == 1)
	{   //  No arguments found. 	    
	    Syntax ();      //  Does not return
	}
	argc--; argv++;     //  Ignore program argument
	while (argc)
	{   if (argc % 4)       
	    {   cout << "Number of arguments must be a multiple of 4" << endl;
	        Syntax ();      //  Does not return
        }
        //  Process exactly 4 arguments
        process_arguments (argv[0], argv[1], argv[2], argv[3]);	    
        argc -= 4;  argv += 4;  //  Advance to next argument group
    }
    return 0;
}
Last edited on
It works as it should now.

argv[0] file name
argv[1] -d destionation
argv[2] file path
argv[3] -k column
argv[4] column to start replacing or erasing from
argv[5] -e if you want to erase or -r if you want to replace
argv[6] bytes to replace or number of bytes to erase

Sorry for comments in polish, but it would take to long to change them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip> 
#include <string>
#include <stdlib.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
using namespace std;

int dec(int bin);
string hex2bin(string sciezka);
string hex_zamiana(string hexString, int kol_zamiany, string wartosc_zamiany);
string sciezka;
string hex_erase(string hexString, int kol_zamiany, int do_usuniecia);

int main(int argc, const char * argv[])
{
	int kol_zamiany, do_usuniecia;
	string hexpierwsza;
	string hexdruga;

	if (argc == 3)
	{
		if (strcmp(argv[1], "-d") != 0) //pierwszy argument -d potrzebne strcmp porownuje stringi
		{
			cout << "-d oczekiwane" << endl;
			return 1;
		}

		string sciezka(argv[2]); //zamiana z char na string
		hexpierwsza = hex2bin(argv[2]); //otwarcie funkcji zamiany
		cout << endl << "Twoje wczytane dane to: " << hexpierwsza << endl;
	}
	else if (argc == 7)
	{
		if (strcmp(argv[5], "-r") == 0)
		{
			//argv[0] to jest zawsze nazwa programu
			if (strcmp(argv[1], "-d") != 0) //pierwszy argument -d potrzebne strcmp porownuje stringi
			{
				cout << "-d oczekiwane" << endl;
				return 1;
			}

			string sciezka(argv[2]); //zamiana z char na string
			hexpierwsza = hex2bin(argv[2]); //otwarcie funkcji zamiany
			cout << endl << "Twoje wczytane dane to: " << hexpierwsza << endl;
			if (strcmp(argv[3], "-k") != 0) //-r pobranie kolumny od ktorej bedzie zamiana wartosci
			{
				cout << "-k oczekiwane" << endl;
				return 1;
			}

			kol_zamiany = atoi(argv[4]); //numer kolumny zamiana na int

			if (strcmp(argv[5], "-r") != 0) //-s potrzebne potem wpisanie nowej wartosci do zamiany za oryginalene wartosci
			{
				cout << "-r oczekiwane" << endl;
				return 1;
			}

			string wartosc_zamiany(argv[6]); //zamiana wartosci zamiany z char na string

			cout << endl << "Twoje zamienione dane to: " << hex_zamiana(hexpierwsza, kol_zamiany, wartosc_zamiany) << endl;

			system("pause");
			return 0;
		}
		else if (strcmp(argv[5], "-e") == 0)
		{
			//argv[0] to jest zawsze nazwa programu
			if (strcmp(argv[1], "-d") != 0) //pierwszy argument -d potrzebne strcmp porownuje stringi
			{
				cout << "-d oczekiwane" << endl;
				return 1;
			}

			string sciezka(argv[2]); //zamiana z char na string
			hexpierwsza = hex2bin(argv[2]); //otwarcie funkcji zamiany
			cout << endl << "Twoje wczytane dane to: " << hexpierwsza << endl;
			if (strcmp(argv[3], "-k") != 0) //-r pobranie kolumny od ktorej bedzie zamiana wartosci
			{
				cout << "-k oczekiwane" << endl;
				return 1;
			}

			kol_zamiany = atoi(argv[4]); //numer kolumny zamiana na int

			if (strcmp(argv[5], "-e") != 0) //-s potrzebne potem wpisanie nowej wartosci do zamiany za oryginalene wartosci
			{
				cout << "-e oczekiwane" << endl;
				return 1;
			}

			do_usuniecia = atoi(argv[6]);

			cout << endl << "Twoje zamienione dane to: " << hex_erase(hexpierwsza, kol_zamiany, do_usuniecia) << endl;

			system("pause");
			return 0;
		}
	}
	else
	{
		cout << "Inna liczba argumentow oczekiwana" << endl;
		system("pause");
		return 0;
	}
}

string hex2bin(string sciezka)
{

	int bin;
	ifstream plik;
	plik.open(sciezka); //otwarcie pliku, sciezka jest podana w cmd jako argument
	plik >> bin; //zapisanie do zmiennej

	char hexString[33];
	_itoa_s(dec(bin), hexString, 16); //zamiana z bin na 10 na hex


	return hexString;


}

string hex_zamiana(string hexString, int kol_zamiany, string wartosc_zamiany)
{

	string hexarray = hexString.replace(kol_zamiany, wartosc_zamiany.length(), wartosc_zamiany);

	return hexarray;
}

string hex_erase(string hexString, int kol_zamiany, int do_usuniecia)
{
	string hexerase = hexString.erase(kol_zamiany, do_usuniecia);
	return hexerase;
}

int dec(int bin)//zamiana z bin na dec matematycznie
{
	int zmienna = 1;
	int suma = 0;

	while (bin != 0)
	{
		suma += (bin % 10) * zmienna;
		bin /= 10;
		zmienna *= 2;
	}

	return suma;
}
Topic archived. No new replies allowed.