-3

I want to read a c file from another c program. and print it line by line. But I got some problem. here is my code, the file to be read and the output i'm getting in terminal.

my Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char sourcefilename[100];
    char targetfilename[100];
    int counter = 0;
    int lower_limit = 10;
    char *line = NULL;
    char *temp = NULL;
    int is_multilinecomment = 0;

    FILE *source = fopen("hello.c", "r");
    FILE *target = fopen("newcode.c", "w");

    char ch = fgetc(source);
    while (ch != EOF)
    {
        // printf("%c", ch);
        if (ch == '\n')
        {
            counter = 0;
            printf("%s\n", line);
            free(line);
            line = NULL;
        }
        else
        {
            temp = (char *)realloc(line, counter * sizeof(char));
            if (!temp)
            {
                free(line);
                line = NULL;
            }
            line = temp;
            line[counter] = ch;
            counter++;
            // printf("%s", line);
        }
        // printf("helo");
        ch = fgetc(source);
    }
    return 0;
}

hello.c

I'm trying to read this file

#include <stdio.h>
#include <string.h>
// this is a single line comment
int main()
{
    char var[500];
    printf("Enter a name of a variable : ");
    scanf("%s", var);

    if (!((var[0] >= 'a' && var[0] <= 'z') || (var[0] >= 'A' && var[0] <= 'Z') || var[0] == '_'))
    {
        printf("%s is not valid variable.\n", var);
        return 0;
    }
    // this is another single line comment
    for (int i = 1; i < strlen(var); i++)
    {
        if (!((var[i] >= 'a' && var[i] <= 'z') || (var[i] >= 'A' && var[i] <= 'Z') || var[i] == '_' || (var[i] >= '0' && var[i] <= '9')))
        {

            printf("%s is not valid variable.\n", var);
            return 0;
        }
    }
    /*
    this is a multi line
    comment */

    printf("%s is valid variable.\n", var);

    return 0;
}

output i'm getting

#include <stdio.h>\Progr�
#include <string.h>
// this is a single line comment`�
int main()�
{�
    char var[500];e line/
    printf("Enter a name of a variable : ");{~
    scanf("%s", var);ame/
    if (!((var[0] >= 'a' && var[0] <= 'z') || (var[0] >= 'A' && var[0] <= 'Z') || var[0] == '_'))�
    {
        printf("%s is not valid variable.\n", var);
        return 0;s is nok�_z~
    }
    // this is another single line comment
    for (int i = 1; i < strlen(var); i++)
    {
        if (!((var[i] >= 'a' && var[i] <= 'z') || (var[i] >= 'A' && var[i] <= 'Z') || var[i] == '_' || (var[i] >= '0' && var[i] <= '9')))
 _�

you can notice here i'm getting some unwanted characters at the end of each line. and also last part of the hello.c is ignored.

please help !!!

  • 2
    Your title is misleading. C files are the same as .txt files. The file extension does not tell anything. – Gerhardh Feb 25 '22 at 14:25
  • `int fgetc(FILE *stream);` catch return value in an integer; coz often EOF is not an 8-bit character. – जलजनक Feb 25 '22 at 14:27
  • 1
    You might take a look at [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Gerhardh Feb 25 '22 at 14:27
  • `(var[0] >= 'a' && var[0] <= 'z')`? Use [`islower()`](https://port70.net/~nsz/c/c11/n1570.html#7.4.1.7) instead. And `isupper()` for upper-case checks. – Andrew Henle Feb 25 '22 at 14:44

1 Answers1

1

You have multiple issues in your code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char sourcefilename[100];
    char targetfilename[100];
    int counter = 0;
    int lower_limit = 10;
    char *line = NULL;
    char *temp = NULL;
    int is_multilinecomment = 0;

    FILE *source = fopen("hello.c", "r");
    FILE *target = fopen("newcode.c", "w");

    char ch = fgetc(source);

Function fgetc returns an int. This is required to detect EOF. Do not use char.

    while (ch != EOF)

See Why is “while ( !feof (file) )” always wrong? for details

    {
        // printf("%c", ch);
        if (ch == '\n')
        {
            counter = 0;
            printf("%s\n", line);

If you hit an empty line, you do not have any memory allocated for line and it contains NULL, causing undefined behaviour.

In any case you do not have a terminating 0 byte in your line buffer. This means it is not a valid string and passing that character array to printf again causes undefined behaviour.

            free(line);
            line = NULL;
        }
        else
        {
            temp = (char *)realloc(line, counter * sizeof(char));

You start with counter=0 for each line. You allocate 0 bytes for first character. Instead of allocating memory for your string + 1 byte for terminating \0 byte, you allocate 2 bytes less.

            if (!temp)
            {
                free(line);
                line = NULL;
            }
            line = temp;
            line[counter] = ch;

If condition (!temp) was true above, you still assign temp to line and dereference it, causing undefined behaviour.

            counter++;
            // printf("%s", line);
        }
        // printf("helo");
        ch = fgetc(source);
    }
    return 0;
}

Some more issues, not related with weird characters:

  • You do not write your output to target file.
  • You do not close your files.
  • A proper signature for main should be int main (void). Empty parameter list in function definition should not be used nowadays.
  • Most of your variables in main are unused.
  • Not all included headers are actually required.
Gerhardh
  • 11,688
  • 4
  • 17
  • 39