C programming- read from text file - c

it's about reading from a text file.
I have 3 command line arguments:
name of text file
delay time
how many line(s) want to read.
I want to read that text file by user specified line numbers till text file ends.
For example, the first time I read 5 lines and then the program asks how many line(s) do you want to read?. I would enter 7 it reads lines 5 to 12.
This would repeat until the end of the file.
#include <stdlib.h>
#include <stdio.h>
#include<time.h>
#include <string.h>
void delay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
int countlines(const char *filename) {
FILE *fp = fopen(filename, "r");
int ch, last = '\n';
int lines = 0;
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
last = ch;
}
fclose(fp);
if (last != '\n')
lines++;
}
return lines;
}
int main(int argc, char *arg[])
{
FILE *ptDosya;
char ch;
ch = arg[1][0];
int s2;
int satir = 0;
int spaceCounter=0;
int lineCount, x = 0;
lineCount = atoi(arg[3]);
s2 = atoi(arg[2]);
printf("dosya %d satir icerir.\n", countlines(arg[1]));
ptDosya = fopen(arg[1], "r");
if (ptDosya != NULL)
{
while (ch != EOF&& x < lineCount)
{
ch = getc(ptDosya);
printf("%c", ch);
if (ch == '\n')
{
delay(s2);
x++;
}
}
while (x < countlines(arg[1]))
{
printf("satir sayisi giriniz:");
scanf("%d", &lineCount);
// i don't know what should i do in this loop..
x=x+lineCount;
}
}
else {
printf("dosya bulunamadi");
}
printf("\n\nend of file!\n");
fclose(ptDosya);
return 0;
system("PAUSE");
}

Your delay function uses a busy loop. This is unnecessarily expensive in terms of computing power. It would be very unwelcome to do this on a battery operated device. Furthermore, clock() does not necessarily return a number of milliseconds. The unit used by the clock() function can be determined using the CLOCKS_PER_SEC macro. Unfortunately, there is no portable way to specify a delay expressed in milliseconds, POSIX conformant systems have usleep() and nanosleep().
Your line counting function is incorrect: you count 1 line too many, unless the file ends without a trailing linefeed.
Here is an improved version:
int countlines(const char *filename) {
FILE *fp = fopen(filename, "r");
int ch, last = '\n';
int lines = 0;
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
last = ch;
}
fclose(fp);
if (last != '\n')
lines++;
}
return lines;
}
There are issues in the main() function too:
You so not verify that enough arguments are passed on the command line.
You do not check for EOF in the main reading loop.
You do not repeat the process in a loop until end of file, nor do you even ask the question how many line(s) do you want to read? after reading the specified number of lines...

First, if the file cannot be found, the countlines method returns zero. You should use that value to write the error message, and skip the rest of the code.
Second, in the next loop, you use
if (ch != '\n') {
printf("%c", ch);
} else {
printf("\n");
delay(s2);
x++;
}
Why the two printf statements? They will print the same thing.
Perhaps something like this:
ch = getc(ptDosya);
/* exit the loop here if you hit EOF */
printf("%c", ch); /* Why not putc() or putchar() ? */
if (ch == '\n') {
x++;
if ( x == lineCount ) {
x = 0;
lineCount = requestNumberOfLinesToRead();
} else {
sleep(s2); /* instead of delay(). Remember to #include unistd.h */
}
}

Related

Function is not correctly incrementing variable by 1

