Frequency of specific symbols on each line of a text file - c

I am making a C program that counts the occurrence of the symbol ; and . and display their frequency for each line of a text file.
My code only works with only one symbol counter for dotcoma (counts ;) and when I add another counter varriable coma(counts .) it gives me an error.
Stack arround varriable was corrupted.
Here is the full code:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS /* Да си изключа предупрежденията*/
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>/* For exit() function */
int main()
{
char file_name[1000];
FILE *file2 = 0;
gets(file_name);
int rows = 1;//broq na vsichki redove
int dotcoma[150];//broq na ;
int coma[150];//broq na .
int j;
char c;
file2 = fopen(file_name, "r");//otvarq faial za chetene
if (file2 == NULL){
printf("Cannot open %s\n", file_name);
exit(2);
}//if
for (j = 0; j<150; j++)
dotcoma[j] = 0;
coma[j] = 0;
do{
c = fgetc(file2);
if (c == '\n') rows++;
else{
if (c == ';')
dotcoma[rows - 1]++;
if (c == '.')
coma[rows-1]++;
}
} while (c != EOF);//chete do kraq na faila
if (ferror(file2)){
printf("Error reading file.\n");
exit(2);
}//if
printf("The number of the symbols on a row ");
for (j = 0; j<rows; j++){
printf("Row %d: %f %f\n", j + 1, (float)dotcoma[j], (float)coma[j]);
}
_getche();
if (fclose(file2) == EOF){
printf("Cannot close %s\n", file_name);
exit(2);
_getche();
return 0;
}
}

Try to fix your coma initialization! You forgot the brackets!
for (j = 0; j<150; j++){
dotcoma[j] = 0;
coma[j] = 0;
}

