Program to indent code

So this was my project for the last couple of hours, it's an indenting program that "properly" indents code for you. I made it because it will definitely help me.
I've got it running very nicely except it outputs a single line at the bottom of the output file with a bunch of tabs to it. I was wondering if someone could debug that for me. It's safe, and I even ran it on itself and the output worked flawlessly besides the extra line at the end.

Note - this code doesn't directly change your code, it outputs the newly indented code to a file named "temp.txt" which you can then copy and paste from.

Here's the code;
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
void indent(string fileName)	
{
	
	int pos = 0, count =0, lengthp = 0,j=0;
	
	string ch;
	ifstream file(fileName);
	while(file.good())
	{
		pos++;
		getline(file,ch);
	}
	lengthp=file.tellg();
	string* hold (nullptr);
	hold = new string[pos + 1];
	int* bracketcount(nullptr);
	bracketcount = new int[pos+1];
	file.clear();
	file.seekg(0);
	while(file.good())
	{
		
		getline(file,hold[count]);
		count++;
	}
	int endline = count;
	int p=0;
	while(p<=endline)
	{
		bracketcount[p]=0;
		p++;
	}
	count = 0;
	int len=0,i = 0, current=0;
	while(count<endline)
	{
		len = hold[count].length();
		i=0;
		while(i<=len)
		{
			if(hold[count][i] == '{')
				{
					
					current=count;
					while(current <endline)
					{
						current++;
						bracketcount[current]++;
						
					}
				}
			if(hold[count][i] == '}')
			{
				current=count;
				while(current <endline)
				{
					bracketcount[current]--;
					current++;
				}
			}
			i++;
		}
		count++;
	}
	file.close();
	ofstream file2("temp.txt");
	
	string* indents(nullptr);
	indents = new string[pos+1];
	
	 p=0;
	while(p<=endline)
	{
		count=0;
		while(hold[p][count]=='\t')
		{
			count++;
		}
		while(bracketcount[p]>0)
		{
			bracketcount[p]--;
			indents[p] +="\t";
		}
		if(count==0)
		{
			file2<<indents[p]<<hold[p]<<endl;
		}
		else if(count>0)
		{
			file2<<indents[p];
			len = hold[p].length();
			i=0;
			while(i<len-count)
			{
				file2<<hold[p][i+count];
				i++;
			}
			file2<<endl;
		}
		p++;
	}
	file2.close();
	delete [] hold;
	delete [] bracketcount;
	delete [] indents;
}
								

Last edited on
I haven't tested your code but I think the problem is the way you read all lines in the file. Take line 20-25 for instance. file.good() will stay true until getline has failed to read a line so when getline fails it will still increment count, so count will be one more than the number of rows in the file. A better way to write the loop is to use the return value getline as the loop condition directly.

1
2
3
4
while (getline(file,hold[count]))
{
	count++;
}
oh cool good idea for project
Thanks Peter87, actually that wasn't the problem but it put me on the right track. I did implement what you said because it saves a bit of space though.
You were right that the program was getting instructions to go one line further than it should;
The problem was at line 72, It should be just a "greater than" sign instead of a "greater and equal" sign.
It's working perfectly now, Thanks.
Last edited on
OK, I made another modification to my own version at home, for line 66 I set the file2 object to open the fileName variable. I think this code is pretty safe, and this way the program can automatically make the changes to whatever file I have it working on without having to copy and paste anything.

It's also kind of neat because if I run it on a file that I currently have open I can watch the changes as they happen.
Last edited on
Hi there,

I just wanted to comment on something you said:

newbieg wrote:
I think this code is pretty safe