I have a function that returns the number of lines, characters, and words in an array. For some reason, when i loop through the array to print the values I am only getting the corrrect value for lines, the characters and words are returning as 0. All the functions are predetermined by my professor and my job is to fill them in.
int main(int argc, char **argv)
{
int *myArray = get_counts(argv[1]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", myArray[i]);
}
return 0;
}
int *get_counts(char *filename)
{
FILE *file;
file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
}
char c;
int h;
bool whitespace = true;
static int arr[3] = {0,0,0};
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
while (true)
{
h = fgetc(file);
if (feof(file))
{
break;
}
else if (ferror(file))
{
printf("error reading file");
}
arr[2] ++;
if (whitespace && !isspace(h))
{
arr[1] ++;
whitespace = false;
}
else if (!whitespace &&isspace(h))
{
whitespace = true;
}
}
fclose(file);
return arr;
}
The best option is probably to just iterate through the file in one loop (you could also rewind() after the first loop). Use the return value of fgetc() to determine of you are at EOF instead of separate feof() calls. I also made the the result array an (out) argument instead of using a static variable (the latter is not reentrant if you ever want to call this from multiple threads and it's easy to do):
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
void get_counts(char *filename, int arr[3]) {
memset(arr, 0, 3 * sizeof(int));
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("NULL FILE");
return;
}
bool whitespace = true;
for(;;) {
int c = fgetc(file);
if(c == EOF)
break;
else if(c == '\n')
arr[0]++;
else if (whitespace && !isspace(c)) {
arr[1]++;
whitespace = false;
} else if (!whitespace && isspace(c))
whitespace = true;
arr[2]++;
}
fclose(file);
}
int main(int argc, char **argv) {
int myArray[3];
get_counts(argv[1], myArray);
for (int i = 0; i < 3; i++) {
printf("%d\n", myArray[i]);
}
}
The output on the above file is:
39
94
715
The word count 94 doesn't agree with wc -w but you could be using a different definition of what a word is.
It's a good idea to separate calculations and i/o, so consider opening and closing the file in main() and pass in the file handle. It becomes easy, for instance, to use the stdin file handle instead if you don't want to use a physical file.
After the first do-while loop the condition EOF occurs.
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
So the following while loop has no effect.
You should use only one loop to count lines, words and characters.
Pay attention to that the variable c should be declared as having the type int
int c;
Also you need to exit the function if the file was not opened.

running the program doesn't print the second printf statement

whenever I run the program the second print statement isn't printing. I tried using a function but I'm new to C and don't really understand anything. I've also attached my activity as I'm not sure how to do the other things on it.activity photo
#include <stdio.h>
#include <string.h>
#define LINE_LENGTH 1000
int main(int argc, char **argv)
{
FILE *input_file = fopen("cstest.c", "r");
char line [LINE_LENGTH];
//while loop to ger
while (fgets(line, LINE_LENGTH, input_file) != NULL)
{
int ch = 0;//ch is the cast
int lines = 0;//start with one because
if (input_file == NULL)
return 0;
while (!feof(input_file))
{
ch = fgetc(input_file);
if (ch == '\n')
{
lines++;
}
}//end while
printf("lines: %d\n", lines);
}//end while loop
while (fgets(line, LINE_LENGTH, input_file) != NULL)
{
int ch = 0;//ch is the cast
int lines = 0;//start with one because
if (input_file == NULL)
return 0;
while (!feof(input_file))
{
int characters = 0;
char c;
for (c = getc(input_file); c != EOF; c = getc(input_file))
// Increment count for this character
characters = characters + 1;
printf("characters: %d\n", characters);
fclose(input_file);
}
}
}

Counting chars, words and lines in a file

