pallindrome is not copied to next file but printed on output screen - c

I have a file named fp1 containing different names, some being palindromes, and have to read all names from fp1 and check if each name is a palindrome or not. If it's a palindrome the I need to print the name to screen and copy it to another file named fp.
Here's my program:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
FILE *fp, *fp1;
char m, y[100];
int k = 0, i = 0, t = 1, p = 0;
fp = fopen("C:\\Users\\HP\\Desktop\\New folder\\file 2.txt", "w");
fp1 = fopen("C:\\Users\\HP\\Desktop\\New folder\\file4.txt", "r");
if (fp == NULL) {
printf("error ");
exit(1);
}
if (fp1 == NULL) {
printf("error");
exit(1);
}
k = 0;
m = fgetc(fp1);
while (m != EOF) {
k = 0;
i = 0;
t = 1;
p = 0;
while (m != ' ') {
y[k] = m;
k = k + 1;
m = fgetc(fp1);
}
p = k - 1;
for (i = 0; i <= k - 1; i++) {
if (y[i] != y[p]) t = 0;
p = p - 1;
}
if (t == 1) {
fputs(y, fp);
printf("%s is a pallindrome\n", y);
}
m = fgetc(fp1);
}
fclose(fp);
fclose(fp1);
}
coping pallindrome from one file to next file

You are not null terminating your buffer before attempting to use the contents as a string. After placing the last valid character read by fgetc into the buffer, you must place a null terminating character (\0).
A character buffer without a null terminating byte is not a string. Passing such a buffer to fputs, or the printf specifier %s without a length bound, will invoke Undefined Behaviour.
fgetc returns an int, not a char. On systems where char is unsigned, you will not be able to reliably test against the negative value of EOF.
The inner while loop is not checking for EOF. When the file is exhausted, it will repeatedly assign EOF to the buffer, until the buffer overflows.
To that end, in general, the inner while loop does nothing to prevent a buffer overflow for longer inputs.
In a hosted environment, void main() is never the correct signature for main. Use int main(void) or int main(int argc, char **argv).
Note that fputs does not print a trailing newline. As is, you would fill the output file full of strings with no delineation.
The nested while loops are fairly clumsy, and I would suggest moving your palindrome logic to its own function.
Here is a refactored version of your program. This program discards the tails of overly long words ... but the buffer is reasonably large.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
FILE *open_file_or_die(const char *path, const char *mode)
{
FILE *file = fopen(path, mode);
if (!path) {
perror(path);
exit(EXIT_FAILURE);
}
return file;
}
int is_palindrome(const char *word, size_t len)
{
for (size_t i = 0; i < len / 2; i++)
if (word[i] != word[len - i - 1])
return 0;
return 1;
}
int main(void)
{
/*
FILE *input = open_file_or_die("C:\\Users\\HP\\Desktop\\New folder\\file4.txt", "r");
FILE *output = open_file_or_die("C:\\Users\\HP\\Desktop\\New folder\\file 2.txt", "w");
*/
FILE *input = stdin;
FILE *output = stdout;
char buffer[BUFFER_SIZE];
size_t length = 0;
int ch = 0;
while (EOF != ch) {
ch = fgetc(input);
if (isspace(ch) || EOF == ch) {
buffer[length] = '\0';
if (length && is_palindrome(buffer, length)) {
fputs(buffer, output);
fputc('\n', output);
printf("<%s> is a palindrome.\n", buffer);
}
length = 0;
} else if (length < BUFFER_SIZE - 1)
buffer[length++] = ch;
}
/*
fclose(input);
fclose(output);
*/
}

Related

How to loop a nested array in C

