read file line by line in C(without using fgets) - c

I have a file with 3 lines in it, I'm tring to read this file and save each line as a separate string.
here is what I tried to do, it does save the first line but it overrides it by saving the first line and the second line' and I can't get my head around on how to do save each line as an individual string , and also I'm getting an error->
* stack smashing detected *: /home/ubuntu/workspace/ex12.c.o terminated
Aborted
#include <stdio.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
#include <unistd.h>
extern int errno;
int main( int argc, char *argv[] ) {
char *path1;
char firstline[80];
char secondline[80];
char thirdline[80];
printf("Program name %s\n", argv[0]);
if( argc == 2 ) {
printf("The path of the config file that you supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
int fd1 = open(argv[1], O_RDONLY | O_CREAT);
if (fd1 ==-1)
{
// print which type of error have in a code
printf("Error Number % d\n", errno);
// print program detail "Success or failure"
perror("Program");
exit(EXIT_FAILURE);
}
else {
char c;
int i=0;
while ((read(fd1, &c, 1) == 1) )
{
firstline[i++]=c;
if(c=='\n')
{
//printf("end of line");
printf("%s",firstline);
}
}
}
int close(int fd1);
return 0;
}
NOTE: I DO NOT WANT to use fopen,fgets,sscanf or getline.
Any help would be appreciated

Here is an example to demonstrate the brake from first loop from your example:
#define MAXLENGTH 80
...
char firstline[MAXLENGTH + 1] = {0};
char secondline[MAXLENGTH + 1] = {0};
char thirdline[MAXLENGTH + 1] = {0};
....
else {
char c;
int i=0;
while ((read(fd1, &c, 1) == 1 && i < MAXLENGTH)
{
firstline[i++]=c;
if(c=='\n')
{
break; /* break from first loop */
}
}
/* add a '\0' to the end of the string! */
firstline[i] = '\0';
//printf("end of line");
printf("%s",firstline);
i=0;
while ((read(fd1, &c, 1) == 1 && i < MAXLENGTH)
{
secondline[i++]=c;
if(c=='\n')
{
break; /* break from second loop */
}
}
/* add a '\0' to the end of the string! */
secondline[i] = '\0';
printf("%s",secondline);
i = 0;
int i=0;
while ((read(fd1, &c, 1) == 1 && i < MAXLENGTH)
{
thirdline[i++]=c;
if(c=='\n')
{
break; /* break from third loop */
}
}
/* add a '\0' to the end of the string! */
thirdline[i] = '\0';
//printf("end of line");
printf("%s",thirdline);
}
...

printf prints until a NULL terminating character is seen. Your printf goes over unallocated memory areas because you are not inserting a NULL(value 0) at the end of the string.
Also, you forgot to reinitialize i to 0.
while ((read(fd1, &c, 1) == 1) )
{
firstline[i++]=c;
if(c=='\n')
{
firstline[i] = 0;
i = 0;
//printf("end of line");
printf("%s",firstline);
}
}

The reason you are getting the error is most likely because you never reset i back to 0 so you keep reading more than 80 characters in to firstline
As to saving each line in to its own string, your just need to use you other variables, instead of using firstline all the time.
There a couple of ways to do that:
When you detect end of line exit the loop (with break), and start another loop where you will put the characters in secondline. Do the same for third.
If you already learned a bit about pointers, you can keep one loop, but use an extra variable, like char *currentLine that will hold the address of the array you want to read in to. Change the address every time you detect end of line like this: currentLine = secondline.
Also remember to put '\0' at the end of every line you read, or your program may print garbage when you try to print what you read to the screen.

the following proposed code:
cleanly compiles
performs the desired functionality
proper checks for and handles errors
gives 'magic' numbers (3, 80) meaningful names
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#define MAX_LINES 3
#define MAX_LINE_LEN 80
int main( int argc, char *argv[] )
{
char Lines[ MAX_LINES ][ MAX_LINE_LEN ] = { '\0' };
if( argc != 2 )
{
fprintf( stderr, "USAGE: %s <configFileName>\n", argv[0] );
exit( EXIT_FAILURE );
}
// implied else, correct number of command line arguments
int fd1 = open(argv[1], O_RDONLY );
if (fd1 ==-1)
{
perror( "open failed" );
exit(EXIT_FAILURE);
}
// implied else, open successful
char c;
for( int i = 0; i < MAX_LINES; i++ )
{
for( int j=0; j< MAX_LINE_LEN; j++ )
{
ssize_t bytecount = read(fd1, &c, 1 );
if( bytecount < 0 )
{
perror( "read failed" );
close( fd1 );
exit( EXIT_FAILURE );
}
// implied else, read successful
Lines[ i ][ j ] = c;
if( c == '\n' )
{
break;
}
}
}
for( int i = 0; i< MAX_LINES; i++ )
{
printf( "%s\n", Lines[i] );
}
close( fd1 );
return 0;
}
Note: this code assumes that each line is less than 80 characters
running the proposed code against its' own source file results in:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

Related

Why does fscanf ignore the first string?

I am trying to make a translator.
This is the part where I put all the strings from the text file on the memory.
But the program ignores the first string of the text file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct b
{
char b[30];
}b;
int main()
{
int d,c,i=0;
char k[30],x;
b *a;
FILE *fp;
if ((fp=fopen("translate.txt","r"))==NULL)
{
printf("Σφάλμα κατά το άνοιγμα του αρχείου\n");
}
else
{
while(!feof(fp))
{
fscanf(fp,"%s",k);
i++;
}
a=malloc((i)*(sizeof(b)));
fclose(fp);
}
if ((fp=fopen("translate.txt","r+"))==NULL)
{
printf("Σφάλμα κατά το άνοιγμα του αρχείου\n");
}
else
{
rewind(fp);
for (c=0;c<i;c++)
{
fscanf(fp,"%s",a[c].b);
}
fclose(fp);
}
1. You should write this loop (so as to check return of fscanf ) —
for (c=0;c<i;c++)
{
fscanf(fp,"%s",a[c].b);
}
as —
c=0;
while (fscanf(fp,"%29s",a[c].b) == 1 && c<i){
...
c++;
}
2. Also while(!feof(fp)) is wrong, so instead use fscanf to control the loop —
while (fscanf(fp,"%29s",k)==1)
i++;
Note — And, just to avoid confusion, give different names to your structure member and structure.
after applying all the comments, the resulting code is:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char **lines = NULL;
size_t lineCount = 0;
FILE *fp = NULL;
if ((fp=fopen("translate.txt","r"))==NULL)
{
perror("Σφάλμα κατά το άνοιγμα του αρχείου\n");
exit( EXIT_FAILURE );
}
char * inputBuf = NULL;
size_t inputLen = 0;
while( getline( &inputBuf, &inputLen, fp ) )
{
lineCount++;
char **tempLines = realloc( lines, (lineCount+1)*sizeof( char*) );
if( !tempLines )
{ // then realloc failed
perror( "realloc failed");
free( lines );
exit( EXIT_FAILURE );
}
lines = tempLines;
lines[lineCount] = strdup( inputBuf );
lineCount++;
}
fclose(fp);
free( lines );
return 0;
} // end function: main
however, this code is not very efficient as it repeatedly calls realloc()
To fix that, initially allocate enough room in lines[] for several lines, say 10, then keep a count of how many of those pointers are being used.
When all the allocated pointers are used and need to add another line, then double the allocation via realloc().

Stdin with getc producing additional output, and opening file causing segmentation fault in C

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
typedef int bool;
#define true 1
#define false 0
#define A 65
#define Z 90
#define a 97
#define z 122
#define NEWLINE 10
int main(int argc, char* argv[])
{
int noArgReverse();
int argReverse(int i, char* c[]);
if (argc == 1){
if (noArgReverse() == 0)
return 0;
else
return 1;
}
if (argc > 1){
if (argReverse(argc, argv) == 0)
return 0;
else
return 1;
}
else{
fprintf(stderr, "unknown error detected.\n");
return 1;
}
}
int noArgReverse()
{
char charInput[10000];
int pointerArray[5000];
int pointerCount = 0;
bool wordStart = false;
int indexer;
int lineLength;
int parser;
char currInput;
pointerArray[0] = 0; // first word would start at 0 be default
while (currInput != EOF){
lineLength = 0;
indexer = 0;
pointerCount = 0;
while ((currInput = getc(stdin)) != NEWLINE){
/*
* I am implementing a 10,000 char limit, as this seems an
* unreasonable length.
*/
if (lineLength == 9999){
fprintf(stderr, "Line length exceeded 10,000 chars. "
"This line and, if in the middle of a word,"
"will be split.\n");
break;
}
if (!wordStart){
if ((currInput >= A && currInput <= Z) || (currInput >= a && currInput <= z)){
wordStart = true;
}
}
while (wordStart){
charInput[lineLength++] = currInput;
currInput = getc(stdin);
//if the word has ended
if ((currInput < A || currInput > Z) && (currInput < a || currInput > z)){
wordStart = false;
charInput[lineLength++] = '\0';
if (pointerCount != 0){ // at least one word has been added
++indexer;
pointerArray[indexer] = pointerCount;
pointerCount = lineLength;
}
else //first word of the line to be added
pointerCount = lineLength;
}
}
}
while (indexer >= 0){
parser = pointerArray[indexer--];
while (charInput[parser] != '\0')
fprintf (stdout, "%c", charInput[parser++]);
fprintf (stdout, " ");
}
fprintf (stdout, "\r\n");
if (lineLength == 0){
currInput = EOF;
}
}
return 0;
}
int argReverse (int argc, char* argv[])
{
char charInput[10000];
int pointerArray[5000];
int pointerCount = 0;
bool wordStart = false;
int indexer;
int lineLength;
int parser;
char currInput;
FILE *currentFile;
while (argc > 0){
currentFile = fopen(argv[argc--], "r");
while ((currInput = getc(currentFile)) != EOF){
lineLength = 0;
indexer = 0;
pointerCount = 0;
while (currInput != NEWLINE){
/*
* I am implementing a 10,000 char limit, as this seems an
* unreasonable length for a single line.
*/
if (lineLength == 9999){
fprintf(stderr, "Line length exceeded 10,000 chars. "
"This line and, if in the middle of a word, the word, "
"will be split.\n");
break;
}
if (!wordStart){
if ((currInput >= A && currInput <= Z) || (currInput >= a && currInput <= z)){
wordStart = true;
}
}
while (wordStart){
charInput[lineLength++] = currInput;
currInput = getc(currentFile);
//if the word has ended
if ((currInput < A || currInput > Z) && (currInput < a || currInput > z)){
wordStart = false;
charInput[lineLength++] = '\0';
if (pointerCount != 0){ // at least one word has been added
++indexer;
pointerArray[indexer] = pointerCount;
pointerCount = lineLength;
}
else //first word of the line to be added
pointerCount = lineLength;
}
}
}
}
fclose(currentFile);
}
return 0;
}
So for my first function, I'm getting an error I can't seem to get to the bottom to while debugging, or, rather, I'm not sure how to solve. The function should take input from stdin, and print the words in reverse order (the chars should remain in order, so "This is a sentence" should be "sentence a is This"). Simple enough. However, when I give sample input, the output I get is all wrong.
input:
This is sample
input for testing
output:
testing for input sample is This
This
The input has one return, but the output has an extra return between the lines, and does not split the lines.
So, it's not printing the newline when it should, and it's printing the first inputted word again when it ends.
The second issue I am having is in the second set of code, the argReverse function. After the file is opened, in this case I use test.txt, which is a simple text file with a couple lines of phrases and empty lines, the first use of getc returns a segmentation fault. I read this is a permission or failed file opening, but I'm not sure what to do to fix this. I'm trying to open the last file first and work down from there, obviously, and this should be able to handle multiple files, but I can't even open one. I'm not sure what to do to fix this. I've tried moving the getc outside of the while loop, same problem. I'm guessing I'm doing something wrong with opening the file, but I don't know what it is.
Notes on style:
The bool type, and true and false are defined in <stdbool.h>.
Use character constants like 'A' 'Z' 'a' 'z' '\n' instead of hard-coded numbers, and/or use the character classification functions like isalpha from <ctype.h>.
The "reverse" functions just return 0 when they end, so there's no point in returning anything. They should be declared as returning void. If they did return something useful, I would return that value from main (eliminating the if statements). For example,
if ( argc == 1 )
return noArgReverse();
Putting large arrays on the stack is generally a bad idea. (Large is subjective, but I use 2K bytes as a rule of thumb.) For a non-reentrant function, you can declare the arrays as static to get them off the stack. For a reentrant function, you can malloc the arrays, and free them at the end.
Notes on design:
The fgets function will read a line and put it into a buffer. No need to read a character at a time.
When processing command line arguments, the canonical loop is
int main( int argc, char *argv[] )
{
for ( int i = 1; i < argc; i++ )
printf( "argv[%d] is \"%s\"\n", i, argv[i] );
}
The reason for your seg-fault is that you are using argv[argc], which the C specification guarantees to be NULL. So you are passing NULL to fopen. Furthermore, you should always check the return value from fopen, because fopen will return NULL if it is unable to open the file.
By far the biggest design issue in the code is repetition. You have two almost-identical functions, which is a nightmare to debug and maintain, since every change needs to be made twice, and tested twice. The solution is to define a reverse function that takes a file pointer as input. The main function should take care of opening/closing the files, or can pass stdin when there aren't any args.
Sample code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXL 10000
#define MAXW 5000
void reverse( FILE *fp );
int main( int argc, char *argv[] )
{
if ( argc < 2 )
{
reverse( stdin );
return 0;
}
FILE *fp;
for ( int i = 1; i < argc; i++ )
{
printf( "----- %s -----\n", argv[i] );
if ( (fp = fopen( argv[i], "r" )) == NULL )
{
printf( "***Error: unable to open file\n" );
}
else
{
reverse( fp );
fclose( fp );
}
}
return 0;
}
void reverse( FILE *fp )
{
static char line[MAXL]; // buffer for the input line
static char *word[MAXW]; // array of pointers to the words on the line
while ( fgets( line, MAXL, fp ) != NULL )
{
int i = -1;
int count = 0; // count of words on the line
for (;;)
{
// skip any non-alpha characters
for ( i++; line[i]; i++ )
if ( isalpha( line[i] ) )
break;
// check if we've reached the end of the line
if ( !line[i] )
break;
// add the pointer to the word list
word[count++] = &line[i];
// scan till we reach the end of the word
for ( i++; line[i]; i++ )
if ( !isalpha( line[i] ) )
break;
// check if we've reached the end of the line
if ( !line[i] )
break;
// terminate the word
line[i] = '\0';
}
// output the words in reverse order
for ( i = count - 1; i >= 0; i-- )
printf( "%s ", word[i] );
printf( "\n" );
}
}

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 Greek words to uppercase

I have to create a function that reads a file called grwords.txt containing around 540000 words which are written in Greek letters.
I have to convert these words to uppercase and fill an array called char **words.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <ctype.h>
void fp();
int main(int argc, char *argv[]) {
SetConsoleOutputCP(1253);
fp();
return 0;
}
void fp(){
char **words;
words = malloc(546490 * sizeof(int *));
for (i = 0; i < 546490; i++)
words[i] = malloc(24 * sizeof(int));
FILE *file;
char *word;
size_t cnt;
file = fopen("grwords.txt", "rt");
if (file == NULL){
printf("File cannot be opened.\n");
exit(1);
}
cnt = 0;
while (1==fscanf(file, "%24s",word)){
if (cnt == 546490)
break;
strcpy(words[cnt++], word);
}
fclose(file);
}
I'm still trying to figure out pointers. I know that & makes a pointer from a value and * a value from a pointer. Updated the program and it successfully fills the array with the words from the file! I still have no idea how to convert Greek lowercase to uppercase.
Handling Greek words can be dependent on your platform.
First of all, you need to understand how file handling works. Here is what I wrote:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bufSize 1024 // max lenght of word
// we are going to receive the .txt from cmd line
int main(int argc, char *argv[])
{
FILE *fp;
// Assume file has max 10 words
const size_t N = 10;
// Allocate a 2D array of N rows
// and bufSize columns.
// You can think of it like an array
// of N strings, where every string
// has, at most, bufSize length.
char buf[N][bufSize];
// make sure we got the .txt
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
// open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
// we will use that for toupper()
char c;
// counters
int i = 0, j;
while (fscanf(fp, "%1024s", buf[i]) == 1)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
// print what we read
printf("%s\n", buf[i]);
j = 0;
// while we are on a letter of word placed
// in buf[i]
while (buf[i][j])
{
// make the letter capital and print it
c = buf[i][j];
putchar (toupper(c));
j++;
}
i++;
printf("\ndone with this word\n");
}
// close the file
fclose(fp);
return 0;
}
For this test.txt file:
Georgios
Samaras
Γιώργος
Σαμαράς
the code would run as:
./exe test.txt
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
Γιώργος
done with this word
Σαμαράς
Σαμαράς
done with this word
As you can see, I could read the Greek words, but failed to convert them in upper case ones.
Once you got how file handling goes, you need to use wide characters to read a file with Greek words.
So, by just modifying the above code, we get:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t buf[N][bufSize];
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
return 0;
}
And now the output is this:
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
ΓΙΏΡΓΟΣ
done with this word
Σαμαράς
ΣΑΜΑΡΆΣ
done with this word
I see that you may want to create a function which reads the words. If you need a simple example of functions in C, you can visit my pseudo-site here.
As for the 2D array I mentioned above, this picture might help:
where N is the number of rows (equal to 4) and M is the number of columns (equal to 5). In the code above, N is N and M is bufSize. I explain more here, were you can also found code for dynamic allocation of a 2D array.
I know see that you are on Windows. I tested the code in Ubuntu.
For Windows you might want to take a good look at this question.
So, after you read all the above and understand them, you can see what you asked for with dynamic memory management.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
wchar_t **get(int N, int M);
void free2Darray(wchar_t** p, int N);
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t** buf = get(N, bufSize);
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
// NEVER FORGET, FREE THE DYNAMIC MEMORY
free2Darray(buf, N);
return 0;
}
// We return the pointer
wchar_t **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
wchar_t **table;
table = malloc(N*sizeof(wchar_t *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(wchar_t) );
return table;
}
void free2Darray(wchar_t** p, int N)
{
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
Note that this code is expected to work on Linux (tested on Ubuntu 12.04), not on Windows (tested on Win 7).

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