C, getc/fgetc - terminal null - c

I'm writing program that counts words in C, I know I can do this simply with fscanf. But I'm using getc.
I have file like this:
One two three four five.
I'm reading chars in while loop and breaking point is when I reach terminal null.
Will c = fgetc(input); or c = getc(input); set c = '\0'; after One_ and after two_ etc.?

When a return value of a function like getc() is EOF which is -1,then you have reached the end of file.try this code to count words:
#include <stdio.h>
int WordCount(FILE *file);
int main(void)
{
FILE *file;
if(fopen_s(&file,"file.txt","r")) {
return 1;
}
int n = WordCount(file);
printf("number of words is %d\n", n);
fclose(file);
return 0;
}
int WordCount(FILE *file)
{
bool init = 0;
int count = 0, c;
while((c = getc(file)) != EOF)
{
if(c != ' ' && c != '\n' && c != '\t') {
init = 1;
}
else {
if(init) {
count++;
init = 0;
}
}
}
if(init)
return (count + 1);
else
return count;
}

Related

Finding palindrome in C

A palindrome is a word that reads the same from left to right and from right to left.
I wrote a program that finds palindromes from a console.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define SIZE 100
int main() {
int i = 0, c;
int left, right;
char string[SIZE];
while (EOF != (c = getchar()) || (c = getchar()) != '\n') {
if (isspace(c) != 0) {
if (i > 0) {
left = 0;
right = i - 1;
while (right > left) {
if (string[left] != string[right]) {
i = 0;
break;
}
++left;
--right;
}
if (left >= right) {
while (i > 0)
printf("%c", string[--i]);
printf("%c", c);
}
i = 0;
}
if (c == '\n')
break;
}
else {
string[i++] = c;
}
}
}
For example, we enter the words: dad sad mum. She outputs: dad mum. But if we write dad sad or dad mum sad. The output will be: dad mum.
That is, an extra space is printed when the last word we read is not a palindrome. How can you get around this situation?
Code is convoluted
First read input properly and form a string.
for (i = 0; i < SIZE - 1; i++) [
int ch = getchar();
if (ch == EOF || ch == '\n') {
break;
}
string[i++] = (char) ch;
}
string[i] = 0;
Then process the string in string[]. Only print spaces when needed.
const char *separator = "";
int i = 0;
while (string[i]) {
// Beginning of a word?
if (!isspace(string[i])) {
int start = i;
int end = i;
while (!isspace(string[end+1]) && string[end+1]) {
end++;
}
// At this point, start indexes the 1st char of the word
// and end indexes the last char of the word
// Now find if a palindrome
while (start <= end && string[start] == string[end]) {
start++;
end--;
}
// Found a palindrome?
if (start > end) {
fputs(separator, stdout);
separator = " "; // print a space _next_ time
while (!isspace(string[i]) && string[i]) {
fputc(string[i++], stdout);
}
} else {
i = end + 1;
}
} else {
i++;
}
}
fputc('\n', stdout);
Life is easier if you just read the string all at once, then process the string.
char s[1000];
fgets( s, sizeof(s), stdin );
char * p = strchr( s, '\n' );
if (p) *p = '\0';
If you wanted to read one character at a time you should read once, test twice:
int c;
while ( ((c = getchar()) != '\n') and (c != EOF) )
But trying to compute the palindrome-ness at the same time as reading seriously makes your algorithm waaaaay more complicated than it needs to be. Read a string first, then compute.
Now you can use integer indices from each end of the string. If you can get them to meet (or cross) then you’ve got a palindrome. Hint: put that in a function:
bool is_palindrome( const char * s )
{
int left = 0;
int right = strlen(s) - 1;
...
}

Write a program to break long input lines into two or more shorter lines of length at most n