I try to count the number of characters, words, lines in a file.
The txt file is:
The snail moves like a
Hovercraft, held up by a
Rubber cushion of itself,
Sharing its secret
And here is the code,
void count_elements(FILE* fileptr, char* filename, struct fileProps* properties) // counts chars, words and lines
{
fileptr = fopen(filename, "rb");
int chars = 0, words = 0, lines = 0;
char ch;
while ((ch = fgetc(fileptr)) != EOF )
{
if(ch != ' ') chars++;
if (ch == '\n') // check lines
lines++;
if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0') // check words
words++;
}
fclose(fileptr);
properties->char_count = chars;
properties->line_count = lines;
properties->word_count = words;
}
But when i print the num of chars, words and lines, outputs are 81, 18, 5 respectively
What am i missing?
(read mode does not changes anything, i tried "r" as well)
The solution I whipped up gives me the same results as the gedit document statistics:
#include <stdio.h>
void count_elements(char* filename)
{
// This can be a local variable as its not used externally. You do not have to put it into the functions signature.
FILE *fileptr = fopen(filename, "rb");
int chars = 0, words = 0, lines = 0;
int read;
unsigned char last_char = ' '; // Save the last char to see if really a new word was there or multiple spaces
while ((read = fgetc(fileptr)) != EOF) // Read is an int as fgetc returns an int, which is a unsigned char that got casted to int by the function (see manpage for fgetc)
{
unsigned char ch = (char)read; // This cast is safe, as it was already checked for EOF, so its an unsigned char.
if (ch >= 33 && ch <= 126) // only do printable chars without spaces
{
++chars;
}
else if (ch == '\n' || ch == '\t' || ch == '\0' || ch == ' ')
{
// Only if the last character was printable we count it as new word
if (last_char >= 33 && last_char <= 126)
{
++words;
}
if (ch == '\n')
{
++lines;
}
}
last_char = ch;
}
fclose(fileptr);
printf("Chars: %d\n", chars);
printf("Lines: %d\n", lines);
printf("Words: %d\n", words);
}
int main()
{
count_elements("test");
}
Please see the comments in the code for remarks and explanations. The code also would filter out any other special control sequences, like windows CRLF and account only the LF
Your function takes both a FILE* and filename as arguments and one of them should be removed. I've removed filename so that the function can be used with any FILE*, like stdin.
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
typedef struct { /* type defining the struct for easier usage */
uintmax_t char_count;
uintmax_t word_count;
uintmax_t line_count;
} fileProps;
/* a helper function to print the content of a fileProps */
FILE* fileProps_print(FILE *fp, const fileProps *p) {
fprintf(fp,
"chars %ju\n"
"words %ju\n"
"lines %ju\n",
p->char_count, p->word_count, p->line_count);
return fp;
}
void count_elements(FILE *fileptr, fileProps *properties) {
if(!fileptr) return;
properties->char_count = 0;
properties->line_count = 0;
properties->word_count = 0;
char ch;
while((ch = fgetc(fileptr)) != EOF) {
++properties->char_count; /* count all characters */
/* use isspace() to check for whitespace characters */
if(isspace((unsigned char)ch)) {
++properties->word_count;
if(ch == '\n') ++properties->line_count;
}
}
}
int main() {
fileProps p;
FILE *fp = fopen("the_file.txt", "r");
if(fp) {
count_elements(fp, &p);
fclose(fp);
fileProps_print(stdout, &p);
}
}
Output for the file you showed in the question:
chars 93
words 17
lines 4
Edit: I just noticed your comment "trying to count only alphabetical letters as a char". For that you can use isalpha and replace the while loop with:
while((ch = fgetc(fileptr)) != EOF) {
if(isalpha((unsigned char)ch)) ++properties->char_count;
else if(isspace((unsigned char)ch)) {
++properties->word_count;
if(ch == '\n') ++properties->line_count;
}
}
Output with the modified version:
chars 74
words 17
lines 4
A version capable of reading "wide" characters (multibyte):
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <wchar.h>
#include <wctype.h>
typedef struct {
uintmax_t char_count;
uintmax_t word_count;
uintmax_t line_count;
} fileProps;
FILE* fileProps_print(FILE *fp, const fileProps *p) {
fprintf(fp,
"chars %ju\n"
"words %ju\n"
"lines %ju\n",
p->char_count, p->word_count, p->line_count);
return fp;
}
void count_elements(FILE *fileptr, fileProps *properties) {
if(!fileptr) return;
properties->char_count = 0;
properties->line_count = 0;
properties->word_count = 0;
wint_t ch;
while((ch = fgetwc(fileptr)) != WEOF) {
if(iswalpha(ch)) ++properties->char_count;
else if(iswspace(ch)) {
++properties->word_count;
if(ch == '\n') ++properties->line_count;
}
}
}
int main() {
setlocale(LC_ALL, "sv_SE.UTF-8"); // set your locale
FILE *fp = fopen("the_file.txt", "r");
if(fp) {
fileProps p;
count_elements(fp, &p);
fclose(fp);
fileProps_print(stdout, &p);
}
}
If the_file.txt contains one line with öäü it'll report
chars 3
words 1
lines 1
and for your original file, it'd report the same as above.