I've been developing a guessing game in which the goal is to guess the character selected by the user among specific characters, anyway, my first and only idea is to create an array with the questions to be asked, and each question has its options like in the code below I'm a newbie in C language so that I there are several things which I'm not sure how to handle. In short, I'd like to know how can I loop over the array showing to the user the questions with its questions to be answered? Here's the code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define ROW 500
#define LINE 200
//Read file and append to an array buffer
char *characters(){
char *source = NULL;
FILE *fp = fopen("file.txt", "r");
if (fp != NULL) {
/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
/* Allocate our buffer to that size. */
source = malloc(sizeof(char) * (bufsize + 1));
/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }
/* Read the entire file into memory. */
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
}
return source;
}
char *strndup(const char *s, size_t n) {
char *p;
size_t n1;
for (n1 = 0; n1 < n && s[n1] != '\0'; n1++)
continue;
p = malloc(n + 1);
if (p != NULL) {
memcpy(p, s, n1);
p[n1] = '\0';
}
return p;
}
// User input
char *input(){
char *value;
char buffer[10];
int j = 0;
while( j < 1 && fgets(buffer, 10, stdin) != NULL){
value = strndup(buffer, 10);
j++;
}
return value;
}
// Main function
int main (void)
{
char *questions[] = {
"Genre",{"male","female"},
"Hair", {"black","red","blond"},
"Cloths",{"dress","shirt","pants"},
"pet", {"dog","cat","pig"}
};
int asked[4] = {0};
char *answers[5];
char buffer[6];
srand(time(NULL));
for (int i = 0; i < 4; i++) {
int q = rand() % 4;
while (asked[q])
q = rand() % 4;
asked[q]++;
printf ("%s\n", questions[q]);
answers[i] = input();
}
for(int i = 0; i < 4; i++)
{
printf(" %s ",answers[i]);
}
return 0;
}
That's the file's structure I'll compare as long as I have all the answers from the user.
female,blond,vestido,pig,character b
male,black,shirt,pants,dog,character c
male,black,shirt,pants,cat,character d
female,blond,dress,cat,character A
male,red,shirt,pants,pig,character e

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++

How to indicate the last line of the file

