C program wrong output for reading a file - c

Hello guys so I write this program which purpose is to open a file and read how many characters has in it and print the line with the most and the least characters.I've made it into two functions one for the biggest line and one for the smallest.The "biggest line" function works just fine but I get wrong output for the smallest one.Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
char f_view[150];
void ShowResults();
int leastsymbols();
int mostsymbols();
int main(){
ShowResults();
return 0;
}
int mostsymbols(){
FILE *fp;
fp=fopen(f_view, "r");
if(fp==NULL){
printf("Error\n");
exit(-1);
}
int lineNO=1;
int c;
int currCount=0;
int highestCount=0;
int highestline=0;
while ((c = getc(fp)) != EOF){
if (c == '\n') {
currCount=0;
lineNO++;
}
if (c != '\n' && c != '\t' && c!= ' ') {
currCount++;
if(currCount>highestCount){
highestCount=currCount;
if(lineNO>highestline){
highestline=lineNO;
}
}
}
}
fclose(fp);
return highestline;
}
int leastsymbols()
{
FILE *fp;
fp = fopen(f_view, "r");
if (fp == NULL)
{
printf("Could not open file \n");
exit(-1);
}
int c;
int lineNO = 1;
int currCount=0;
int leastLine=0;
int leastCount=1000;//assuming that a line in a file can not be longer
//than 1000 characters
while ((c = getc(fp)) != EOF){
if (c == '\n'){
currCount = 0;
lineNO++;
}
if (c != '\n' && c != '\t' && c!= ' ') {
currCount++;
}
if(currCount<leastCount){
leastCount=currCount;
leastLine=lineNO;
}
}
fclose(fp);
return leastLine;
}
void ShowResults()
{
FILE *fptr;
char *fix;
char c;
char openFile[1024];
printf("Type the destination to the *.c file or the file name.\n");
//the user has to enter a .C file
while(f_view[strlen(f_view) - 2] != '.' && f_view[strlen(f_view) - 1]
!= 'c')
{
fgets(f_view, 150, stdin);
fix = strchr(f_view, '\n');
if(fix != 0)
*fix = 0;
}
if((fptr = fopen(f_view, "r")) == NULL)
{
printf("Cannot open file !\n");
exit(-1);
}
int highestLine;
int lowestLine;
while (fgets(openFile, 1024, fptr))
{
highestLine=mostsymbols();
lowestLine=leastsymbols();
}
printf("Line %d has the most symbols.\n",highestLine);
printf("Line %d has the least symbols.\n",lowestLine);
fclose(fptr);
return ;
}

I fixed my program thank you.:)
while ((c = getc(fp)) != EOF){
if(c == '\n' && currCount<leastCount){
leastCount=currCount;
leastLine=lineNO;
}
if(c=='\n'){
currCount = 0;
lineNO++;
}
if (c != '\n' && c != '\t' && c!= ' ') {
currCount++;
}
}

move this check to when you go to the next line
if(currCount<leastCount){
leastCount=currCount;
leastLine=lineNO;
}
your placement is wrong because currCount is at the first iteration is still 1 or 0 depending on what is first character on the line, so it is the smallest and this is for every new line you read

Related

How to check if there is no content inside a file, and how to avoid reading the last character from a file?

I have used comma as a separator after every string
fp=fopen("log.dat","ab");
fprintf(fp,"%s%c",enteredUsername,',');
fclose(fp);
Reading from file:
fp=fopen("log.dat","rb");
int c;
while ((c = fgetc(fp)) != EOF)
printf("%c", c);
How can I:
1.Avoid reading the final character inside the file,
2.Check if file is empty?
You can use a one-character buffer like this:
#include <stdio.h>
int main(void)
{
FILE *fp = fopen("log.dat", "rb");
if(fp == NULL) return;
int prev = -1000;
int c;
while ((c = fgetc(fp)) != EOF) {
if(prev >= 0) {
printf("%c", prev);
}
prev = c;
}
fclose(fp);
return 0;
}
Input log.dat
one,two,three,
Output
one,two,three
Why you want to avoid reading the final character? You can use the EOF in order to check if a file is empty.
if( (c= fgetc(fp)) == EOF){
//do stuff
}
else{
printf("File is empty\n")
return 0;
}
That worked for me.
#include <stdio.h>
int main(void) {
unsigned counter;
for( counter=0; 1; counter++) {
int ch;
char lastchar;
ch = getc(stdin);
if (ch == EOF) break;
if (counter) putc( lastchar, stdout);
lastchar = ch;
}
if (!counter) fprintf(stderr,"File was empty\n" );
else fprintf(stderr,"Read %u characters.\n", counter );
return 0;
}
// Test it with:
// echo -n "a,b,c," >bagger
// ./a.out <bagger