Unable to get File I/0 working in period counter function -c

int periodCount(const char *filename) {
FILE * fp;
int n = 0;
if( (fp=fopen(filename,"r")) != NULL) {
while(fgetc(fp)!= EOF) {
if(fgetc(fp)=='.') n++;
fclose(fp);
}
}
return n;
}
Here is my code, it simply should count the number of periods in the file named filename, which contains 15 periods, yet when I try to print 'n' at the end of the program, it seems to only be reading 1 of the periods. I know that the problem is probably within the while loop, but I'm not sure why it's doing it.
You're closing the file after the first character. Also you're skipping every other character as a result of not storing the return from fgetc(). Change to:
int periodCount(const char *filename) {
FILE * fp;
int n = 0, c = 0;
if( (fp=fopen(filename,"r")) != NULL) {
while( (c = fgetc(fp)) != EOF) {
if( c == '.' )
n++;
}
fclose(fp); /* <---- move this line here */
}
return n;
}
Your fclose(fp) should be outside the while loop.
As it is, the code is reading (& discarding) the first character; reading the 2nd character & comparing it to '.'; and closing the file.
There are two problems:
You have two calls to fgetc() but you only test whether one of them returned a dot.
You close the file stream in the body of the loop.
You need something more like:
if ((fp = fopen(filename,"r")) != NULL)
{
int c;
while ((c = fgetc(fp)) != EOF)
{
if (c == '.')
n++;
}
fclose(fp);
}

How to count blank lines from file in C?

So what I'm trying to do is to count blank lines, which means not only just containing '\n'but space and tab symbols as well. Any help is appreciated! :)
char line[300];
int emptyline = 0;
FILE *fp;
fp = fopen("test.txt", "r");
if(fp == NULL)
{
perror("Error while opening the file. \n");
system("pause");
}
else
{
while (fgets(line, sizeof line, fp))
{
int i = 0;
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ')
{
i++;
}
emptyline++;
}
printf("\n The number of empty lines is: %d\n", emptyline);
}
fclose(fp);
You should try and get your code right when posting on SO. You are incrementing both i and emptyline but the use el in your call to printf(). And then I don't know what that is supposed to be in your code where it has }ine. Please, at least make an effort.
For starters, you are incrementing emptyline for every line because it is outside of your if statement.
Second, you need to test the entire line to see if it contains any character that is not a whitespace character. Only if that is true should you increment emptyline.
int IsEmptyLine(char *line)
{
while (*line)
{
if (!isspace(*line++))
return 0;
}
return 1;
}
Before getting into the line loop increment the emptyLine counter and if an non whitespace character is encountred decrement the emptyLine counter then break the loop.
#include <stdio.h>
#include <string.h>
int getEmptyLines(const char *fileName)
{
char line[300];
int emptyLine = 0;
FILE *fp = fopen("text.txt", "r");
if (fp == NULL) {
printf("Error: Could not open specified file!\n");
return -1;
}
else {
while(fgets(line, 300, fp)) {
int i = 0;
int len = strlen(line);
emptyLine++;
for (i = 0; i < len; i++) {
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ') {
emptyLine--;
break;
}
}
}
return emptyLine;
}
}
int main(void)
{
const char fileName[] = "text.txt";
int emptyLines = getEmptyLines(fileName);
if (emptyLines >= 0) {
printf("The number of empty lines is %d", emptyLines);
}
return 0;
}
You are incrementing emptyline on every iteration, so you should wrap it in an else block.
Let's think of this problem logically, and let's use functions to make it clear what is going on.
First, we want to detect lines that only consist of whitespace. So let's create a function to do that.
bool StringIsOnlyWhitespace(const char * line) {
int i;
for (i=0; line[i] != '\0'; ++i)
if (!isspace(line[i]))
return false;
return true;
}
Now that we have a test function, let's build a loop around it.
while (fgets(line, sizeof line, fp)) {
if (StringIsOnlyWhitespace(line))
emptyline++;
}
printf("\n The number of empty lines is: %d\n", emptyline);
Note that fgets() will not return a full line (just part of it) on lines that have at least sizeof(line) characters.

Resources