1

I am trying to read in a file and then check to see if it contains a new line,tab or space.

I am currently reading in the file with fgets() and then checking line by line to see if the file contains a new line,space or tab.

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

int main(){
  FILE* fp;
  char line[255];
  int nonBlankLines = 0;
  int totalLines = 0;


  fp = fopen("Test.java","r");

  while(fgets(line,sizeof(line),fp)){
    if(line != '\n' || line != '\t' || line != '\n'){
      nonBlankLines++;
    }
    totalLines++;
    printf("%s\n",line);
  }
  fclose(fp);
  
  printf("The total lines are %d \n", totalLines);
  printf("The total non blank lines are %d \n", nonBlankLines);
}

When I compile and run the program, both the total lines and blank lines are the same number.

Here is the java file I am trying to examine:

/**
 * This is the first line in the comment.
 * This is another line in the comment.
 * The comment ends on the line below.
 */
class Hello{
  public static void main(String[] args){
    System.out.println("Hello");
  }
}


there are 2 empty lines near the bottom of the java file my program is not picking up on.

How do I get my program to read these characters?

bobdylan01
  • 158
  • 2
  • 10
  • Maybe you can check with line[0]!='\n'. If the first character is '\n' so there is an empty line. Because you are trying to check whole line. – Ogün Birinci Feb 19 '21 at 17:43
  • `line != '\n'` - line is an array, you cannot just compare it to your characters. Also, you compare for `'\n'` twice in your conditional. I assume one of those should be `' '`. – Christian Gibbons Feb 19 '21 at 17:43
  • Your compiler should show some warnings about severe errors in your program. `line` is an array and cannot be compared with a integer constant. You should turn up your warning level. For GCC you can use `-Wall -Wextra` . If there already are warnings, read them carefully! – Gerhardh Feb 19 '21 at 17:43
  • 1
    Does this answer your question? [How do I properly compare strings in C?](https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings-in-c) – Govind Parmar Feb 19 '21 at 17:43
  • 1
    @GovindParmar that is not a dupe. Question is about finding certain characters inside a string. – Gerhardh Feb 19 '21 at 17:44
  • @Gerhardh but the conceptual error is the same – Govind Parmar Feb 19 '21 at 17:44
  • @GovindParmar maybe, nevertheless the provided answers are useless. – Gerhardh Feb 19 '21 at 17:45
  • Recommend using `strpbrk()` – Christian Gibbons Feb 19 '21 at 17:45
  • 3
    Also, it should be worth noting that every line should have a new line character except for the last line. That's how lines work. – Christian Gibbons Feb 19 '21 at 17:47
  • 1
    You might find the library function `isspace()` useful... – Eugene Sh. Feb 19 '21 at 17:48
  • @ChristianGibbons `fgets` stops at the line size when it hasn't seen a newline. – stark Feb 19 '21 at 17:49
  • 1
    @stark That is true, but having too small of a buffer is its own problem if the intention is to read the entire line. – Christian Gibbons Feb 19 '21 at 17:50
  • *I am currently reading in the file with fgets() and then checking line by line to see if the file contains a new line,space or tab.* is confusing, all the lines have a newline character. Do you meant to say that you are looking for empty lines? – anastaciu Feb 19 '21 at 17:56
  • 1
    @ChristianGibbons, that should be: "every line should have a newline character (period)". At least in the Unix world, that is. See: https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/V1_chap03.html#tag_03_206 and https://stackoverflow.com/q/729692/6372809 – ilkkachu Feb 19 '21 at 18:18
  • 1
    @ilkkachu I stand corrected. – Christian Gibbons Feb 19 '21 at 18:38

5 Answers5

1

You get a point for providing a full program that actually compiles. And a deduction of about the same value for not enabling compiler warnings / not reading them.

Gcc warns of that even without extra flags:

$ gcc -o char char.c
char.c: In function ‘main’:
char.c:14:13: warning: comparison between pointer and integer
     if(line != '\n' || line != '\t' || line != '\n'){
             ^~
[same for the other two]

Your line is char[255], for almost all practical purposes the same as char *, i.e. a pointer to char (or a bunch of them). The character literals '\n', however, are of type char. Comparing them doesn't make sense.

If you want the first character of the string, use line[0]; or if you want to compare the full line, use strcmp(line, "\n") == 0. Though note that you probably want to scan the whole line to see if there's any non-whitespace characters -- the input could be e.g. " \n", two spaces and a newline.

Also, consider your condition more closely. You have "X is not A OR X is not B". What happens in each of the subconditions for each of these cases: X is A, X is B, X is C?

Also note that the string returned by fgets() always contains a newline, if one was present in the input within the given size.

ilkkachu
  • 6,221
  • 16
  • 30
1

strcspn searches of the first occurence of a character in a list of characters and returns the index. If not found it points to the end of the input string.

size_t index = strcspn(line, " \n\t");
if (index == strlen(line))
    printf("line contains no whitespaces\n");
else
    printf("first whitespace found at %u\n", index);
Devolus
  • 21,661
  • 13
  • 66
  • 113
0

You need to iterate over your string character by character and check if said character is whitespace. Here is a function that accepts a string and returns 1 if it only contains whitespace and 0 if it doesn't.

int isStringEmpty(const char *str) {
    while (*str) {
        if (*str != ' ' && *str != '\t' && *str != '\n'){
            return 0;
        }
        str++;
    }
    return 1;
}

You can also modify the implementation to use C's isspace function which will additionally check for vertical tabs, form feeds, and carriage returns.

Given your code excerpt, you would use the function like so:

if (!isStringEmpty(line)){
    nonBlankLines++;
}
hgs3
  • 525
  • 3
  • 6
0

You should check for carriage return line feed, '\n' might not be enough as on certain OS (like Windows), new line characters are specified with the string "\r\n". That might be the problem you have.

antaalt
  • 11
  • 1
  • 3
  • There is some point to this in that getting CRLF newlines would make every line look non-empty, if they only consider space tab and newline. But that's hardly the only problem the code in question has. Also, the way of writing "this might be the problem" makes it sound like you're not at all sure of what you're saying, but are instead just trying blindly to see if the problem goes away. It would be more useful to go further into the _why_ that could fix the problem at hand. – ilkkachu Feb 19 '21 at 18:15
0

You are trying to calculate total number of blank lines and non-blank lines. To know if line is blank, we are only concerned with 3 cases:

  1. If newline '\n' repeats consecutively 2 or more times.
  2. If 2 '\n' characters have only whitespaces between them. Here, we will assume that 2 '\n' characters are consecutive for implementation purpose.
  3. If 2 '\n' have non-whitespace characters too between them.

In case 1, there can be 1 or more consecutive blank lines. In case 2, there will be 1 blank line. In case 3, there won't be any blank line but a non-blank line. If you see properly, we are only concerned with character comparison which can be achieved by using fgetc(). We will use a flag appropriately to indicate if two '\n' characters are consecutive or not.

#include<stdio.h>
#include<stdlib.h>
int main(){
    int c;
    FILE *f =fopen("Test.java","r");
    int flag=0,blank=0,newline=0;
    while((c=fgetc(f))!=EOF){
        if(flag ==1 && c=='\n'){ //is newline consecutive?
            blank++;
        }else if(c==' '){
            continue; //wait for non-whitespace character
        }
        if(c=='\n'){
            flag=1;
            newline++;
        }else{
            flag=0; 
        }
    }
    printf("blank lines, non-blank lines =%d, %d",blank, newline-blank);
    fclose(f);
    return 0;
}
Akash Dahane
  • 254
  • 2
  • 14