How can I detect unterminated comment and write an error message saying "Error: line X: unterminated comment" to the standard error stream in my code?

#include <stdio.h>
#include <stdbool.h>
void m_cmnt(FILE *fp) {
int prev;
int ch;
while ((ch = getc(fp)) != EOF) {
if (prev == '*' && ch == '/') {
return;
} else
prev = ch;
}
}
int main(int c, char **arr) {
FILE *fp, *np;
int ch, prev;
bool String = 0;
fp = fopen("test.txt", "r");
np = fopen("temp.txt", "w");
if (fp == NULL) {
printf("Invalid/No Filename given as Argument ! \n");
return 1;
}
while ((ch = getc(fp)) != EOF) {
if (!String) {
if (ch == '/') {
prev = ch;
ch = getc(fp);
switch (ch) {
case '*':
/* if(ch != 'a') putc('h', np); */
m_cmnt(fp);
putc(' ', np);
break;
default:
putc(prev, np);
putc(ch, np);
break;
}
} else
putc(ch, np);
} else
putc(ch, np);
if (ch == '\"' || ch == '\'')
String = !String;
prev = ch;
}
fclose(fp);
fclose(np);
remove(arr[1]);
//rename("temp.txt", arr[1]);
return 0;
}
This is a simple de-commenting C program (which is C pre-processor job). I was struggling adding a feature to write an error message when detecting unterminated comment (/* example) to the standard error stream. The error should say something like Error: line X: unterminated comment where X is the line number the error occurred. I have been trying this for days now and I can't make any progress and I am highly frustrated. So please someone help me with simple and to the point answer.
test.txt
hello\nworld
Me/*some\ncomment*/again
The result of test.txt after the program run should be like
hello
world
me
again
Both of them are in separate line because \n is present in each case. But what I am getting right now is
hello\nworld
Me again
You can modify the m_cmnt() function to output the error message if it encounters EOF while scanning for */:
void m_cmnt(FILE *fp) {
int prev, ch;
for (prev = 0; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '*' && ch == '/')
return;
}
fprintf(stderr, "error: unterminated comment\n");
}
If you want to output the line number, you must keep track of the line count everywhere.
Note also that you should handle // comments too and parse the strings more accurately, handling escape sequences.
Here is a version with line number handling:
#include <stdio.h>
#include <stdbool.h>
/* skip a C multi-line comment, return the last byte read or EOF */
int m_cmnt(FILE *fp, int *lineno_p) {
int prev, ch, replacement = ' ';
for (prev = 0; (ch = getc(fp)) != EOF; prev = ch) {
if (ch == '\n') {
replacement = '\n';
++*lineno_p;
}
if (prev == '*' && ch == '/')
return replacement;
}
return EOF;
}
int main(int c, char **arr) {
FILE *fp, *np;
int ch;
bool String = 0;
const char *filename = "test.txt";
int lineno = 1;
fp = fopen(filename, "r");
np = fopen("temp.txt", "w");
if (fp == NULL) {
printf("cannot open input file %s\n", filename);
return 1;
}
while ((ch = getc(fp)) != EOF) {
if (ch == '\n')
lineno++;
if (!String) {
if (ch == '/') {
ch = getc(fp);
if (ch == '\n')
lineno++;
if (ch == '*') {
int startline = lineno;
ch = m_cmnt(fp, &lineno);
if (ch == EOF) {
fprintf(stderr, "%s:%d: error: unterminated comment started on line %d\n",
filename, *lineno, startline);
break;
}
putc(ch, np);
} else {
putc('/', np);
putc(ch, np);
}
} else {
putc(ch, np);
}
} else {
putc(ch, np);
}
if (ch == '\"' || ch == '\'')
String = !String;
}
fclose(fp);
fclose(np);
remove(arr[1]);
//rename("temp.txt", arr[1]);
return 0;
}
For illustration, here is a more complete program that handles all special cases for character and string constants and escaped newlines:
/* strip C comments by chqrlie */
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* read the next byte from the C source file, handing escaped newlines */
int getcpp(FILE *fp, int *lineno_p) {
int ch;
while ((ch = getc(fp)) == '\\') {
if ((ch = getc(fp)) != '\n') {
ungetc(ch, fp);
return '\\';
}
++*lineno_p;
}
if (ch == '\n')
++*lineno_p;
return ch;
}
int main(int argc, char *argv[]) {
FILE *fp = stdin, *ft = stdout;
const char *filename = "<stdin>";
int ch, lineno;
if (argc > 1) {
if ((fp = fopen(filename = argv[1], "r")) == NULL) {
fprintf(stderr, "Cannot open input file %s: %s\n",
filename, strerror(errno));
return 1;
}
}
if (argc > 2) {
if ((ft = fopen(argv[2], "w")) == NULL) {
fprintf(stderr, "Cannot open output file %s: %s\n",
argv[2], strerror(errno));
return 1;
}
}
lineno = 1;
while ((ch = getcpp(fp, &lineno)) != EOF) {
int startline = lineno;
if (ch == '/') {
if ((ch = getcpp(fp, &lineno)) == '/') {
/* single-line comment */
while ((ch = getcpp(fp, &lineno)) != EOF && ch != '\n')
continue;
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated single line comment\n",
filename, startline);
break;
}
putc('\n', ft); /* replace comment with newline */
continue;
}
if (ch == '*') {
/* multi-line comment */
int lastc = 0, replacement = ' ';
while ((ch = getcpp(fp, &lineno)) != EOF) {
if (ch == '/' && lastc == '*') {
break;
}
if (ch == '\n')
replacement = '\n';
lastc = ch;
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated comment\n",
filename, startline);
break;
}
putc(replacement, ft); /* replace comment with single space */
continue;
}
putc('/', ft);
/* keep parsing to handle n/"a//"[i] */
}
if (ch == '\'' || ch == '"') {
int sep = ch;
const char *const_type = (ch == '"') ? "string" : "character";
putc(sep, ft);
while ((ch = getcpp(fp, &lineno)) != EOF) {
putc(ch, ft);
if (ch == sep)
break;;
if (ch == '\\') {
if ((ch = getcpp(fp, &lineno)) == EOF)
break;
putc(ch, ft);
}
if (ch == '\n') {
fprintf(stderr, "%s:%d: unescaped newline in %s constant\n",
filename, lineno - 1, const_type);
/* This is a syntax error but keep going as if constant was terminated */
break;
}
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated %s constant\n",
filename, startline, const_type);
break;
}
continue;
}
putc(ch, ft);
}
if (fp != stdin)
fclose(fp);
if (ft != stdout)
fclose(ft);
return 0;
}