I am currently learning C and working on a problem that breaks input lines into lengths of n. Below is my current code where n is set to 30. When it reaches the n-th index it replaces that index with ' ' and then line breaks, but it will only do it for the first n characters and I'm unsure what isn't getting rest in order to it to continue making a new line at the nth index.
int getline2(void);
int c, len, cut, counter;
char line[MAXLINE];
main() {
while ((len = getline2()) > 0) {
if (len > BREAK) {
c = 0;
counter = 0;
while (c < len) {
if (line[c] == ' ') {
counter = c;
}
if (counter == BREAK) {
line[counter] = '\n';
counter = 0;
}
counter++;
c++;
}
}
printf("%s", line);
}
return 0;
}
int getline2(void) {
int c, i;
extern char line[];
for (i = 0; i < MAXLINE - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
line[i] = c; //i gets incremented at the end of the loop
if (c == '\n') {
line[i] = c;
++i;
}
line[i] = '\0';
return i;
}
Your code is a little too complicated:
you do not need to store the bytes read from the file into an array, just output them one at a time, keeping track of the line length
when the line would become too long, output a newline and reset the count before you output the byte.
also not that none of these global variables deserves to be global.
and the prototype for main should be either int main(), int main(void) or int main(int argc, char *argv[]) or equivalent. main()` is an obsolete syntax that should be avoided.
Here is a modified version:
#include <stdio.h>
#define BREAK 30
int main() {
int c;
int len = 0;
while ((c = getchar()) != EOF) {
if (c == '\n') {
putchar(c);
len = 0;
} else {
if (len >= BREAK) {
putchar('\n');
len = 0;
}
putchar(c);
len++;
}
}
return 0;
}

How to truncate characters over a certain length in C?

I'm working on a C program that takes in an input of lines of text, and return it by printing only 40 characters each.
So far, I have this code:
#include <stdio.h>
#include <stdlib.h>
int main() {
char input = getchar();
int numChar;
int total;
while ((input != EOF) && (input != '\n')) {
++numChar;
if (numChar > 40) {
printf("\n");
++total;
numChar = 0;
}
putchar(input);
input = getchar();
}
return EXIT_SUCCESS;
}
Just updated my post with a new draft I have. For this attempt I am trying to print each character as it takes each input but if the character count is over 40, to make a new line. But, I don't get an output as expected.
You are using two uninitialized variables
int numChar;
int total;
So the program has undefined behavior.
Moreover the accumulated value of the variable total is not used in the program.
And the variable input has to be declared as having the type int.
Pay attention to that the last outputted substring can contain less than 40 characters. In this case you need to call
putchar( '\n' );
also after the loop.
Using your approach with inputting characters by means of the function getchar the program can look the following way
#include <stdio.h>
int main(void)
{
const size_t LINE_LENGTH = 40;
size_t count = 0;
for ( int c; ( c = getchar() ) != EOF && c != '\n'; )
{
putchar( c );
if ( ++count % LINE_LENGTH == 0 )
{
putchar( '\n' );
count = 0;
}
}
if ( count % LINE_LENGTH != 0 ) putchar( '\n' );
return 0;
}
If to input the string shown in your question then the output will be
This line is soooooooooooooooooo looooou
oooooooooooooooooooooooooooooooooooooooo
oooong!
I'm not sure if thats whats you're asking. Basically every 40 characters, a newline character is printed.
#include <stdio.h>
int main(void)
{
int c = 0;
size_t i = 0;
while ((c = getchar()) != EOF)
{
if (i++ < 40)
{
putchar(c);
}
else if (i++ > 40 && c !='\n')
{
i = 1;
printf("\n%c",c);
}
if (c == '\n')
{
i = 0;
}
}
return 0;
}
Edit:
Your code seem to work fine if you were to initiliaze numChar --> numChar = 0 and total --> total = 0.
Actually strings are sequences of chars terminated by a null char '\0', so strings are arrays of chars.
You can easily iterate over the string untill you encounter the null char and on every iteration you print the current char and if the character index is a multiple of 40 you print a new line char, in this way every 40 character you split the string.
So here is the code:
#include <stdio.h>
#define MAX_LENGHT 200
int main () {
char input[MAX_LENGHT];
fgets(input, MAX_LENGHT, stdin);
int index = 0;
while (input[index++] != '\0') {
putchar(input[index]);
if (index % 40 == 0) {
putchar('\n');
}
}
}
#include <stdio.h>
int main() {
char c;
for(int i = 0; (c = getchar()) != EOF; i++) {
if( !(i % 40) ) puts("");
putchar(c);
}
return 0;
}
Or if you want to avoid starting on a newline , just change the if to
if( i && !(i % 40) ) puts("");
There are multiple problems:
numChars and total are uninitialized, you get undefined behavior.
you only handle the first line of text as you stop when you read a newline.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main() {
int pos = 0, c;
while ((c = getchar()) != EOF) {
if (c == '\n') {
putchar(c);
pos = 0;
} else
if (pos < 40) {
putchar(c);
pos++;
} else {
// ignore the character beyond the first 40
}
}
return EXIT_SUCCESS;
}

remove leading spaces from string in c

I am reading in a string character by character then for each word found(separated by space) counting the length of each word, and finally printing all that information to the screen.
Sample run: trickier to master
n=8, s=[trickier]
n=2, s=[to]
n=6, s=[master]
n=0, s=[]
n=-1, s=[]
This is correct what I get is this:
n=0, s=[]
n=0, s=[]
n=8, s=[trickier]
n=2, s=[to]
n=0, s=[]
n=6, s=[master]
n=0, s=[]
n=-1, s=[]
The problem is the leading spaces in the string I have looked at a lot of examples of how to trim the leading spaces, but I couldn't get anything to work with my current source code.
Code:
#include "getword.h"
int getword(char *w) {
int iochar;
int index = 0;
int numberofchars = 0;
if (numberofchars == 0 && iochar == '\n') {
w[index] = '\0';
iochar = EOF;
return 0;
}
if (iochar == EOF && numberofchars == 0) {
w[index] = '\0';
return -1;
}
while ((iochar = getchar()) != EOF) {
if (iochar != ' ' && iochar != '\n') {
w[index] = iochar;
index++;
numberofchars++;
} else {
w[index] = '\0';
if (strcmp(w, "done") == 0) {
return -1;
} else {
return numberofchars;
}
}
} //after while loop
} // end of function
int main() {
int c;
char s[STORAGE];
for (;;) {
(void)printf("n=%d, s=[%s]\n", c = getword(s), s);
if (c == -1)
break;
}
}
The code is way too complicated, with some useless and bogus tests producing undefined behavior:
testing iochar in getword() before you even read it with getchar() makes no sense.
combining reading, testing and writing the words in a single printf() call is bogus too: you should instead read, then test, then output if not done.
Here is a simplified version:
#include <stdio.h>
#include <string.h>
#define STORAGE 50
// read a word into an array of size `size`.
// return the number of characters read.
int getword(char *w, size_t size) {
int c;
size_t i = 0;
while (i + 1 < size && (c = getchar()) != EOF) {
if (c == ' ' || c == '\t' || c == '\n') {
if (i == 0)
continue; // ignore leading spaces
else
break; // stop on white space following the word.
}
w[i++] = c;
}
w[i] = '\0';
return i;
}
int main() {
char s[STORAGE];
int len;
while ((len = getword(s, sizeof s)) != 0) {
if (!strcmp(s, "done"))
break;
printf("n=%d, s=[%s]\n", len, s);
}
return 0;
}
I tried to make the code produce desired output, but this is all I could do. There were some bugs which I thought and so I fixed them. See the comments in the code for more details. Hope that solves the problem.
int getword(char * w) {
int iochar = 0;
int index = 0;
int numberofchars = 0;
// I really don't know why those if conditions were required
// Thought they were useless so removed them
while ((iochar = getchar()) != EOF) {
if (iochar != ' ' && iochar != '\n') {
w[index++] = iochar; // slight change here
numberofchars++;
} else {
w[index] = '\0';
// I don't know what this condition is supposed to mean
// so I ignored it
if (strcmp(w, "done") == 0) {
return -1;
} else {
return numberofchars;
}
}
} //after while loop
// Since EOF is encountered, no more characters to read
// So terminate the string with '\0'
w[index] = '\0';
// Here after the loop you should check if some characters were read, but not
// handled. If there are any, return them because that's what you last read
// before EOF was encountered
return (numberofchars > 0 ? numberofchars : -1);
} // end of function
int main()
{
int c;
char s[STORAGE];
for (;;) {
// Put the if condition before printing because if -1 is returned
// it doesn't make sense to print the string at all
c = getword(s);
if (c == -1) break;
printf("n=%d, s=[%s]\n", c, s);
}
}
Here's where I tested this: http://ideone.com/bmfaA3

Input string of unknown length

I wrote this program that replaces two spaces with an '*'.
How do I modify the code so that it does the same thing regardless of the string size? Is it even possible only using putchar and getchar?
#include <stdio.h>
int c;
char buffer[256];
int counter= 0;
int i;
int main()
{
while ((c = getchar()) != '\n'&&c!=EOF) {
buffer[counter] =c;
counter++;
if (counter >=255) {
break;
}
}
for(i=0; i<256; i++) {
if(buffer[i]== ' '&&buffer[i+1]==' ')
{
buffer[i]= '*';
putchar(buffer[i]);
i = i + 2;
continue;
}
putchar(buffer[i]);
}
putchar('\n');
return 0;
}
The problem statement doesn't require you to store the complete input in a buffer. The decision on what character to output only depends on the last two characters of input. Consider the following code:
#include <stdio.h>
int main(void)
{
// two variables for the last two input characters
int c = EOF, last = EOF;
while ((c = getchar()) != EOF)
{
// if both are a space, store a single '*' instead
if (c == ' ' && last == ' ')
{
c = '*';
last = EOF;
}
// print the output, and shift the buffer
if (last != EOF)
putchar(last);
last = c;
}
// take care of the last character in the buffer after we see EOF
if (last != EOF)
putchar(last);
}
no need for malloc and friends at all. This is a good expample for a problem that requires you to think carefully, before writing code, in order to not waste unnecessary resources on buffers.
Code for just printing:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char prev = EOF, curr;
while ((curr =(char)getchar()) != '\n' && curr != EOF)
{
if(curr==' '&&prev==' ')
{
curr = '*';
prev = EOF;
}
if (prev != EOF)
putchar(prev);
prev = curr;
}
putchar(prev);
return 0;
}
Using realloc for actually changing the string:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int len_max = 128;
char *m = malloc(len_max);
char c;
int counter= 0;
int i;
int current_size = 256;
printf("please input a string\n");
while ((c = getchar()) != '\n' && c != EOF)
{
m[counter] =(char)c;
counter++;
if(counter == current_size)
{
current_size = i+len_max;
m = realloc(m, current_size);
}
}
for(i=0; i<counter; i++)
{
if(m[i]== ' '&&m[i+1]==' ')
{
m[i]= '*';
putchar(m[i]);
i = i + 2;
continue;
}
putchar(m[i]);
}
putchar('\n');
free(m);
m = NULL;
return 0;
}

Resources