C Programming , getc() , stdin , file redirection - c

My assignment is to redirect a text file and do all sorts of operations on it , everything is working except I have a little problem :
so the main function that reads input is getline1():
char* getline1(){
char *LinePtr = (char*)malloc(sizeof(char*)*LINE);
int i = 0;
for ( ; (*(LinePtr+i) = getc(stdin)) != '\n' ; i++){}
*(LinePtr+i) = '\0';
return LinePtr;
}
it returns a pointer to char array of a single line,
so we know that a new line saparates with '\n' char,
previous problem I had is when I wrote the getline1() function like this :
for (int i = 0 ; Line[i] != '\n' ; i++){
Line[i] = getc(stdin);
}
as it logically it may be authentic the getc() is a streaming function and I saw online answers that this will not work didn't quite understand why.
anyway the big issue is that I need to know how many lines there are in the text so I can stop reading values , or to know from getline1() function that there is no next line left and Im done.
things we need to take for account :
1.only <stdio.h> <stdlib.h> need to be used
2.Im using Linux Ubuntu and gcc compiler
3.the ridirection goes like ./Run<input.txt
also I understand that stdin is a file pointer , didn't found a way that this can help me.
Thank you ,
Denis

You should check for the EOF signal in addition to the newline character, you should also check for that your index-1 is always smaller than LINE to avoid overflow and also save space for the NULL terminator.
#define LINE 100
char *my_getline(void)
{
size_t i = 0;
char *str = NULL;
int c = 0;
if ((str = malloc(LINE)) == NULL)
{
fprintf(stderr,"Malloc failed");
exit(EXIT_FAILURE);
}
while (i+1 < LINE && (c = getchar()) != EOF && c != '\n') /* Saving space for \0 */
{
str[i++] = c;
}
str[i] = '\0';
return str;
}

Thanks for everybody , I just made another function to count line this was the only lazy option available :)
static void linecounter(){
FILE *fileptr;
int count = 0;
char chr;
fileptr = fopen("input.txt", "r");
chr = getc(fileptr);
while (chr != EOF){
if (chr == '\n'){count = count + 1;}
chr = getc(fileptr);}
fclose(fileptr);
count_lines = count;}

Related

Working on a C program to count characters, words, sentences, lines, or all the above.

We are asked to create a program that provides a table in which the user can choose whether to count characters, words, sentences, lines, or all the above. This requires a separate function for each utility. I have the line counter working perfectly, but for some reason, the character counter function keeps returning 0. The program is incomplete, but I am getting very frustrated with the character counter.
#include <stdlib.h>
#define WHT_SPC\
(cur == ' ' || cur == '\n' || cur == '\t')
int countLines(sp1);
int wordCounter(sp1);
int characterCounter(sp1);
int sentenceCounter (sp1);
int main()
{
int lineCount = 0;
int wordCount = 0;
int characterCount= 0;
int sentenceCount = 0;
char filename[100];
FILE* sp1;
printf("Enter Filename to be read: ");
gets(filename);
sp1 = fopen(filename,"r");
lineCount = countLines(sp1);
characterCount = characterCounter(sp1);
printf("Number of Lines: %d\n",lineCount);
printf("Number of Characters: %d\n",characterCount);
fclose(sp1);
return 0;
}
int countLines(sp1)
{
int curCh;
int preCh;
int countLn = 0;
while ((curCh = fgetc(sp1)) != EOF)
{
if (curCh == '\n')
countLn++;
preCh = curCh;
}
if (preCh != '\n')
countLn++;
return countLn;
}
int characterCounter(sp1)
{
int chr;
int countCh = 0;
while ((chr = fgetc(sp1)) != EOF)
{
if (chr != 'n' && chr != ' ')
countCh++;
}
return countCh;
}
I understand the lack of comments is not ideal, but my problem is very specific. Not looking for answers just some advice to kind of point me in the right direction.
sp1 is a structure that holds, among other things, your position in the file you are reading. After the inner loop of countLines(), this field will point the end of the file. You will need to call rewind(sp1); before performing other read operations on this same stream, so it will work on its beginning again.
Don't hesitate to take a look at man rewind!
fgetc() increments the filepointer.
Thus characterCounter() caled after countLines() has to return 0 as the first character it encounters is EOF.
Try using fseek(sp1, 0L, SEEK_SET) before characterCounter().