There is one thing you should be aware of. When you allocate memory dynamically (using new, there is a chance that it will fail, for instance due to lack of memory. The standard version of new will throw an exception (std::bad_alloc). When an exception is thrown, all variables in the current scope are destructed, the problem is that pointer variables are destructed, but the memory they point to is not deallocated, so you have no more ways to access (and deallocate) that memory.

In your code:

1
2
3
4
5
6
7
8
9
10
11
string* hold (nullptr);
hold = new string[pos + 1];
int* bracketcount(nullptr);
bracketcount = new int[pos+1];

//...

string* indents(nullptr); 
indents = new string[pos+1];  
//suppose this previous line fails, the end of the function is never reached (i.e. delete[])
//so now bracketcount and hold are destroyed, but their memory is not deallocated -> leak. 



To counteract this, there are a few possibilities:

- Don't use regular arrays, but use STL containers such as std::array, std::vector, etc. They don't require dynamic allocation and save you a lot of bother.
- Wrap all calls to new in a try/catch block and delete[] the pointers there. More about that here: http://cplusplus.com/doc/tutorial/exceptions/
- If you need to use pointers, use smart pointers such as std::unique_ptr and std::shared_ptr, which will automatically deallocate the associated memory when they are destructed.

Just wanted to point that out to you, as it's a rather important consideration in application security.

All the best,
NwN
Ack! You're right, I forgot that my book mentioned that dynamic vars could crash like that. I haven't gotten into using vectors yet, but my book should have them coming up in a couple of chapters.
I guess I'll change my home version back to sending the indented version to "tempt.txt" again until I find out how to work with vectors.
Thanks NWN, that completely blew my mind.

Oh, you know what, I just got to the chapter that starts covering the STL Library yesterday, guess I'll get back to reading then.
Hey man I came here hoping I could be of help, but It looks like you have your answers already (good news)...

However it looks like you might be able to help me!
When you're 100% sure this works safely could you send me the source please? It'd make my life coding a lot easier too, and what a GREAT idea by the way... Good Job!!
(If the topic get's archived you can pm me)
Oh, sorry, I should have posted the final code earlier.

Changes made;
- Included comments to show where things are happening.
- Switched over from dynamic memory to vectors.
- Set it to return the total number of lines in the file, I just figure that would be a nice feature.

Here's the code, Since I'm new to vectors I still don't know if they're 100% safe, so this version still sends the modified code to temp.txt, just change the code at line 58 if you trust it, I haven't had any problem with it yet.
Since it uses vectors you'll need to include the <vector> and <string> headers in the program.

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
int indent(string fileName)//Autoindent a file
{
	int pos = 0, count =0, j=0;
	string ch;
	ifstream file(fileName);
	while(file.good())
	{
		pos++;//return value at end of code, number of lines
		getline(file,ch);
	}
	
	vector<string> hold(pos+1);//holds the actual content of the line.
	vector<int> bracketcount(pos+1);//keeps track of number of nested brackets
	file.clear();
	file.seekg(0);
	while(getline(file,hold[count]))
	{
		count++;
	}
	int endline = count;
	int p=0;
	while(p<=endline)
	{
		bracketcount[p]=0;
		p++;
	}
	count = 0;
	int len=0,i = 0, current=0;
	while(count<endline)
	{
		len = hold[count].length();
		i=0;
		while(i<=len)
		{
			if(hold[count][i] == '{')
				{
					current=count;
					while(current <endline)
					{
						current++;
						bracketcount[current]++;
					}
				}
			if(hold[count][i] == '}')
			{
				current=count;
				while(current <endline)
				{
					bracketcount[current]--;
					current++;
				}
			}
			i++;
		}
		count++;
	}
	file.close();
	ofstream file2("temp.txt");// consider this a safety net, change to fileName if you trust the code.
                                                  // I'm probably just being overly cautious.
	vector<string> indents(pos+1);
	 p=0;
	while(p<endline)
	{
		count=0;
		while(hold[p][count]=='\t')//check if there were already tabs in the file
		{
			count++;
		}
		while(bracketcount[p]>0)//tells indents[p] how many indents should be in a line
		{
			bracketcount[p]--;
			indents[p] +="\t";
		}
		if(count==0)//if the line wasn't previously indented in the code
		{
			file2<<indents[p]<<hold[p]<<endl;
		}
		else if(count>0)//If there were already indents in the code then set them to the right amount
		{
			file2<<indents[p];
			len = hold[p].length();
			i=0;
			while(i<len-count)
			{
				file2<<hold[p][i+count];
				i++;
			}
			file2<<endl;
		}
		p++;
	}
	file2.close();
	return pos;
}


Heh, I just think it's funny that my codes shorter than when I first posted.
Last edited on
Hmm... Just noticed your code uses '/t' to indent instead of spaces...
Why're you using tabs instead of the standard 4 spaces? (space char value = 32)
And you're also using tabs in your program script, I didn't think you could contain tabs in your script (maybe I'm thinking of xml documents?) but when I type a tab my compiler changes it to standard 4 spaces.
@SatsumaBenji
You can use tabs just fine. It is your IDE/text editor that is set to convert tabs to spaces automatically. You can probably turn off this behaviour if you want. Personally I prefer tabs. Using tabs allows people to use whatever tab width they want, without making changes to the code.
Last edited on
This version indents the code with spaces instead of tabs, but will still recognize if you used tabs and will change it to 4 spaces.

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
#include <string>
#include <vector>
int indent(string fileName)//Autoindent a file
{
    
    int pos = 0, count =0, lengthp = 0,j=0;
    string ch;
    ifstream file(fileName);
    while(file.good())
    {
        pos++;
        getline(file,ch);
    }
    int linecount = pos;//value to return at end of code, total lines in a code.
    vector<string> hold(pos+1);
    vector<int> bracketcount(pos+1);//keeps track of number of nested brackets
    file.clear();
    file.seekg(0);
    while(getline(file,hold[count]))
    {
        count++;
    }
    int endline = count;
    int p=0;
    while(p<=endline)//initialize all bracketcounts to 0
    {
        bracketcount[p]=0;
        p++;
    }
    count = 0;
    int len=0,i = 0, current=0;
    while(count<endline)
    {
        len = hold[count].length();
        i=0;
        while(i<=len)
        {
            if(hold[count][i] == '{')
                {
                    current=count;
                    while(current <endline)
                    {
                        current++;
                        bracketcount[current]++;
                    }
                }
            if(hold[count][i] == '}')
            {
                current=count;
                while(current <endline)
                {
                    bracketcount[current]--;
                    current++;
                }
            }
            i++;
        }
        count++;
    }
    file.close();
    ofstream file2("temp.txt");// consider this a safety net, change to fileName if you trust the code.
    vector<string> indents(pos+1);
    int tabcount=0, h=0;
    p=0;
    while(p<pos)
    {
        count=0;
        tabcount=0;
        while(hold[p][h] ==' ')//check if there were already 4 spaces in the file
        {
            h=count;
            if(hold[p][h] ==' ')
            {
                count++;
                h++;
            }
            else if(hold[p][h] =='\t')
            {
                h++;
            }
            else
            {
                break;
            }
        }
        h=0;
        while(hold[p][h]=='\t')//check if there were already tabs in the file
        {
            if(hold[p][h]=='\t')
            {
                tabcount++;
                h++;
            }
            else if(hold[p][h]==' ')
            {
                h++;
            }
            else
            {
                break;
            }
        }
        indents[p]="";
        while(bracketcount[p]>0)//tells indents[p] how many indents should be in a line
        {
            bracketcount[p]--;
            indents[p] +="    ";
        }
        
        if(count==0&&tabcount==0)//if there were no tabs in the file then continue
        {
            file2<<indents[p]<<hold[p];
            if(p<pos-1)
            {
                file2<<endl;
            }
        }
        else if(count>0||tabcount>0)
        {
            file2<<indents[p];
            len = hold[p].length();
            i=0;
            while(i<len-tabcount-(count))//if there were tabs in the file then remove them
            {
                file2<<hold[p][i+(count)+tabcount];
                i++;
            }
            if(p<pos-1)
            {
                file2<<endl;
            }
        }
        p++;
    }
    file2.close();
    cin>>p;
    return pos;
}

Last edited on
Topic archived. No new replies allowed.