I want to read the txt line by line and store it to the array;
I am like success to store line by line in array;
I use printf("%s", loadtext[i]) with i= 0,1,2,3-20 respectively to check that things in stored in array;
but I realize that the for loop had done 1912 times when I
type printf("%d", i); right behind the for loops,
Suppose my txt is store like this:
I am a jerk
I am a noob
I am an idiot
I am done
I have another program to add new lines to the text file while this program is running.
How can I detect I am done or the new line added later is the last line to not allow the for loop do so many times?
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
int main(){
FILE *fp = fopen("abc.txt","r");
int i = 0,j=0,k=0;
char ch[10000];
char loadtext[100][100];
for (i=0; ch[i] != EOF; i++){
ch[i] = fgetc(fp);
if (ch[i] != '\n'){
loadtext[j][k] = ch[i];
k++;
}
if(ch[i] == '\n'){
loadtext[j][k] = ch[i];
k=0;
j++;
}
}
printf("%s", loadtext[0]);
printf("%s", loadtext[1]);
printf("%s", loadtext[2]);
fclose(fp);
return 0;
}
To read a whole file into an "array" of pointers to char which represent the lines, you can do:
#include <stddef.h> // size_t
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
#include <stdio.h> // malloc(), realloc(), free(), fgets()
#include <string.h> // strlen(), strcpy()
enum { BUFFER_SIZE = 30 }; // whatever line length you suspect the input file to be + 1
int main(void)
{
char const *filename = "test.txt";
FILE *is = fopen(filename, "r");
if (!is) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
int result = EXIT_SUCCESS; // assume a happy ending
char buffer[BUFFER_SIZE];
size_t num_lines = 0;
char **lines = NULL;
while (fgets(buffer, sizeof(buffer), is)) {
++num_lines;
char **temp = realloc(lines, num_lines * sizeof(*lines));
if (!temp) {
fputs("Not enough memory :(\n\n", stderr);
fclose(is);
result = EXIT_FAILURE;
goto cleanup;
}
lines = temp;
size_t length = strlen(buffer);
length = strlen(buffer);
// remove a trailing newline if any:
if (length && buffer[length - 1] == '\n')
buffer[--length] = '\0';
size_t line_length = length;
lines[num_lines - 1] = malloc((length + 1) * sizeof(*lines));
if (!lines[num_lines - 1]) {
fputs("Not enough memory :(\n\n", stderr);
fclose(is);
result = EXIT_FAILURE;
goto cleanup;
}
strcpy(lines[num_lines - 1], buffer);
// as long as the buffer has been filled completely by the previous
// call to fgets() and a next call to fgets() also succeeds:
while (length == BUFFER_SIZE - 1 && fgets(buffer, sizeof(buffer), is)) {
length = strlen(buffer);
// remove a trailing newline if any:
if (length && buffer[length - 1] == '\n')
buffer[--length] = '\0';
char *temp = realloc(lines[num_lines - 1], line_length + length + 1);
if (!temp) {
fputs("Not enough memory :(\n\n", stderr);
fclose(is);
result = EXIT_FAILURE;
goto cleanup;
}
lines[num_lines - 1] = temp;
strcpy(lines[num_lines - 1] + line_length, buffer);
line_length += length;
}
}
fclose(is);
// use lines:
for (size_t i = 0; i < num_lines; ++i)
puts(lines[i]);
cleanup:
for (size_t i = 0; i < num_lines; ++i)
free(lines[i]);
free(lines);
return result;
}
Using only a fixed-size two-dimensional array and fgetc()*):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
enum { MAX_LINES = 100, MAX_LINE_LENGTH = 100 };
int main(void)
{
char const *filename = "test.txt";
FILE *is = fopen(filename, "r");
if (!is) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
char text[MAX_LINES][MAX_LINE_LENGTH + 1] = { 0 }; // zero-initialize the array
// so we don't have to care
size_t num_lines = 0; // about zero terminating
size_t current_column = 0; // every line
int ch;
// as long as we are still inside the bounds of the fixed size array
// and fgetc() doesn't return EOF
while (num_lines < MAX_LINES && current_column < MAX_LINE_LENGTH &&
(ch = fgetc(is)) != EOF)
{
if (ch == '\n') { // "move" num_lines and current_column to the next
++num_lines; // line.
current_column = 0;
continue;
}
text[num_lines][current_column++] = ch;
}
if (ch != EOF) {
fputs("The file is too big :(\n\n", stderr);
return EXIT_FAILURE;
}
for (size_t i = 0; i <= num_lines; ++i)
puts(text[i]);
}
*) Could be done with fgets() too.
to read the txt line by line and store it to the array
Code has various problems:
ch[i] != EOF accesses ch[i] before it is assigned! Undefined Behavior (UB).
char can be signed or unsigned. EOF is some negative. When char is unsigned the below is an infinite loop. When char is signed, ch[i] != EOF could exit the loop early.
printf("%s", loadtext[0]); attempts to print loadtext[0] as if it was a string. But lacking a certain null character, and thus not a string, this leading to more UB.
Lack of buffer index checks: loadtext[j][k] = ch[i]; k++; may increment k to beyond 100. Similar weak code with i.
Code may fail to open the file and no check provided.
Instead save the result from fgetc() as an int, test for for EOF, test for '\n' and append a null character to form strings.
Some ideas for alternate code:
#define LINES_N 100
#define LINE_SIZE 100
int main(void) {
FILE *fp = fopen("abc.txt", "r");
if (fp) {
// char ch[10000];
char loadtext[LINES_N][LINE_SIZE];
int ch_index = 0;
int line_count = 0;
int character;
int previous_character = '\n';
while ((character = fgetc(fp)) != EOF) {
// Starting a new line?
if (previous_character == '\n') {
if (++line_count > LINES_N) {
printf("Too many lines\n");
return EXIT_FAILURE;
}
}
loadtext[line_count - 1][ch_index++] = (char) character;
loadtext[line_count - 1][ch_index] = '\0';
if (ch_index + 1 >= LINE_SIZE) {
printf("Too long a line\n");
return EXIT_FAILURE;
}
previous_character = character;
}
if (line_count >= 1) printf("%s", loadtext[0]);
if (line_count >= 2) printf("%s", loadtext[1]);
if (line_count >= 3) printf("%s", loadtext[2]);
fclose(fp);
}
return 0;
}

How to store text, line by line, to a 2D array in C?