Is this a valid use of fgetc?

My input stream is from a text file with a list of words separated by the \n character.
The function stringcompare is a function that will compare the equivalence of two strings, case insensitive.
I have two string arrays, word[50] and dict[50]. word is a string that would be given by the user.
Basically what I want to do is pass word[] and each word in the text file as arguments of the stringcompare function.
I've compiled and run this code but it is wrong. Very wrong. What am I doing wrong? Can I even use fgetc() like this? would dict[] even be a string array after the inner loop is done?
char c, r;
while((c = fgetc(in)) != EOF){
while((r = fgetc(in)) != '\n'){
dict[n] = r;
n++;
}
dict[n+1] = '\0'; //is this necessary?
stringcompare(word, dict);
}
It is wrong.
The return value of fgetc() should be stored to int, not char, especially when it will be compared with EOF.
You might forgot to initialize n.
You will miss the first character of each line, which is stored to c.
Use dict[n] = '\0'; instead of dict[n+1] = '\0'; because n is already incremented in the loop.
Possible fix:
int c, r;
while((c = fgetc(in)) != EOF){
ungetc(c, in); // push the read character back to the stream for reading by fgetc later
n = 0;
// add check for EOF and buffer overrun for safety
while((r = fgetc(in)) != '\n' && r != EOF && n + 1 < sizeof(dict) / sizeof(dict[0])){
dict[n] = r;
n++;
}
dict[n] = '\0'; //this is necessary
stringcompare(word, dict);
}

Using fgetc to pass only part of a text file to a buffer