Here it is.
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS /* Да си изключа предупрежденията*/
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>/* For exit() function */
int main()
{
char file_name[1000];
FILE *file2 = 0;
gets(file_name);
int rows = 1;//broq na vsichki redove
int dotcoma[150];//broq na ;
int coma[150];//broq na .
int j;
char c;
file2 = fopen(file_name, "r");//otvarq faial za chetene
if (file2 == NULL){
printf("Cannot open %s\n", file_name);
exit(2);
}//if
for (j = 0; j<150; j++)
{
dotcoma[j] = 0;
coma[j] = 0;
}
do{
c = fgetc(file2);
if (c == '\n') rows++;
else{
if (c == ';')
dotcoma[rows - 1]++;
if (c == '.')
coma[rows-1]++;
}
} while (c != EOF);//chete do kraq na faila
if (ferror(file2)){
printf("Error reading file.\n");
exit(2);
}//if
printf("The number of the symbols on a row ");
for (j = 0; j<rows; j++){
printf("Row %d: %f %f\n", j + 1, (float)dotcoma[j], (float)coma[j]);
}
_getche();
if (fclose(file2) == EOF){
printf("Cannot close %s\n", file_name);
exit(2);
_getche();
return 0;

the return statement is inside the if(fclose...) this means the compiler will raise a warning about missing return statement
the initialization of dotcoma and coma arrays is failing becuase the 'if' only handles one code block and the coma[j] =0; is not inside a code block, This is another good reason to ALWAYS place { and } around every code block
under DOS/Windows, a new line is two characters, so this line: if (c == '\n') shows that 'c' should be an int, not a char
regarding this line: FILE *file2 = 0; file2 is a pointer, not an integer, so the line should be: FILE *file2 = NULL;
to avoid edit problems and simplify future maintenance, the 'magic number' 150 should be defined as '#define MAX_COUNT (150)' then MAX_COUNT should be used in all cases rather than the literal 150
Similar considerations should be applied for file_name
the function: getchar() returns a int value (so EOF can be recognized) so this line: 'char c;' should be 'int c;'
the exit() prototype is in stdlib.h not conio.h
regarding this line: gets(file_name); gets() is full of security problems and many other problems. It is depreciated from the C language. Much better to use fgets() as, amongst other things, it limits the number of characters read, so input buffer overflow does not occur.
#include <stdio.h>
#include <stdlib.h> /* For exit() function */
#include <string.h>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS /* Да си изключа предупрежденията*/
#include <conio.h>
#endif
#define MAX_ROWS (150)
#define MAX_FILENAME_LEN (1000)
int main()
{
char file_name[MAX_FILENAME_LEN];
FILE *file2 = NULL;
if( NULL == fgets(file_name, MAX_ROWS, stdin)
{
perror( "fgets failed" );
exit( EXIT_FAILURE )
}
// implied else, fgets successful
int rows = 1;//broq na vsichki redove
int dotcoma[MAX_ROWS] = {0};//broq na ;
int coma[MAX_ROWS] = {0};//broq na .
int j; // index/loop counter
int c; // char input from console
if( NULL == (file2 = fopen(file_name, "r") )//otvarq faial za chetene
{
perror( "fopen failed for input file" );
exit(2);
}//if
// implied else, fopen successful
while( EOF != (c = fgetc(file2) )
{
switch( c )
{
case '\n':
rows++;
break;
case ';':
dotcoma[rows - 1]++;
break;
case '.':
coma[rows-1]++;
break;
default: // all other characters
break;
} // end switch
} // end while
printf("The number of the symbols on a row ");
for (j = 0; j<rows; j++)
{
printf("Row %d: %f %f\n", j + 1, (float)dotcoma[j], (float)coma[j]);
}
fclose( file2 );
getchar(); // wait for user to read screen and enter a char
return 0;
} // end function: main

Related

How to shuffle 2 different text file into 1?

#include <stdio.h>
int main(){
char temp[64];
FILE *fp1=fopen("data/1.txt","a");
FILE *fp2=fopen("data/2.txt","r");
while(fgets(temp,64,fp2)!=NULL){
fputs(temp,fp1);
}
fclose(fp1);
fclose(fp2);
return 0;
}
With such code I was able to combine 2 different text file into 1.
data/1.txt contents: abcdefghijk
data/2.txt contents: ABCDE
Outcome: abcdefghijkABCDE
However, I am struggling with shuffling 2 different text file.
Wanted result: aAbBcCdDeEfghijk
Followings are my current code.
#include <stdio.h>
#include <string.h>
int main(){
FILE *fp1,*fp2,*fp_out;
char ch1,ch2;
int result=1;
fp1=fopen("data/1.txt","r");
fp2=fopen("data/2.txt","r");
fp_out=fopen("data/out.txt","w");
//shuffling code area//
fclose(fp1);
fclose(fp2);
fclose(fp_out);
char buf[64]={};
fp_out=fopen("data/out.txt","r");
fgets(buf,64,fp_out);
if(!strncmp("aAbBcCdDeEfghijk",buf,64))
printf("PASS\n");
else
printf("FAIL\n");
fclose(fp_out);
return 0;
}
How can I design a code in "shuffling code area" in order to have outcomes like wanted result? I have thought about making 2 different FOR loops and combining but it kept showed an error.
This is some dirty way to do the job.
You can read the file which ever you want to write first character first and then read a character from second file and write both into third file one after the other.
Just adding extra code as per your need.
This just works for your case , not tested with many cases and corner cases.
#include <stdio.h>
#include <string.h>
int main(){
FILE *fp1,*fp2,*fp_out;
char ch1,ch2;
int result=1;
int file1_content_over = 0;
int file2_content_over = 0;
fp1 = fopen("data/1.txt","r");
fp2 = fopen("data/2.txt","r");
fp_out=fopen("data/out.txt","w");
//shuffling code area//
// read till file1_content_over or file2_content_over is not finished
while(! file1_content_over || !file2_content_over)
{
ch1 = fgetc(fp1);
ch2 = fgetc(fp2);
if(ch1 != EOF)
fputc(ch1,fp_out);
else
file1_content_over = 1;
if(ch2 != EOF)
fputc(ch2,fp_out);
else
file2_content_over = 1;
}
//shuffling code area//
fclose(fp1);
fclose(fp2);
fclose(fp_out);
char buf[64]={};
fp_out=fopen("data/out.txt","r");
fgets(buf,64,fp_out);
printf("buf = %s\n", buf);
if(!strncmp("aAbBcCdDeEfghijk",buf,strlen("aAbBcCdDeEfghijk")))
printf("PASS\n");
else
printf("FAIL\n");
fclose(fp_out);
return 0;
}
Working for me! Not the best optimized code, I didnt get to much time to that!
Main():
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
int removingSPaces(char array[MAX], int sizeArray);
void orderChar(char bufFile1[MAX], char bufFile2[MAX], char bufOut[MAX], int maxSize, int sizeBuf1, int sizeBuf2);
int getChar(char buf[MAX], FILE *fp);
int main(){
FILE *fp1, *fp2, *fpOut;
char bufFile1[MAX] = {0}, bufFile2[MAX] = {0}, bufOut[MAX] = {0};
int sizeBuf1 = 0, sizeBuf2 = 0;
int maxSize=0;
if((fp1=fopen("file1.txt","r")) == NULL || (fp2=fopen("file2.txt","r")) == NULL || (fpOut=fopen("fileOut.txt","w")) == NULL){
perror("");
exit(1);
}
sizeBuf1 = getChar(bufFile1, fp1); //geting the chars from file1
fclose(fp1);
sizeBuf1 = removingSPaces(bufFile1, sizeBuf1); //removing the \n if exists from chars of file1
sizeBuf2 = getChar(bufFile2, fp2); //geting the chars from file2
fclose(fp2);
sizeBuf2 = removingSPaces(bufFile2, sizeBuf2); //removing the \n if exists from chars of file2
maxSize = sizeBuf1 + sizeBuf2; //Max Size to loop for
orderChar(bufFile1, bufFile2, bufOut, maxSize, sizeBuf1, sizeBuf2); //Order the chars!
fprintf(fpOut, "%s", bufOut); //Printing to the file
fclose(fpOut);
/* COPIED FROM YOUR CODE */
char buf[64]={0}; //Just added the 0, because you cant initialize the array like with only {}
if((fpOut=fopen("fileOut.txt", "r")) == NULL){
perror("");
exit(1);
}
fgets(buf,64, fpOut);
if(!strncmp("aAbBcCdDeEfghijk", buf, 64))
printf("PASS\n");
else
printf("FAIL\n");
fclose(fpOut);
/* COPIED FROM YOUR CODE */
return 0;
}
Functions():
int removingSPaces(char array[MAX], int sizeArray){
int size = sizeArray;
if(array[sizeArray -1] == '\n'){
array[sizeArray -1] = '\0';
size = strlen(array);
}
return size;
}
int getChar(char buf[MAX], FILE *fp){
char bufAux[MAX];
int size;
while(fgets(bufAux, sizeof(bufAux), fp)){
size = strlen(bufAux);
}
strcpy(buf, bufAux);
return size;
}
void orderChar(char bufFile1[MAX], char bufFile2[MAX], char bufOut[MAX], int maxSize, int sizeBuf1, int sizeBuf2){
int positionsF1=0, positionsF2=0;
int aux = 0; //This will starts organization by the first file! If you want to change it just change to 1;
for(int i=0; i < maxSize; i++){
if(aux == 0 && positionsF1 != sizeBuf1){
bufOut[i]=bufFile1[positionsF1];
if(positionsF2!=sizeBuf2){
aux = 1;
}
positionsF1++;
}else if(aux == 1 && positionsF2 != sizeBuf2){
bufOut[i]=bufFile2[positionsF2];
if(positionsF1!=sizeBuf1){
aux = 0;
}
positionsF2++;
}
}
}
Content of file 1:
abcdefghijk
Content of file 2:
ABCDE

How to split a text file into multiple parts in c

What i need to do, is to take a file of n lines, and for every x lines, create a new file with the lines of the original file. An example would be this:
Original File:
stefano
angela
giuseppe
lucrezia
In this case, if x == 2, 3 file would be created, in order:
First file:
stefano
angela
Second FIle:
giuseppe
lucrezia
Third File:
lorenzo
What i've done so far is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int getlines(FILE *fp)
{
int c = 0;
int ch;
do{
ch = fgetc(fp);
if(ch == '\n')
{
c++;
}
}while(ch != EOF);
fseek(fp, 0 , SEEK_SET);
return c;
}
int ix = 0;
void Split(FILE *fp, FILE **fpo, int step, int lines, int *mem)
{
FILE **fpo2 = NULL;
char * filename = malloc(sizeof(char)*64);
char * ext = ".txt";
char number[2];
for(int i = ix; i < *mem; i++)
{
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
if(!(fpo[i] = fopen(filename, "w")))
{
fprintf(stderr, "Error in writing\n");
exit(EXIT_FAILURE);
}
}
char ch;
int c = 0;
do{
ch = fgetc(fp);
printf("%c", ch);
if(ch == '\n')
{
c++;
}
if(c >= step)
{
c = 0;
ix++;
if(ix >= *mem && (ix*step) <= lines)
{
*mem = *mem + 1;
fpo2 = realloc(fpo, sizeof(FILE*)*(*mem));
Split(fp, fpo2, step, lines, mem);
}
}
putc(ch, fpo[ix]);
}while(ch != EOF);
}
int main()
{
FILE * fp;
if(!(fp = fopen("file.txt", "r")))
{
fprintf(stderr, "Error in opening file\n");
exit(EXIT_FAILURE);
}
int mem = N;
int lines = getlines(fp);
int step = lines/N;
FILE **fpo = malloc(sizeof(FILE *)*N);
Split(fp, fpo, step, lines, &mem);
exit(EXIT_SUCCESS);
}
I'm stack with segmentation error, i couldn't find the bug doing
gdb myprogram
run
bt
I really appreciate any help.
EDIT:
I've changed some things and now it works, but it creates an additional file that contains strange characters. I need to still adjust some things:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int getlines(FILE *fp)
{
int c = 0;
int ch;
do{
ch = fgetc(fp);
if(ch == '\n')
{
c++;
}
}while(ch != EOF);
fseek(fp, 0 , SEEK_SET);
return c;
}
int ix = 0;
void Split(FILE *fp, FILE **fpo, int step, int lines, int *mem)
{
FILE **fpo2 = NULL;
char * ext = ".txt";
for(int i = ix; i < *mem; i++)
{
char * filename = malloc(sizeof(char)*64);
char * number = malloc(sizeof(char)*64);
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
if(!(fpo[i] = fopen(filename, "w")))
{
fprintf(stderr, "Error in writing\n");
exit(EXIT_FAILURE);
}
free(number);
free(filename);
}
char ch;
int c = 0;
do{
ch = fgetc(fp);
printf("%c", ch);
if(ch == '\n')
{
c++;
}
if(c >= step)
{
c = 0;
ix++;
if(ix >= *mem && ((ix-1)*step) <= lines)
{
*mem = *mem + 1;
fpo2 = realloc(fpo, sizeof(FILE*)*(*mem));
Split(fp, fpo2, step, lines, mem);
}
}
putc(ch, fpo[ix]);
}while(ch != EOF);
}
int main()
{
FILE * fp;
if(!(fp = fopen("file.txt", "r")))
{
fprintf(stderr, "Error in opening file\n");
exit(EXIT_FAILURE);
}
int mem = N;
int lines = getlines(fp);
int step = lines/N;
FILE **fpo = malloc(sizeof(FILE *)*N);
Split(fp, fpo, step, lines, &mem);
exit(EXIT_SUCCESS);
}
There are a few problems in your code. But first I think you need to fix the most important thing
int step = lines/N;
Here step is 0 if your input file has less than N lines of text. This is because lines and N both are integer and integer division is rounding down.
I won't fix your code, but I'll help you with it. Some changes I
suggest:
Instead of getlines, use getline(3) from the standard
library.
fseek(fp, 0 , SEEK_SET) is pointless.
In char * filename = malloc(sizeof(char)*64), note that
both arguments to malloc are constant, and the size is arbitrary.
These days, it's safe to allocate filename buffers statically,
either on the stack or with static: char filename[PATH_MAX].
You'll want to use limits.h to get that constant.
Similarly you have no need to dynamically allocate your FILE
pointers.
Instead of
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
use sprintf(filename, "temp%d%s", i+1, ext)
get familiar with err(3) and friends, for your own convenience.
Finally, your recursive Split is -- how shall we say it? -- a nightmare. Your whole program
should be something like:
open input
while getline input
if nlines % N == 0
create output filename with 1 + n/N
open output
write output
nlines++

Config / .cfg / .ini file linked with c program

I made program that helps with learning english. You have code below, but for my question you don't need to read and understand what's inside. What I want to do is to create .cfg or .ini file, that can be open with simple notepad and lets user modify:
MAX size (default is 15)
Sleep(x) value (default is 500)
I have no idea how can I make such config file that can be modified by user,link it with my c code, and then after runing program.exe it accepts changes from there. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <Windows.h>
#define MAX 15 //word max size
struct slowa
{
char pl_word[MAX];
char eng_word[MAX];
};
void menu(void);
int count_lines(FILE*);
void print_array1 (const int[],int); //print 1-dimension array
void swap (int*,int*);
int main ()
{
srand( time( NULL ) );
int i,k,j;
FILE* fp;
fp = fopen ("tekst", "r");
if (!fp)
{
printf ("zjebales"); //"you fucked up"
return -1;
}
const int lines = count_lines(fp);
int tab[lines]= {};
int* temp = (int*)malloc(lines*sizeof(int));
for (j=0; j<lines; j++)
{
temp[j]=j+1;
}
j=lines;
for (i=0; i<lines; i++)
{
k=rand()%j--;
tab[i]=temp[k]-1;
swap(temp+k,temp+j);
}
free(temp);
struct slowa arr[lines];
rewind (fp);
for (i=0; i<lines; i++)
{
fscanf(fp, "%s %s", arr[tab[i]].pl_word, arr[tab[i]].eng_word);
}
fclose(fp);
char text[MAX];
k=0;
system("cls");
menu();
scanf("%d",&j);
system("cls");
char ch;
while ((ch = getchar()) != '\n' && ch != EOF);
switch (j)
{
case 1:
for (i=0; i<lines; i++)
{
printf ("Podaj tlumaczenie:%s\n", arr[i].eng_word); //"Write translation"
//fgets (text, MAX, stdin);
scanf ("%s",text);
if (strcmp(arr[i].pl_word, text) == 0)
{
puts ("DOBRZE!"); //"Correct!"
k++;
}
else puts ("ZLE!"); //"Wrong"
Sleep(500);
system("cls");
}
break;
case 2:
for (i=0; i<lines; i++)
{
printf ("Podaj tlumaczenie:%s\n", arr[i].pl_word); //"Write translation"
scanf ("%s",text);
if (strcmp(arr[i].eng_word, text) == 0)
{
puts ("DOBRZE!"); //Correct!
k++;
}
else puts ("ZLE!"); //Wrong!
Sleep(500);
system("cls");
}
break;
default:
puts ("miales podac 1 lub 2 dzbanie"); //"You should put 1 or 2"
getchar();
return -1;
}
printf ("Odpowiedziales dobrze na %d/%d pytan. ", k, lines); //"You answered correctly k/lines words"
if (k==lines) puts("No dobra cos tam umiesz");
else if(k>(lines/2)&&k<lines) puts ("Mogloby byc lepiej");
else puts ("Wracaj do nauki debilu");
while ((ch = getchar()) != '\n' && ch != EOF);
getchar();
return 0;
}

reading words/strings from file+length of them - c

i have a problem with my c program,
it should read words/strings from txt file, then count length of them.
when i run my program, it doesnt response
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f;
char c;
char word[50];
int a,b=0;
if ((f = fopen("file.txt", "r")) == NULL)
{
printf("CANT OPEN THE FILE" "\n");
return 1;
}
while((c=fgetc(f))!=EOF){
if (c==' ')b++;
word[b]=word[b]+c;
}
for (a=0;a<b;a++){
printf("%c ",word[0]);
}
return 0;
}
it should do this: first i open my file, then i will read every char from this file+storing this chars in array word, then when blank space occurs(' '), it should write chars to next index of array, so the words will be created on different indexes of array
then it should count the lenght of words, but that should be easy to implement, thx a sorry for my english
They are ALOT of errors with the code you shared :
J is not declared, so you need to add int j = 0; I'm assuming than j is the number on whitespace on your doc.
word[b]=word[b]+c; get changed into word[b]= c;
You add an incremntation on b in your loop then, so you wont write only on word[0].
Your printing is bad aswell, you would only show the first letter over and over.
This is the final code, corrected. It shows the entire file if the file is less than 200 caracters. J is the number of whitespace.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f;
char c;
char word[200];
int a,b=0;
int j = 0;
if ((f = fopen("file.txt", "r")) == NULL)
{
printf("CANT OPEN THE FILE" "\n");
return 1;
}
while((c=fgetc(f))!=EOF){
if (c==' ')j++;
word[b]= c;
b++;
}
for (a=0;a<b;a++){
printf("%c",word[a]);
printf("The file contains %d caracters, and %d whitespaces", b, j);
}
return 0;
}
By the way, next time. try to compile at least. It's clear that you put no effort into it before submitting a question here on SO.
the following compiles and meets your description of what needs to be done
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
#define MAX_WORD_LENGTH (50)
struct wordStruct_t
{
char word[MAX_WORD_LENGTH];
};
int main()
{
FILE *fp;
int c;
char word[50]; // assume max word length is < 50
int i = 0; // word byte index
int wordCount = 0; // count of words read
struct wordStruct_t * wordArray = NULL;
char * testArray = NULL;
if ((fp = fopen("file.txt", "r")) == NULL)
{
perror( "fopen failed for read of file.txt");
exit( EXIT_FAILURE );
}
// implied else open successful
memset( word, 0x00, sizeof( word ) );
while((c=fgetc(fp))!=EOF)
{
if( (c!=' ') && (c != '\n') )
{ // then letter to add to current word (should also check for word overflow)
word[i++] = c;
}
else
{ // else, end of word found
// allocate max room for new word
if( NULL == (testArray = realloc( wordArray, sizeof(struct wordStruct_t) * (wordCount+1)) ) )
{
perror( "realloc failed");
free( wordArray );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
wordArray = (struct wordStruct_t*)testArray;
strcpy( wordArray[wordCount].word, word );
memset( word, 0x00, sizeof(word) ); // prep for next word
} // end if
} // end while
for (i = 0; i< wordCount; i++)
{
printf("word: %d is %s and contains %d bytes\n",
i,
wordArray[i].word,
(int)strlen(wordArray[i].word ) );
}
free( wordArray );
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //for string functions
int main()
{
FILE *f;
int c; //c should be an int
char word[50];
char *ptr; //to store each word
int a,b=0;
if ((f = fopen("file.txt", "r")) == NULL)
{
printf("CANT OPEN THE FILE" "\n");
return 1;
}
while((c=fgetc(f))!=EOF){
word[b++]=c;
}
for (a=0;a<b;a++){
printf("%c ",word[a]); //word[a] not word[0]
}
ptr=strtok(word," ");//get first word
a=0;
while(ptr!=NULL)
{
printf("Word %d which is %s is %d letters long",++a,ptr,strlen(ptr));
ptr=strtok(NULL," "); //get next word
}
return 0;
}

Converting head program to tail C

I just got a semi function head program running and I need help making it into a tail program where it will display x number of lines at the end of the file. Here is my head code.
I'm having trouble thinking of how to get the counter to read the entire file then start at the bottom and show the last lines of the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1024
int numLines = 0;
int linecount = 0;
FILE *src = NULL;
char ch[MAX];
void GetArgs (int argc, char **argv){
if(argc != 4 || argc != 2) {
printf("Error not enough arguments to continue \n", argv[0]);
exit(-1);
}// end if argc doenst = 4 or 2
if(argc == 2){
src = fopen( argv[1], "r:");
numLines=10;
}// end argc = 2
if(argc == 4){
if (strcmp (argv[1], "-n") !=0 ){
numLines = atoi (argv[2]);
src = fopen (argv[3], "r");
if ( src == NULL){
fputs ( "Can't open input file." , stdout);
exit (-1);
}
while (NULL != fgets(ch, MAX, src)){
linecount++;
fputs(ch, stdout);
if (linecount == numLines){
break;
}
}
}//end of nested if
else if (strcmp (argv[2], "-n") !=0 ){
numLines = atoi (argv[3]);
src = fopen (argv[1], "r");
if ( src == NULL){
fputs ( "Can't open input file." , stdout);
exit (-1);
}
while (NULL != fgets(ch,MAX, src)){
linecount++;
fputs(ch, stdout);
if (linecount == numLines){
break;
}
}
}//end of else
}//end if argc == 4
}// end GetArgs
int main(int argc, char **argv){
GetArgs(argc, argv);
fclose( src );
}
You can keep a counter to pass through the whole file and count the total number of lines (Only call fgets to read one line at a time). Suppose N is the total number of lines and n is the number of last lines to be shown on the screen. Then start again at the beginning of the file pass through N - n lines without showing them on the screen (i.e. dont call fputs), after that call fputs for n number of times.
I used your variables and style. If I understand, you want to printout last [X] lines from file. [X] - parameter from CLI
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 1024
FILE *src = NULL;
FILE *src_end = NULL;
int linecount = 0;
char ch[MAX];
int main(int arc, char **argv) {
int i = 0;
int letter = 0;
if (arc != 4) {
puts("Wrong parameters");
return 1;
}
do {
src = fopen(argv[1], "r");
if (src == NULL) {
puts("Can't open input file.");
break;
}
if (0 != strcmp(argv[2], "-n")) {
puts("Wrong 2nd parametr");
break;
}
sscanf(argv[3], "%u", &linecount);
printf("Printout last %u lines, from file:%s\n", linecount,
argv[1]);
src = fopen(argv[1], "r");
if (src == NULL) {
fputs("Can't open input file.", stdout);
return 1;
}
for (i = 2; linecount; i++) {
fseek(src, -i, SEEK_END);
letter = fgetc(src);
if (letter == 0x0a) { // 0x0a == "\n"
fgets(ch, MAX, src);
fputs(ch, stdout);
linecount--;
}
}
} while (0);
fclose(src);
return 1;
}

Resources