again. I'm new to C. Still thinking in Python terms (readlines, append them to variable) so I'm having difficulties translating that to C. This is what I want to do: open a text file for reading, store each line in an array row by row, print it out to make sure it's stored.
This is how far I've got:
int main(){
FILE * fp = fopen("sometext.txt", "r");
char text[100][100];
if(fp == NULL){
printf("File not found!");
}
else{
char aLine[20];
int row = 0;
while(fgets(aLine, 20, fp) != NULL){
printf("%s", aLine);
//strcpy(text[row], aLine); Trying to append a line (as row)
return 0;
}
Please don't start with "invest in some more time and look somewhere else because it's easy and has been answered". I'm bad at this, and I'm trying.
You can try this. Basically you need an array of arrays to store each line. You find the length of the longest line in the file and you allocate space for it. Then rewind the pointer to the start of the file and use fgets to get each line from the file and strdup to allocate space and copy the line to the respective position. Hope this helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE * fp = fopen("sometext.txt", "r");
int maxLineSize = 0, count = 0;
char c;
while ((c = fgetc(fp)) != EOF) {
if (c == '\n' && count > maxLineSize) maxLineSize = count;
if (c == '\n') count = 0;
count++;
}
rewind(fp);
char ** lines = NULL;
char * line = calloc(maxLineSize, sizeof(char));
for (int i = 0 ; fgets(line, maxLineSize + 1, fp) != NULL ; i++) { // +1 for \0
lines = realloc(lines, (i + 1) * sizeof(char *));
line[strcspn(line, "\n")] = 0; // optional if you want to cut \n from the end of the line
lines[i] = strdup(line);
printf("%s\n", lines[i]);
memset(line, maxLineSize, '\0');
}
fclose(fp);
}
You could solve it without copy
The follow code could work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
int main()
{
FILE * fp = fopen("sometext.txt", "r");
if(fp == NULL){
printf("File not found!");
return -1;
}
char text[100][20];
int row = 0;
while(row < 100 && fgets(text[row], sizeof(text[0]), fp) != NULL)
++row;
for (int i= 0; i != row; ++i)
fputs(text[i], stdout);
return 0;
}

Reading in bytes of a file for printable ASCII characetrs

I have to write a program that takes a file name from the command line.
It then read several bytes from the file, looking for strings of printable characters (ASCII values between 32 and 126 decimal).
Then print out the strings.
A string is a run of at least 4 consecutive printable characters and ends whenever a non-printable character is encountered.
Whenever such a string is found, print it out on a new line.
What I have so far is:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
FILE *fp;
fp = fopen(argv[1], "rb");
char buffer;
while(fp != NULL)
{
fread(&buffer, 1, 1, fp);
}
fclose(fp);
}
What I think this does it take the program from the command line and read in all the bytes of the file 1 by 1 and store them into buffer.
Now I need to check each part of the array and see if each element is between 32 and 136.
If it is, I add those bytes to another array until there is a byte not in this range.
Do this for the entirety of the buffer array.
Is this a code approach and is this right so far?
Change the while loop a bit. What you're checking is whether the file exits or not in a loop which won't fetch the required result you want.
fp is comapared with NULL to find out if the file opening is succesful or not as fopen returns address of the file if it opens a file or NULL saying something went wrong.
if( fp == NULL )
{
perror("Error while opening the file\n");
exit(0);
}
What you want do is following lines:
while( ( ch = fgetc(fp) ) != EOF ) { // reads character by character from the file
if((ch <32) || (ch>136)) // check if it is in range to printed
break;
else
printf("%c",ch); // format whoever you want
}
If I understand you correctly, you want your program to read characters from a file (the file might contain non-printable characters), and check if the character falls in the range of 32 to 126 (printable character). If it is, then add that character to a buffer and read more characters until a non-printable character is found. It should also make sure that the string should have at least 4 characters; string should be printed on a newline.
Here is the code that might help you. It was compiled with gcc, and I hope it works for you too.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *fp;
char buf[100], ch; //the size of the array would vary according to your need
int i=0;
//check for enough arguments
if(argc<2)
{
printf("\nInsufficient Arguments.\n");
printf("\nUsage: PrintChar <file>\n\n");
return 1;
}
//open the file in binary mode and check for exisitence of the file
if((fp = fopen(argv[1], "rb"))== NULL)
{
printf("\nError: Unable to open the file.\n");
return 2;
}
i=0;
while( (ch = fgetc(fp))!=EOF )
{
//check for the range
if(ch>=32 && ch<=126)
{
buf[i] = ch; i++;
//This loop will run till it find a next unprintable character (not between the range of 32 and 126
//we also check for the EOF while reading the characters
while( ( (ch = fgetc(fp))>=32 && ch<=126 ) && ch!=EOF )
{
buf[i] = ch; i++;
}
buf[i] = '\0'; //adding the NULL character
//if the string is at least of 4 letters, print it
if(i>=4)
printf("\n%s", buf);
//reset the counter
i=0;
}
}
fclose(fp);
return 0;
}
File contents - test.txt, that I used:
---------------------------------------------------------------
This is a string
anotherline of text #$%#$%#$% #$% #$%345#$$%&$&##$!##~#######
!∞▬345345µ∞#452353453$%##$%#$%$%%^&%^*4234346443754754451} 
and this is the output of the program:
C:\Users\shine\Documents\MYCPROGS\forStackoverflow>printchar test.txt
This is a string
anotherline of text #$%#$%#$% #$% #$%345#$$%&$&##$!##~#######
345#$%##$%##452353453$%##$%#$%$%%^&%^*4234346443754754451}
345345
-------------------------------------------------------------------
Hope this would be helpful. I made this is a hurry, so please let me know if you find something wrong in it.
Read one character each time, write when we find long enough string or have to:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
size_t min_str_len = 4;
size_t buf_len = 4; /* Must greater than or equal to min_str_len */
char buf[buf_len], ch;
size_t out_len, last_len;
last_len = out_len = 0;
while (fread(&ch, 1, 1, stdin) > 0) {
if (isprint(ch)) {
buf[out_len++] = ch;
if (out_len >= buf_len) {
fwrite(buf, 1, out_len, stdout);
last_len += out_len;
out_len = 0;
}
}
else {
if (out_len + last_len >= min_str_len) {
fwrite(buf, 1, out_len, stdout);
#ifdef NEWLINE
fwrite("\n", 1, 1, stdout);
#endif
last_len = out_len = 0;
}
else {
out_len = 0;
}
}
}
exit(EXIT_SUCCESS);
}
If you want to read more than one byte each time, this "at least 4 consecutive printable characters" will make it a little bit tricky:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
size_t str_min_len = 4;
size_t buf_len = 1024; /* Must greater than or equal to str_min_len */
char in_buf[buf_len], out_buf[buf_len];
size_t out_len, in_len, last_len;
last_len = out_len = 0;
while ((in_len = fread(in_buf, 1, buf_len, stdin)) > 0) {
assert(out_len == 0);
for (size_t i = 0; i < in_len; i++) {
char ch = in_buf[i];
if (isprint(ch)) {
out_buf[out_len++] = ch;
}
else {
if (out_len + last_len >= str_min_len) {
fwrite(out_buf, 1, out_len, stdout);
#ifdef NEWLINE
/* Write a newline between strings. */
fwrite("\n", 1, 1, stdout);
#endif
last_len = 0;
}
out_len = 0;
}
}
if (0 < out_len && out_len < str_min_len) {
size_t pad_len = str_min_len - out_len;
for (size_t i = 0; i < pad_len; i++) {
char ch;
if (fread(&ch, 1, 1, stdin) < 1) {
exit(EXIT_SUCCESS);
}
else if (isprint(ch)) {
out_buf[out_len++] = ch;
}
else {
break;
}
}
}
if (out_len >= str_min_len) {
fwrite(out_buf, 1, out_len, stdout);
last_len = out_len;
out_len = 0;
}
else {
last_len = out_len = 0;
}
}
exit(EXIT_SUCCESS);
}

Resources