I have the following text file:
13.69 (s, 1H), 11.09 (s, 1H).
So far I can quite happily use either fgets or fgetc to pass all text to a buffer as follows:
char* data;
data = malloc(sizeof(char) * 100);
int c;
int n = 0;
FILE* inptr = NULL;
inptr = fopen("NMR", "r");
if(NULL == fopen("NMR", "r"))
{
printf("Error: could not open file\n");
return 1;
}
for (c = fgetc(inptr); c != EOF && c != '\n'; c = fgetc(inptr))
{
data[n++] = c;
}
for (int i = 0, n = 100; i < n; i++)
{
printf ("%c", data[i]);
}
printf("\n");
and then print the buffer to the screen afterwards. However, I am only looking to pass part of the textfile to the buffer, namely:
13.69 (s, 1H),
So this means I want fgetc to stop after ','. However, this means the that the text will stop at 13.69 (s, and not 13.69 (s, 1H),
Is there a way around this? I have also experimented with fgets and then using strstr as follows:
char needle[4] = ")";
char* ret;
ret = strstr(data, needle);
printf("The substring is: %s\n", ret);
However, the output from this is:
), 11.09 (s, 1H)
thus giving me the rest of the string which I do not want. It's an interesting one and if anyone has any tips it would be much appreciated!
If you know that the closing parenthesis is the last character you want, you can use that as your stopping point in the fgetc() loop:
char data[100]; //No need to dynamically allocate if we know the size at compile time
int c;
int n = 0;
FILE* inptr = NULL;
inptr = fopen("NMR", "r");
if(inptr == NULL) //We want to check the value of the file we just opened
{ //and plan to use
printf("Error: could not open file\n");
return 1;
}
//We'll keep the original value guards (EOF and '\n') below and add two more
//to make sure we break from the loop
//We use n<98 below to make sure we can always create a null-terminated string,
//If we used 99, the 100th character might be a ')', then we have no room for a
//terminating null-char
for (c = fgetc(inptr); c != ')' && n < 98 && c != EOF && c != '\n'; c = fgetc(inptr))
{
data[n++] = c;
}
if(c != ')') //We hit EOF, \n, or ran out of space in data[]
{
printf("Error: no matching sequence found\n");
return 2;
}
data[n]=')'; //Could also write data[n]=c here, since we know it's a ')'
data[n+1]='\0'; //Add the terminating null character
printf("%s\n",data); //Since it's a properly formatted string, we can use %s
(Note that this example will handle null input characters differently from yours. If you expect null characters to be in the input stream (NMR file) then change the printf("%s",...) line back to the for loop you originally had.
Well with only one example of the format you are trying to parse it's not totally possible to give an answer, however if your input is always like this I would simply have a counter and break after the second comma.
int comma = 0;
for (c = fgetc(inptr); c != EOF && c != '\n' && c != ',' && comma < 1; c = fgetc(inptr))
{
if (data[n] = ',')
comma++;
data[n++] = c;
}
In case the characters inside the parenthesis can be more complex I would simply maintain a boolean state to know if I am actually inside or outside a parenthesis and break when I read a comma outside of it.
Simply read using fgets and store desired string in char * using sscanf-
char *new_data;
new_data=malloc(100); // allocate memory
...
fgets(data,100,inptr); // read from file but check its return
sscanf(data,"%[^)]",new_data); // store string untill ')' in new_data from data
strcat(new_data,")"); // concatenating new_data and ")"
printf("%s",new_data); // print new_data
...
free(new_data); // remember to free memory
Also you should check return of malloc though not done in my example and also close the file opened .

Counting lines, numbers, and characters in C

I'm new to C and I got an assignment today that requires that I read text in from a file, count the number of lines, characters, and words, and return it in a specific format.
Just to be clear - I need to read in this text file:
"I must not fear.
Fear is the mind-killer.
Fear is the little-death that brings total obliteration.
I will face my fear.
I will permit it to pass over me and through me.
And when it has gone past I will turn the inner eye to see its path.
Where the fear has gone there will be nothing... only I will remain"
Litany Against Fear, Dune by Frank Herbert
and have it output like so:
1)"I must not fear.[4,17]
2)Fear is the mind-killer.[4,24]
3)Fear is the little-death that brings total obliteration.[8,56]
4)I will face my fear.[5,20]
5)I will permit it to pass over me and through me.[11,48]
6)And when it has gone past I will turn the inner eye to see its path.[16,68]
7)Where the fear has gone there will be nothing... only I will remain"[13,68]
8) Litany Against Fear, Dune by Frank Herbert[7,48]
Now, I've written something that will accept the file, it counts the number of lines properly, but I have 2 major issues - 1. How do I get the text from the file to appear in the output? I can't get that at all. My word count doesn't work at all, and my character count is off too. Can you please help?
#include <stdio.h>
#define IN 1
#define OUT 0
void main()
{
int numChars = 0;
int numWords = 0;
int numLines = 0;
int state = 0;
int test = 0;
FILE *doesthiswork;
doesthiswork = fopen("testWords.in", "r");
state = OUT;
while ((test = fgetc(doesthiswork)) != EOF)
{
++numChars;
if ( test == '\n')
{
++numLines;
if (test == ' ' || test == '\t' || test == '\n')
{
state = OUT;
}
else if (state == OUT)
{
state = IN;
++numWords;
}
}
printf("%d) I NEED TEXT HERE. [%d %d]\n",numLines, numWords, numChars);
}
}
It will be better if you use getline() function to read each line from the file.
And after reading the line process it using strtok() function. With this you will get the number of words in the line and save it in a variable.
Then process each variable and get the number of characters.
Output the line number, number of words and the number of characters.
Then read another line and so on.
How do I get the text from the file to appear in the output?
It should be stored there by preparing a buffer.
My word count doesn't work at all, and my character count is off too.
Order in which the test is wrong.
fix like this:
#include <stdio.h>
#define IN 1
#define OUT 0
int main(){
int numChars = 0;
int numWords = 0;
int numLines = 0;
int state = OUT;
int test;
char buffer[1024];
int buff_pos = 0;
FILE *doesthiswork;
doesthiswork = fopen("data.txt", "r");
state = OUT;
while((test = fgetc(doesthiswork)) != EOF) {
++numChars;
buffer[buff_pos++] = test;
if(test == ' ' || test == '\t' || test == '\n'){
state = OUT;
if(test == '\n') {
++numLines;
--numChars;//no count newline
buffer[--buff_pos] = '\0';//rewrite newline
printf("%d)%s[%d,%d]\n", numLines, buffer, numWords, numChars);
buff_pos = 0;
numWords = numChars = 0;
}
} else {
if(state == OUT){
state = IN;
++numWords;
}
}
}
fclose(doesthiswork);
if(buff_pos != 0){//Input remains in the buffer.
++numLines;
buffer[buff_pos] = '\0';
printf("%d)%s[%d,%d]\n", numLines, buffer, numWords, numChars);
}
return 0;
}