Making program to stop reading from file if EOF and read only from other

Only problem is that when one file is at EOF, program still writes - or +, just need to make some condition to make it just takes words from one file when other is at EOF. For example
prvy.txt: Ahojte nasi studenti ktori maju radi programovanie
druhy.txt: vsetci mili
treti.txt:
+Ahojte -vsetci +nasi -mili +studenti +ktori +maju +radi +programovanie
#include<stdio.h>
#include<stdlib.h>
int main(){
FILE *first, *second, *third;
char ch[256],ch1[256];
int i=1,count=0, ch2;
char space = ' ';
char minus = '-';
char plus = '+';
first=fopen("prvy.txt", "r");
second=fopen("druhy.txt", "r");
third=fopen("treti.txt", "w");
if(first==NULL || second==NULL || third==NULL)
{
perror("error");
exit(1);
}
while (fscanf(first, "%255s", ch) == 1)
{
count++;
}
while (fscanf(second, "%255s", ch) == 1)
{
count++;
}
printf("%d",count);
rewind(first);
rewind(second);
for(i;i<=count;i++)
{
if(i%2==1)
{
fputc(plus,third);
ch2=fgetc(first);
while(ch2 != EOF && ch2 != ' ' && ch2 != '\n') {
putc(ch2,third);
ch2=fgetc(first);
}
}
else if(i%2==0)
{
fputc(minus,third);
ch2=fgetc(second);
while(ch2 != EOF && ch2 != ' ' && ch2 != '\n') {
putc(ch2,third);
ch2=fgetc(second);
}
}
putc(space,third);
}
fclose(first);
fclose(second);
fclose(third);
return 0;
}
Your code will alternate between the two files. That will not work as the files may contain different number of words.
One solution could be to count the words in one variable per file. Then the loop could be something like:
// count1: number of words in first file
// count2: number of words in second file
while(count1 > 0 || count2 > 0)
{
if (count1 > 0)
{
fputc(plus,third);
ch2=fgetc(first);
while(ch2 != EOF && ch2 != ' ' && ch2 != '\n') {
putc(ch2,third);
ch2=fgetc(first);
}
--count1;
}
if (count2 > 0)
{
fputc(minus,third);
ch2=fgetc(second);
while(ch2 != EOF && ch2 != ' ' && ch2 != '\n') {
putc(ch2,third);
ch2=fgetc(second);
}
--count2;
}
putc(space,third);
}
You don't need to scan both files first to get a count. Instead, create an array of two input files and use an index to toggle between both as you read. When a file is exhausted when its turn has come, scan and print the other one.
That way, you get rid of the need to control the succesful input of two files simultaneously:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *in[2]; // Two alternating input files
FILE *out;
char line[80];
char prefix[] = "+-"; // Alternating signs, +/-
int index = 0; // index to in[] and prefix[]
in[0] = fopen("1.txt", "r");
in[1] = fopen("2.txt", "r");
out = fopen("3.txt", "w");
if (!(in[0] && in[1] && out)) {
perror("fopen");
exit(1);
}
while (fscanf(in[index], "%79s", line) == 1) {
fprintf(out, "%c%s ", prefix[index], line);
index = !index;
}
while (fscanf(in[!index], "%79s", line) == 1) {
fprintf(out, "%c%s ", prefix[!index], line);
}
fclose(in[0]);
fclose(in[1]);
fclose(out);
return 0;
}

