Solved

C script to ident another c file

Posted on 2013-01-24
16
450 Views
Last Modified: 2013-01-28
Hi

I need to build a C script that add indents (1 tab) or remove (indents) to another C script file, without using beautifier or any software.

For example

I want it to run from the console like this : myidentificator.c <fileToIdent.c >formatedFile.c

I want the script to avoid any comments and find { and }. When it finds a { it adds one indent to the next lines until he finds a }. Then he remove indents until it finds { and etc etc. The { and } are always alone in their lines.

I have checked on the internet, but I dont even know where to start. I heard C have problems with big buffers and I want my program to not be limited by line size or line numbers.

What sould I do ? Put all the lines into strings ? then arrays ?

Ex

Source

void hello1
{
ads;
}

   void hello 2
{
adssads;
}

Open in new window


Modified will look like
void hello1
{
      ads;
}

void hello 2
{
     adssads;
}

Open in new window

0
Comment
Question by:metraon
  • 7
  • 4
  • 3
  • +2
16 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 38816525
Instead of reinventing the wheel, you might be interested in http://uncrustify.sourceforge.net/ ("Uncrustify - Source Code Beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and VALA") or http://www.faqs.org/docs/Linux-HOWTO/C-C++Beautifier-HOWTO.html#installing_bcpp
0
 

Author Comment

by:metraon
ID: 38816566
I need to do it myself, in C language

What I think I am gonna do is convert each line into a array series characters example

[h][e][l][l][o][/n]

Analyse the array and append it into the file.

Then Go to line 2 etc etc
0
 
LVL 32

Expert Comment

by:phoffric
ID: 38816807
fgets will read a line putting each char in the line in a char:
    http://www.cplusplus.com/reference/cstdio/fgets/
/* fgets example */
#include <stdio.h>

int main()
{
   FILE * pFile;
   char mystring [100];

   pFile = fopen ("myfile.txt" , "r");
   if (pFile == NULL) perror ("Error opening file");
   else {
     if ( fgets (mystring , 100 , pFile) != NULL )
       puts (mystring);
     fclose (pFile);
   }
   return 0;
}

Open in new window

mystring  is an array of char.
You also have to handle {{.
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 38820028
Just how much are you wanting to modify the text vs. leave as much of it alone as possible?

If you want to somewhat standardize the look of the code, I would try a program that does something like the following pseudo-code

Set IndentLevel = 0;
LOOP1:
Read a Line of Text into MyString
LOOP2:
Search for the 1st '{' or '}' character in MyString
Extract a sub-string from MyString of all characters before the 1st '{' or '}'
Perform a Left & Right Trim on the subs-string
Write 4*IndentLevel number of spaces to the file
Write the sub-string and a newline character
If 1st found character was '{' then...
    Write 4*IndentLevel number of spaces to the file
    Write '{' and a newline  character
    Increment IndentLevel
Else if 1st found charater was '}' then...
    Decrement IndentLevel
    Write 4*IndentLevel number of spaces to the file
    Write '}' and a newline  character
Replace MyString with all the text that followed the 1st '{' or '}'
If MyString is not empty
    Return to 'Loop2'
If NOT at End of File
    Return to 'Loop1'
0
 
LVL 37

Expert Comment

by:TommySzalapski
ID: 38820891
You don't have to worry about buffer space. Just read in one line at a time, process it, and read the next line. You'll only need to store one line at a time in any buffer.

The things you'll need to keep track of are the current indent size and whether or not your are inside a comment when you see the { or } characters.

without using beautifier or any software
Can we then assume this is a homework assignment?
0
 

Author Comment

by:metraon
ID: 38822459
So far, I got this. Is there a reason it print  Detected on every line ? I wanted to be clever and add \0 so it would only print the message on { at the end of a line.

Yes its an assignment !


#include <stdio.h>

void main()
{
    char str[200];
    FILE *fp;

    fp = fopen("test.c", "r");
    if(!fp) return 1; // bail out if file not found
    while(fgets(str,sizeof(str),fp) != NULL)
    {
        int len = strlen(str)-1;
        if(str[len] == '\n')
        {
            str[len] = 0;
        }
        char *ptr=strchr(str,'{\0');
        if(ptr)
        {
            sprintf(str,"%s { Detected",str);

        }
        else
        {
            ptr=strchr(str,'}\n');
            if(ptr)
            {
                sprintf(str,"%s } Detected ",str);
            }
        }
        printf("\n%s", str);

    }

    fclose(fp);
}

Open in new window

0
 
LVL 32

Expert Comment

by:phoffric
ID: 38822583
>> Is there a reason it print  Detected on every line ?

The code you posted should not compile without problems. If you are getting warnings, fix them first before posting.

But the gist of the problem is that you are searching for '\0' which you always find. Since your ptr is pointing to the '\0', then ptr is not NULL, and you get Detected.

By the way, the EE policy is one question per thread.
0
 
LVL 37

Assisted Solution

by:TommySzalapski
TommySzalapski earned 250 total points
ID: 38822767
'{\0' doesn't make sense (and should generate the warning phoffric is talking about). When you pass characters, you don't need to null-terminate them. Only strings get the null terminators.  '{' and '}' will do what you want.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:metraon
ID: 38822825
In the orginal post, I mentioned that I want the script to avoid any comments, I think its still related to the same question.

I putted the {\0, because I thought It will only finds the lone { and ignore the ones commented. If i put only char *ptr=strchr(str,'{'); The { in comments will not be ignored, and will output a non desired behavior.

I added this : sprintf(str,"%s } Detected ",str); just to get more visibility and for debugging purposes.
0
 
LVL 32

Expert Comment

by:phoffric
ID: 38822858
Since you want to ignore {} in comments, then you can define a flag, in_a_comment, to let you know when you must ignore curlys.
0
 
LVL 32

Expert Comment

by:phoffric
ID: 38822873
strchr 2nd arg takes an int.
    http://www.cplusplus.com/reference/cstring/strchr/

'{\0' is not a legitimate way to form an int, as Tommy already explained.
0
 
LVL 32

Expert Comment

by:phoffric
ID: 38822908
I take back what I said earlier that you are searching for null. Maybe you are searching for '{'. I do not always know what compilers will generate when the code has warnings like yours.

If you are in_a_comment, then just indent according to your indent_level state variable, and in that line, continue your search for end of comment. From that point in the line, you still must search for new comments as well as curlys.

After reading in a line, just examine one char at a time keeping track of the states, in_a_comment, as well as your indent_level state.
0
 
LVL 37

Expert Comment

by:TommySzalapski
ID: 38822970
You are going to have to parse the line looking for the characters that mean comment. I don't think strchr is what you need since you need to look for // and /*
Just make the boolean phoffric suggests and set and unset it when you see // and \n or /* and */
0
 
LVL 32

Expert Comment

by:phoffric
ID: 38822978
That's right, strchr has its place. But here you should look at one char at a time to keep track of your states. For advanced credit, you will need to keep track of ignoring comment tokens like // when you are already within a comment. You should also compile the program first with no warnings to get rid of what may appear as nested comments. Also, you need a state variable to indicate when you are in a string or a char literal, so that you can ignore curlys within those entities.
0
 
LVL 32

Accepted Solution

by:
phoffric earned 250 total points
ID: 38822989
If you want, you can deal with one char at a time using fgetc instead of fgets.
    http://www.cplusplus.com/reference/cstdio/fgetc/

If using fgetc, you will need another state variable. (Give it a try and you will see what I mean.) I think you should write out pseudo-code since this has become a design question. Then later if you have problems with C programming, you can address them one question at a time.
0
 

Author Comment

by:metraon
ID: 38827127
Thanks. I am going to work on this by myself for the rest. There is no better way to learn with experiments.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Okay. So what exactly is the problem here? How often have we come across situations where we need to know if two strings are 'similar' but not necessarily the same? I have, plenty of times. Until recently, I thought any functionality like that wo…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now