fgetc to skip from point to new line

I am trying to get fgetc to read through a file and skip from a certain indicator until a new line. This seems like a simple question, but I can't find any documentation on it.
Here is an example of my question:
read this in ; skip from semicolon on to new line
My best guess at a solution would be to read in the entire file, and for each line use strtok to skip from ; to the end of the line. Obviously this is horrible inefficient. Any ideas?
*I need to use fgetc or something like fgetc that will parse the file character by character
Easiest thing to do is read the entire line in, then truncate if there a ;.
char buffer[1024], * p ;
if ( fgets(buffer, sizeof(buffer), fin) )
{
if (( p= strchr( buffer, ';' ))) { *p = '\0' ; } // chop off ; and anything after
for ( p= buffer ; ( * p ) ; ++ p )
{
char c= * p ;
// do what you want with each character c here.
}
}
When you do the read, buffer will initially contain:
"read this in ; skip from semicolon on to new line\n\0"
After you find the ; in the line and stick a '\0' there, the buffer looks like:
"read this in \0 skip from semicolon on to new line\n\0"
So the for loop starts at r and stops at the first \0.
//Function of compatible fgets to read up to the character specified by a delimiter.
//However file stream keep going until to newline.
//s : buffer, n : buffer size
char *fgets_delim(char *s, int n, FILE *fp, char delimiter){
int i, ch=fgetc(fp);
if(EOF==ch)return NULL;
for(i=0;i<n-1;++i, ch=fgetc(fp)){
s[i] = ch;
if(ch == '\n'){
s[i+1]='\0';
break;
}
if(ch == EOF){
s[i]='\0';
break;
}
if(ch == delimiter){
s[i]='\0';//s[i]='\n';s[i+1]='\0'
while('\n'!=(ch = fgetc(fp)) && EOF !=ch);//skip
break;
}
}
if(i==n-1)
s[i] = '\0';
return s;
}
Given a requirement to use fgetc(), then you are probably supposed to echo everything up to the first semicolon on the line, and suppress everything from the semicolon to the end of the line. I note in passing that getc() is functionally equivalent to fgetc() and since this code is about to read from standard input and write to standard output, it would be reasonable to use getchar() and putchar(). But rules are rules...
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int c;
bool read_semicolon = false;
while ((c = fgetc(stdin)) != EOF)
{
if (c == '\n')
{
putchar(c);
read_semicolon = false;
}
else if (c == ';')
read_semicolon = true;
else if (read_semicolon == false)
putchar(c);
/* else suppressed because read_semicolon is true */
}
return 0;
}
If you don't have C99 and <stdbool.h>, you can use int, 0 and 1 in place of bool, false and true respectively. You can use else if (!read_semi_colon) if you prefer.

Resources