Read from a text file shift cipher in C

I'm working on Shift cipher, I am having problems with encryption. It has no errors or trouble compiling but after I run it the output file is empty. i think reading the file but not encrypted out.txt file is empty. i didn't solve it. Thank you.
int main
{
file_in = fopen("/Users/mathmoiselle/Desktop/lucky.txt", "r");
if( file_in == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
file_out = fopen("/Users/mathmoiselle/Desktop/out.txt","r");
return 0;
}
Following on from my comments. You need to rewind the file pointer for file_in and also your includes were poorly formatted at the top. Not sure whether this makes a difference (beginner myself, but certainly stuck out when I read it):
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int encode (int, int);
int encode(int ch, int key) {
if (islower(ch)) {
ch = (ch-'a' + key) % 26 + 'a';
ch += (ch < 'a') ? 26 : 0;
}
else if (isupper(ch)) {
ch = (ch-'A' + key) % 26 + 'A';
ch += (ch < 'A') ? 26 : 0;
}
return ch;
}
int main (void)
{
FILE *file_in;
FILE *file_out;
char ch;
char text[300];
int key;
// gets(text); // Removed in question
file_in = fopen("shift_cipher.c", "r");
if( file_in == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("\n The contents of the file are : \n");
while( ( ch = fgetc(file_in) ) != EOF )
{
printf("%c",ch);
}
rewind(file_in);
// while (fgets(line, MAXLINE, f1)) {
// printf("%s", line);
// }
// gets(text); // Removed in question
file_out = fopen("out.txt","w");
printf("\n Enter the alphabetic offset key you would like to use:");
scanf("%d", &key);
while( ( ch = fgetc(file_in) ) != EOF )
{
printf("%c", ch);
ch=encode(ch, key);
fprintf(file_out, "%c", ch);
}
printf("file has been encoded");
fclose(file_out);
fclose(file_in);
return 0;
}

Find today's date in a .txt file and print line?

I have a small problem working with dates, whereas I need to print all lines in a .txt file containing the user's current date.
Here's my code:
//My function
int search(FILE *fp, char * str)
{
FILE *fp1;
fp1 = fopen("fp1","w");
char s[10],c;
int len = strlen(str);
int i = 0;
int d;
int seek = fseek(fp, 0, 0);
c = fgetc(fp);
while (c != EOF)
{
if (c == ' ' || c == '\n')
{
s[i] = '\0';
i = 0;
if (strcmp(s, str) == 0)
{
while (c = fgetc(fp) != '\n')
{
fseek(fp, -2L, 1);
d = ftell(fp);
}
while ((c = fgetc(fp)) != '\n')
{
fputc(c, fp1);
}
}
}
else
{
s[i] = c;
i++;
}
c = fgetc(fp);
}
return 1;
}
//int main function callback
printf("\n\nTasks due today("__DATE__"): \n");
FILE *tasks = fopen("tasks.txt", "r+");
search(tasks, __DATE__);
fclose(tasks);
Any idea on how to get this working?
Thank you.
Try this:
#include <stdio.h>
#include <string.h>
int search(FILE *fp, const char *str){
FILE *fp1;
fp1 = fopen("fp1","w");
if(!fp || !fp1 || !str || !*str)
return 0;
char line[128];
while(fgets(line, sizeof line, fp)){
if(strstr(line, str)){
fputs(line, fp1);
}
}
fclose(fp1);
return 1;
}
int main(void){
printf("\n\nTasks due today(\"%s\"): \n", __DATE__);
FILE *tasks = fopen("tasks.txt", "r");
search(tasks, __DATE__);//Note that __DATE__ is at the time of compilation.
fclose(tasks);
return 0;
}

Resources