I have the following head file code and I am looking for optimization.
How i can rewrite the code using POSIX functions without user-space buffering, without reading character by character but fixed lengths? This I think will improve the efficiency of the code.
#include "stdio.h"
int main(int argc, char* argv[])
{
if(argc<2)
{
printf("<sintaxa(%s)> fisier \n",argv[0]);
}
else
{
int count = 0;
FILE * file;
if((file = fopen(argv[1],"r")) == NULL )
printf(" file %s open error\n",argv[0]);
fseek(file,0,SEEK_SET);
while(count < 10)
{
fseek(file,-2,SEEK_SET);
if(ftell(file)<0L)
break;
char now = fgetc(file);
printf("%c",now);
if(now == '\n')
++count;
}
fclose(file);
}
}
Related
Need help getting display_stream function to read from stdin in Shell. When I type './kittycat' in Shell I am getting blank when it should read from stdin. Everything else works which is for one or more arguments it reads the text files (./kittycat test.txt test2.txt) and if I put './kittycat error.txt' it will say error file not found.' I am just missing a way to read from stdin using the function display_stream. Including Screenshots of shell output vs what is expected.
[enter image description here][1]#include <stdio.h>
#include <stdlib.h>
void display_stream(FILE *fptr);
int
main(int argc, char *argv[])
{
int i;
// if no args given, read from stdin (just like shell/cat)
if (argc < 2)
display_stream(stdin);
for (i = 1; i < argc; i++) {
FILE *fptr = fopen(argv[i], "r");
if (fptr == 0) {
printf("error: file not found.");
continue;
}
display_stream(fptr);
fclose(fptr);
}
return 0;
}
void
display_stream(FILE *fptr)
{
int x;
/* read one character at a time from file, stopping at EOF,
which indicates the end of the file. */
while ((x = fgetc(fptr)) != EOF)
putchar(x);
}
MY output
What is expected
Check argc to decide if the program should read from stdin or should open argv[i] to open the file.
Here's the refactored [and annotated] code:
#include <stdio.h>
#include <stdlib.h>
void display_stream(FILE *fptr);
int
main(int argc, char *argv[])
{
int i;
// if no args given, read from stdin (just like shell/cat)
if (argc < 2)
display_stream(stdin);
for (i = 1; i < argc; i++) {
FILE *fptr = fopen(argv[i], "r");
if (fptr == 0) {
printf("error: file not found.");
}
else {
display_stream(fptr);
#if 1
fclose(fptr);
#endif
}
}
return 0;
}
void
display_stream(FILE *fptr)
{
int x;
/* read one character at a time from file, stopping at EOF,
which indicates the end of the file. */
while ((x = fgetc(fptr)) != EOF) {
printf("%c", x);
}
// don't close this here -- let caller do it (e.g. stdin should _not_ be
// closed and only caller knows whether the stream is stdin or not)
#if 0
fclose(fptr);
#endif
}
Here's a slightly more cleaned up version:
#include <stdio.h>
#include <stdlib.h>
void display_stream(FILE *fptr);
int
main(int argc, char *argv[])
{
int i;
// if no args given, read from stdin (just like shell/cat)
if (argc < 2)
display_stream(stdin);
for (i = 1; i < argc; i++) {
FILE *fptr = fopen(argv[i], "r");
if (fptr == 0) {
printf("error: file not found.");
continue;
}
display_stream(fptr);
fclose(fptr);
}
return 0;
}
void
display_stream(FILE *fptr)
{
int x;
/* read one character at a time from file, stopping at EOF,
which indicates the end of the file. */
while ((x = fgetc(fptr)) != EOF)
putchar(x);
}
Move fclose out of display_stream, it doesn’t belong there. Place it just after the call to display_stream.
Add display_stream(stdin) to main (without fclose this time, stdin shouldn’t be closed), before or after the loop. It should just work.
It will probably copy from stdin line-by-line but that’s due to buffering outside of the program which is not that easy to disable AFAIK.
Also, printf( "%c", x ) could be putchar(x)
I have written this code:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *inputFiles[argc - 1];
int i;
char c;
int counter = 1;
// Enter files into an array
for (i = 1; i < argc; i++)
{
//printf("The file in place %d is %s\n",i, argv[i]);
inputFiles[i] = fopen(argv[i], "r");
if ((inputFiles[i] = NULL)) {
printf("File cannot be opened");
}
//printf("%p\n",inputFiles[i]);
}
c = fgetc(inputFiles[argc - 1]);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(inputFiles[counter]);
}
fclose(inputFiles[argc - 1]);
return 0;
}
and it does what it needs to do, but there is a bug: If I print out the content of a file, the first character of the file is duplicated, how can I fix this. Furthermore as the files are read in through command-line arguments, I would like to output an error message if one of the files cannot be found or is corrupt. How can I do this? Any help is greatly appreciated.
if ((inputFiles[i] = NULL))
You are assigning NULL, not checking for NULL.
change this
if ((inputFiles[i] = NULL)) { //its assignment not comparison
printf("File cannot be opened");
}
to
if ((inputFiles[i] == NULL)) {
printf("File cannot be opened");
}
I tried to change all random lowercase letters to uppercase letters in this program.First of all, I have initialized in lowercase.txt AkfsASlkALfdk.Then I read from it and changing all the lowercase letters into capital ones.The problem is,when I opened the capital.txt is ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌAKFSASLKALFDK.Where did the error come from?I couldn't find it yet and I decided to ask you.
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <conio.h>
int main()
{
int i;
char s[100];
char k[100];
FILE *kp;
kp = fopen("lowercase.txt", "r");
if (kp == NULL)
{
printf("Error in opening file.\n");
system("pause");
exit(1);
}
FILE *temp;
temp = fopen("capital.txt", "w");
if (kp == NULL)
{
printf("Error in opening file.\n");
system("pause");
exit(2);
}
printf("Opening file is successful.\n");
if (fscanf(kp, "%s", &s) != EOF)
{
for (i = 0; i < 100; i++)
{
if (s[i] >= 97 && s[i] <= 122)
{
s[i] -= 32;
}
}
}
fprintf(temp, "%s", k);
getch();
return 0;
}
Multiple issues in your code which together cause the issues
You are storing the opened FILE* in temp, but checking kp. I think that is because you copy pasted the check from above. Can be easily fixed by changing the variable
You perform the capitalization operation outside what was set by scanf. As suggested by #MOehm, change the loop condition to s[i]
Finally you are converting the string in place in s but are saving k in the file. k is never modified. Change fprintf(temp, "%s", k); to fprintf(temp, "%s", s);
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *append(const char *s, char c) {
int len = strlen(s);
char buf[len+2];
strcpy(buf, s);
buf[len] = c;
buf[len + 1] = 0;
return strdup(buf);
}
int main(int argc, char **argv)
{
char ch;
FILE *fp;
if (argc != 2)
return (0);
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
char *res;
while((ch = fgetc(fp)) != EOF)
{
res = append(res, ch);
}
fclose(fp);
int i = 0;
while (i < strlen(res))
{
if (res[i] >= 97 && res[i] <= 122)
res[i] = res[i] - 32;
i++;
}
printf("%s\n", res);
return 0;
}
here is a quick example
read the file char by char and add each char in a char *. Then for each character lowercase char, sub 32 to get the uppercase char and write it then print. Give the filename as first parameter when you start the programm
Everytime I try to run the code it'll print out the contents of the file, however it will print out a garbage value at the end which I don't know how to get rid of. I am supposed to to store the contents of the file into an array, however I am a bit confused on how to do that???
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char filePrinter(char*arr)
int main (int argc, char**argv)
{
char fileArray[150];
if(argc !=2)
{
printf("Invalid Entry. Please Enter name of program followed by input filename\n");
}
filePrinter(fileArray);
return 0;
}
char filePrinter(char*arr)
{
int i;
FILE*file;
i=0;
file=fopen("assests/room.txt","r");
if(file == NULL)
{
printf("Could not open file\n");
exit(-1);
}
else
{
while(0 ==feof(file))
{
i=fgetc(file);
printf("%c", i);
}
}
fclose(file);
return i;
}
file content:
10x16 ds5 h6,5 g7,8 p3,3
10X16 de4 h5,7 g9,2
10X16 dw6,h2,3 m6,7
10X16 dn3,h2,4 p2,3
10X16 de2 h9,9 m4,5
10X16 dn8 h4,5 g1,1*/
feof returns true if the last call to a read operation hit EOF. You'd want to test it after the fgetc call. Or, even better, just check whether fgetc returned the special value EOF.
(A FILE * has an "end-of-file marker" that says whether some read operation has hit EOF. Read operations set the "end-of-file marker" upon hitting EOF. Before you've hit---meaning tried to read past---the end of the file, that "end-of-file marker" is clear.)
Timing is bad than look at the beginning of the loop by feof because EOF occur in fgetc.
replace to
while(EOF!=(i=fgetc(file))){
printf("%c", i);
}
int filePrinter(char*arr){
int i = 0, ch;
FILE*file;
file=fopen("assests/room.txt","r");
if(file == NULL) {
printf("Could not open file\n");
exit(-1);
} else {
while(EOF!=(ch=fgetc(file))) {
//printf("%c", ch);
arr[i] = ch; //*arr++ = ch;
++i;//i : range check
}
arr[i] = '\0';
}
fclose(file);
return i;
}
I think the code should be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void filePrinter(char*arr);
int main (int argc, char**argv)
{
char fileArray[150];
memset(fileArray, 0, sizeof(fileArray));
if(argc !=2)
{
printf("Invalid Entry. Please Enter name of program followed by input filename\n");
}
filePrinter(fileArray);
return 0;
}
void filePrinter(char *arr)
{
int c = 0, j = 0;
FILE* file = NULL;
file=fopen("assests/room.txt","r");
if(file == NULL)
{
printf("Could not open file\n");
exit(-1);
}
else
{
while (1)
{
c = fgetc(file);
if (c != EOF)
{
arr[j++] = c;
}
else
{
break;
}
}
}
fclose(file);
return;
}
I wanted to know how it would be possible to get other input through the command line? I want to look for "-w" and a number, so it would look like "-w60" and "-s". This input is given through the command line, so it would look like this:
c:\Users\Username\Desktop> wrapfile.exe -w5 -s test.txt
Output should look like this:
Hello
,
this
is a
test
What the -w5 and -s mean is:
-w5 = width (can only display 5 characters at a time)
-s = spacing (Include spacing, so fit as many whole words as you can)
I want to create a function that scans for these two characters, and if anyone knows how to format the output so it does what it needs to do, that would also be helpful.
I'm just a wee bit confused, I've been working on this program for a while and I just want to learn how these things can be scanned and used properly.
Here is my current code that takes in an unlimited amount of text files from the command line:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int l = 1;
while(l != argc)
{
FILE *fp;
fp = fopen(argv[l], "rb");
l++;
if (fp != NULL)
{
int i = 1;
do
{
i = fgetc(fp);
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
}
/*
void scanningForWS(int argc, char **argv)
{
}
*/
If you pass -w5 -s test.txt to your program your argv's are:
argv[0] = "wrapfile.exe"
argv[1] = "-w5"
argv[2] = "-s"
argv[3] = "test.txt"
So:
int l = 1;
fp = fopen(argv[l], "rb");
is not what you want for sure.
For illustration purposes... in order to print to a "restricted" width you can do something like this:
char * h = "this is a string longer than width"; // you'd get this from your file
int width = argv[1][2] - '0'; // you wouldn't hardcode this...
int count;
for(count = 0; count < strlen(h); count++){
if((count % width) < width - 1)
printf("%c", str[count];
else
printf("%c\n", str[count];
}
I find getopt cumbersome to use. Writing your own tests is not too difficult. For example:
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv) {
int haveSpacing = 0;
int haveWidth = 0;
FILE *fp = 0;
while (*++argv) {
if (!strcmp(*argv, "-s")) { // check for -s switch
haveSpacing = 1;
}
else if (sscanf(*argv, "-w%d", &haveWidth) == 1) { // check for -wxx
}
else if (**argv == '-') { // reject anything else beginning with "-"
printf("invalid switch %s\n", *argv);
return 1;
}
else if (argv[1]) { // filenaname must be last arg, so arg[1] must be NULL
printf("invalid arg %s\n", *argv);
return 1;
}
else if (!(fp = fopen(*argv, "rb"))) { // open last arg, the filename
perror(*argv);
return 1;
}
}
if (!fp) {
printf("missing filename\n");
return 1;
}
// ...
return 0;
}