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;
}
Related
I have a function that returns the number of lines, characters, and words in an array. For some reason, when i loop through the array to print the values I am only getting the corrrect value for lines, the characters and words are returning as 0. All the functions are predetermined by my professor and my job is to fill them in.
int main(int argc, char **argv)
{
int *myArray = get_counts(argv[1]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", myArray[i]);
}
return 0;
}
int *get_counts(char *filename)
{
FILE *file;
file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
}
char c;
int h;
bool whitespace = true;
static int arr[3] = {0,0,0};
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
while (true)
{
h = fgetc(file);
if (feof(file))
{
break;
}
else if (ferror(file))
{
printf("error reading file");
}
arr[2] ++;
if (whitespace && !isspace(h))
{
arr[1] ++;
whitespace = false;
}
else if (!whitespace &&isspace(h))
{
whitespace = true;
}
}
fclose(file);
return arr;
}
The best option is probably to just iterate through the file in one loop (you could also rewind() after the first loop). Use the return value of fgetc() to determine of you are at EOF instead of separate feof() calls. I also made the the result array an (out) argument instead of using a static variable (the latter is not reentrant if you ever want to call this from multiple threads and it's easy to do):
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
void get_counts(char *filename, int arr[3]) {
memset(arr, 0, 3 * sizeof(int));
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("NULL FILE");
return;
}
bool whitespace = true;
for(;;) {
int c = fgetc(file);
if(c == EOF)
break;
else if(c == '\n')
arr[0]++;
else if (whitespace && !isspace(c)) {
arr[1]++;
whitespace = false;
} else if (!whitespace && isspace(c))
whitespace = true;
arr[2]++;
}
fclose(file);
}
int main(int argc, char **argv) {
int myArray[3];
get_counts(argv[1], myArray);
for (int i = 0; i < 3; i++) {
printf("%d\n", myArray[i]);
}
}
The output on the above file is:
39
94
715
The word count 94 doesn't agree with wc -w but you could be using a different definition of what a word is.
It's a good idea to separate calculations and i/o, so consider opening and closing the file in main() and pass in the file handle. It becomes easy, for instance, to use the stdin file handle instead if you don't want to use a physical file.
After the first do-while loop the condition EOF occurs.
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
So the following while loop has no effect.
You should use only one loop to count lines, words and characters.
Pay attention to that the variable c should be declared as having the type int
int c;
Also you need to exit the function if the file was not opened.
I have this function which is supposed to delete the recipe requested by the user. I've always deleted records in this way, but I don't know why this time it doesn't work in the right way. Sometimes it states that there's no match but it deletes the recipe or it deletes all the recipes inside the file and I don't get it why since I basically created a temp file in which writing all the records except for the one the user wants to delete and I used a function that worked for another record so I really don't get it. Is that because the length of ingredients and procedure is not the same for all the recipes?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int stringCmpi (char *s1,char *s2);
struct _recipe
{
char name[40];
int count_i;
char ingredients[20][40];
char diff[12];
int timr;
int calories;
int count_p;
char procedure[30][500];
} recipe;
int main()
{
FILE* fbr;
FILE* temp;
char ricetta_name[] = "ricette.bin";
char temp_name[] = "temp.bin";
fbr = fopen("ricette.bin", "rb");
temp = fopen("temp.bin", "wb");
int found = 0;
char name_t[40];
int i;
char space = '\n';
if(fbr == NULL)
{
printf("Couldn't open the file.\n");
exit(1);
}
if(fbr == NULL)
{
printf("Couldn't open the file.\n");
exit(1);
}
printf("Write the name of the recipe you want to delete:\n");
fgets(name_t,sizeof(name_t),stdin);
space = getchar();
while(fread(&recipe,sizeof(recipe),1,fbr) && found == 0)
{
if(stringCmpi(name_t,recipe.name) == 0)
{
found = 1;
printf("Match found. Recipe deleted.\n");
}
else
{
fwrite(&recipe,sizeof(recipe),1,temp);
}
if(!found)
{
printf("No match.\n");
}
}
fclose(fbr);
fclose(temp);
remove(ricetta_name);
rename(temp_name,ricetta_name);
system("PAUSE");
return 0;
}
int stringCmpi (char *s1,char *s2)
{
int i=0;
for(i=0; s1[i]!='\0'; i++)
{
if( toupper(s1[i])!=toupper(s2[i]) )
return 1;
}
return 0;
}
The problem is here:
while(fread(&recipe,sizeof(recipe),1,fbr) && found == 0)
Once you find a recipe, you exit the loop, so the remaining elements are not copied to the new file. I recommend you delete the && found == 0 clause.
Furthermore:
if(!found)
{
printf("No match.\n");
}
This is actually inside the while loop, so it will report No match multiple times. Please move it outside the loop.
Proper indentation would help you see the actual structure of the program. This is how the posted program looks with consistent indentation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int stringCmpi (char *s1,char *s2);
struct _recipe
{
char name[40];
int count_i;
char ingredients[20][40];
char diff[12];
int timr;
int calories;
int count_p;
char procedure[30][500];
} recipe;
int main()
{
FILE* fbr;
FILE* temp;
char ricetta_name[] = "ricette.bin";
char temp_name[] = "temp.bin";
fbr = fopen("ricette.bin", "rb");
temp = fopen("temp.bin", "wb");
int found = 0;
char name_t[40];
int i;
char space = '\n';
if(fbr == NULL)
{
printf("Couldn't open the file.\n");
exit(1);
}
if(fbr == NULL)
{
printf("Couldn't open the file.\n");
exit(1);
}
printf("Write the name of the recipe you want to delete:\n");
fgets(name_t,sizeof(name_t),stdin);
space = getchar();
while(fread(&recipe,sizeof(recipe),1,fbr) && found == 0)
{
if(stringCmpi(name_t,recipe.name) == 0)
{
found = 1;
printf("Match found. Recipe deleted.\n");
}
else
{
fwrite(&recipe,sizeof(recipe),1,temp);
}
if(!found)
{
printf("No match.\n");
}
}
fclose(fbr);
fclose(temp);
remove(ricetta_name);
rename(temp_name,ricetta_name);
system("PAUSE");
return 0;
}
int stringCmpi (char *s1,char *s2)
{
int i=0;
for(i=0; s1[i]!='\0'; i++)
{
if( toupper(s1[i])!=toupper(s2[i]) )
return 1;
}
return 0;
}
The program is checking that fbr is not NULL twice. Probably the second check should be for temp.
The programs stops reading and copying when the recipe to be deleted is found; this means that the following records are not copied over.
The program complains that the recipe was not found for each recipe until the desired one is found.
Suggestions:
Modify the while loop condition eliminating the && ! found, so that all records are copied except those matching the given name.
Move the check for if (! found) outside the loop.
Bonus:
The function stringCmpi() stops comparing at the end of string s1; which means that "abc" and "abcdef" will compare equal. You probably want to change return 0 to return s1 [i] != s2 [i].
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _recipe
{
char name[40];
int count_i;
char ingredients[20][40];
char diff[12];
int timr;
int calories;
int count_p;
char procedure[30][500];
} recipe;
int main(int argc, char *argv[])
{
FILE* fbr;
FILE* temp;
char *ricetta_name = "recipe.bin";
char *temp_name = "temp.bin";
int found = 0;
char name_t[40];
// Use command line arguments if possible
if (argc == 2)
{
ricetta_name = argv[1];
}
if((fbr = fopen(ricetta_name, "rb")) == NULL)
{
printf("Couldn't open the file %s.\n", ricetta_name);
exit(1);
}
if((temp = fopen(temp_name, "wb")) == NULL)
{
printf("Couldn't open the file %s.\n", temp_name);
exit(1);
}
printf("Write the name of the recipe you want to delete:\n");
fgets(name_t, sizeof(name_t), stdin);
// Remove '\n'
if (name_t[strlen(name_t) - 1] == '\n')
name_t[strlen(name_t) - 1] = 0;
while(fread(&recipe,sizeof(recipe), 1, fbr))
{
// Use standard strcasecmp()
if(strcasecmp(name_t, recipe.name) == 0)
{
found = 1;
printf("Match found. Recipe deleted.\n");
}
else
{
fwrite(&recipe, sizeof(recipe), 1, temp);
}
}
if (!found)
{
printf("No match.\n");
}
fclose(fbr);
fclose(temp);
remove(ricetta_name);
rename(temp_name,ricetta_name);
return 0;
}
Please format your code: add space(' ') after comma(','). And use standard function if possible.
I'm just getting started into file I/O and am trying to build a function that will simply copy a file to destination.
This program compiles however an empty file is created and nothing is copied. Any advice?
#include <stdio.h>
int copy_file(char FileSource[], char FileDestination[]) {
char content;
FILE *inputf = fopen(FileSource, "r");
FILE *outputf = fopen(FileDestination, "w");
if (inputf == NULL)
;
printf("Error: File could not be read \n");
return;
while ((content = getc(inputf)) != EOF) putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
scanf("%s", &inputname);
printf("Please write output file name: \n");
scanf("%s", &outputname);
copy_file(inputname, outputname);
return 0;
}
There are few bugs in the code you mentioned. These two below statement
scanf("%s", &inputname);
scanf("%s", &outputname);
Are wrong as inputname and outputname are char array and array name itself address so you no need to give &inputname to scanf(). For e.g
scanf("%s",inputname);
scanf("%s",outputname);
Also ; at the end of if statement is not serving correct purpose as you expected.
This
if(inputf == NULL);
Should be
if(inputf == NULL){
/*error handling */
}
As pointed by other, getc() returns int not char. From the manual page of getc()
int getc(FILE *stream);
And this
putc(content, inputf);
Change to
putc(content, outputf); /* write the data into outputf */
Your line :
putc(content, inputf);
needs to change to
putc(content, outputf);
This code has a lot of problems:
if(inputf == NULL);
printf("Error: File could not be read \n");
return;
It is the equivalent of
if(inputf == NULL)
{
;
}
printf("Error: File could not be read \n");
return;
You have a stray ; that terminates you if statement, and whitespace doesn't matter much at all with C.
So your if statement does nothing, and your code will always emit the "Error: File could not be read" message and return without doing anything else.
What you probably want:
if(inputf == NULL)
{
printf("Error: File could not be read \n");
return;
}
This is a perfect example of why a lot of C programmers always use braces after if statements. ALWAYS.
There are multiple problems in your code:
content must be declared as int: getc() returns an int with the value of the byte read from the file or the special negative value EOF at end of file. Storing that to a char variable loses information, making the test for EOF either ambiguous (if char is signed) or always false (if char is unsigned by default).
you should pass outputf to putc.
you should return from the copy_file function if fopen fails to open either file.
you should pass the maximum number of characters to read for the filenames
you should check the return value of scanf() to avoid undefined behavior on invalid input.
Here is a corrected version:
#include <stdio.h>
int copy_file(const char *FileSource, const char *FileDestination) {
int content;
FILE *inputf, *outputf;
if ((inputf = fopen(FileSource, "r")) == NULL) {
printf("Error: cannot open input file %s\n", FileSource);
return -1;
}
if ((outputf = fopen(FileDestination, "w")) == NULL) {
printf("Error: cannot open output file %s\n", FileDestination);
fclose(inputf);
return -1;
}
while ((content = getc(inputf)) != EOF)
putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
if (scanf("%99s", inputname) != 1)
return 1;
printf("Please write output file name: \n");
if (scanf("%99s", &outputname) != 1)
return 1;
copy_file(inputname, outputname);
return 0;
}
Use sendfile() is more simple and efficient for copying file. You can view more detail about sendfile() by man sendfile.
#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("Usage: %s <srcfile> <dst_file>\n", argv[0]);
return 1;
}
char *src_file = argv[1];
char *dst_file = argv[2];
int src;
int dst;
ssize_t size;
struct stat stat_buf;
if ((src = open(src_file, O_RDONLY)) < 0)
{
printf("Can not open %s\n", src_file);
return -1;
}
if (fstat(src, &stat_buf) < 0)
{
printf("Can stat %s\n", src_file);
close(src);
return -2;
}
if ((dst = open(dst_file, O_CREAT|O_WRONLY, stat_buf.st_mode)) < 0)
{
printf("Can not open %s\n", dst_file);
return -1;
}
if ((size = sendfile(dst, src, NULL, stat_buf.st_size)) < 0)
{
printf("Fail to copy file, size: %ld\n", size);
}
else
{
printf("Success, size: %ld\n", size);
}
close(src);
close(dst);
return 0;
}
So here I have a basic program that will write to a specific line in a file by writing the contents of the file into a temporary file where the new line is written and then the contents of that file is then copied back into the starting file.
(Scores) = File
(Sub) = Temp
#include <stdio.h>
#include <conio.h>
#include <string.h>
void insert(void);
int main()
{
insert();
}
void insert(void)
{
FILE *fp,*fc;
int lineNum;
int count=0;
char ch=0;
int edited=0;
int score=0;
fp=fopen("Test 02 Scores.txt","r");
fc=fopen("Sub.txt","w");
if(fp==NULL||fc==NULL)
{
printf("\nError...cannot open/create files");
exit(1);
}
printf("Enter the score");
scanf("%d",&score);
printf("\nEnter Line Number Which You Want 2 edit: ");
scanf("%d",&lineNum);
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n')
count++;
if(count==lineNum-1 && edited==0)
{
if(lineNum==1)
{
fprintf(fc,"%d\n",score);
}
else
fprintf(fc,"\n%d\n",score);
edited=1;
while( (ch=fgetc(fp))!=EOF )
{
if(ch=='\n')
break;
}
}
else
fprintf(fc,"%d",ch);
}
fclose(fp);
fclose(fc);
if(edited==1)
{
printf("\nLine has been written successfully.");
char ch;
FILE *fs, *ft;
fs = fopen("Sub.txt", "r");
if( fs == NULL )
{
printf("File is not real");
exit(1);
}
ft = fopen("Test 02 Scores.txt", "w");
if( ft == NULL )
{
fclose(fs);
printf("File is not real\n");
exit(1);
}
while( ( ch = fgetc(fs) ) != EOF )
fputc(ch,ft);
printf("\nFile copied\n");
getch();
fclose(fs);
fclose(ft);
}
else
printf("\nLine Not Found");
}
However, a problem has arisen, I started to write this code for use with strings, but since decided to use number values, whenever I try to copy with the integer values the program will not copy anything right, I Know this may be caused by the char to int but I'd rather have more help in assessing where I should change stuff.
The error is in this line
fprintf(fc,"%d",ch)
%d prints ch as an integer, not as a character, you should instead write
fprintf(fc,"%c",ch)
or use fputc()
There are some small issues with your code, here is a working version. I added comments where I changed things.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h> // needed for exit()
void insert(void);
int main()
{
insert();
}
// use fgets to read from keyboard, it is simpler.
int readNumber()
{
char buffer[64] = {0};
fgets(buffer, sizeof(buffer), stdin);
return atoi(buffer);
}
void insert(void)
{
FILE *fp = NULL; // prefer one decl per row
FILE *fc = NULL;
int lineNum = 0;
int count=0;
int ch=0; // should be int ch=0;
int edited=0;
int score=0;
// file names
const char src[] = "Test 02 Scores.txt";
const char dest[] = "Sub.txt";
fp=fopen(src,"r");
if(fp==NULL)
{
perror(src); // use perror() instead for better error msg
exit(EXIT_FAILURE); // there are std constants for exit args
}
fc=fopen(dest,"w");
if(fc==NULL)
{
perror(dest);
exit(EXIT_FAILURE);
}
printf("Enter the score: ");
score = readNumber(); // using fgets to avoid lingering \n in buffer
printf("\nEnter Line Number Which You Want 2 edit: ");
lineNum = readNumber();
while((ch=fgetc(fp))!=EOF) // fgetc returns int so ch should be int
{
if(ch=='\n') // better to have {} here too
{
count++;
}
if(count==lineNum-1 && edited==0)
{
if(lineNum==1)
{
fprintf(fc,"%d\n",score);
}
else // better to { } here too
{
fprintf(fc,"\n%d\n",score);
}
edited=1;
// i guess you want to remove old score
while( (ch=fgetc(fp))!=EOF )
{
if(ch=='\n')
{
break;
}
}
}
else // {} for avoiding future pitfall
{
fputc(ch,fc);
}
}
fclose(fp);
fclose(fc);
if(edited==1)
{
puts("\nLine has been written successfully."); // puts() when u can
int ch = 0; // int
FILE *fs = NULL;
FILE *ft = NULL;
fs = fopen(dest, "r");
if( fs == NULL )
{
perror(dest);
exit(EXIT_FAILURE);
}
ft = fopen(src, "w");
if( ft == NULL )
{
perror(src);
exit(EXIT_FAILURE); // at program exit files will close anyway
}
while( ( ch = fgetc(fs) ) != EOF )
{
fputc(ch,ft);
}
fclose(fs);
fclose(ft);
printf("\nFile copied\n");
getch();
}
else
{
printf("\nLine Not Found");
}
}
I've created a very basic 'debugging' program that checks if a c source file has the same number of opening and closing curly brackets, square brackets and parentheses. I have a code that's fairly simple and it works but the code seems unnecessarily long. I was considering using arrays instead. An array to store each {,[,( and another to store },],) then counting the instance of each and comparing the amounts. But I think that code would be almost as long. What do you guys think?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char fname[20];
char c;
int curlybracket = 0;
int curlybracketr = 0;
int squarebracket = 0;
int squarebracketr = 0;
int parentheses = 0;
int parenthesesr = 0;
printf("Please enter the destination of the file: \n");
scanf("%s", fname);
fp = fopen(fname, "r");
if (fp == NULL)
{
printf("Problem opening file!\n");
exit(0);
}
else
{
printf("File opened correctly\n");
}
while (c != EOF)
{
c = getc(fp);
if (c == '{')
{
curlybracket++;
}
if (c == '[')
{
squarebracket++;
}
if (c == '(')
{
parentheses++;
}
if (c == '}')
{
curlybracketr++;
}
if (c == ']')
{
squarebracketr++;
}
if (c == ')')
{
parenthesesr++;
}
}
if (curlybracket == curlybracketr)
{
printf("There are an equal number of curlybrackets\n");
}
else
{
printf("There is an unequal number of curlybrackets\n");
return 0;
}
if (squarebracket == squarebracketr)
{
printf("There are an equal number of squarebrackets\n");
}
else
{
printf("There are an unequal number of squarebrackets\n");
}
if (parentheses == parenthesesr)
{
printf("There are an equal number of parentheses\n");
}
else
{
printf("There are an unequal number of parentheses\n");
}
return 0;
}
Your program will report no error if the source file is like "([)]", which is actually illegal.
A better solution is to use a stack, which is a last-in-first-out data structure. This section from the wikipedia page illustrates the usage.
When you read an opening symbol from the file, push it onto the stack. If it's a closing symbol, pop the stack. If the symbol popped is not the corresponding opening symbol, report unbalanced error.
At the end of file, if the stack is empty, the symbols in the file are balanced.
This is the most common way that I know to test whether the symbols are balanced.
Use the switch statement for the list of comparisons with c. If you want your code to be even more concise, use a single array of 256 int values to store the occurrence of each character and compare the array values at { and }.
True, program can be re-written in more shorter way by using arrays. It could look something like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char fname[20];
char c;
char brackets[6] = "{}[]()";
int bracketCounts[6] = {0};
char * found;
int i;
printf("Please enter the destination of the file: \n");
scanf("%s", fname);
if ((fp = fopen(fname, "r")) == NULL){
printf("Problem opening file!\n");
return 0x00;
}
printf("File opened correctly\n");
// counting various parentheses
while ((c = getc(fp)) != EOF){
found = strchr(brackets, c);
if (found != NULL) {
bracketCounts[found - brackets]++;
}
}
// dont't forget to close file after reading is done
fclose(fp);
// checking parentheses counters
for (i=0; i < 6; i+=2) {
if (bracketCounts[i] != bracketCounts[i+1]) {
printf("Unbalanced parentheses !\n");
return 0x00;
}
}
printf("All parentheses are OK!\n");
return 0x00;
}
But it is error-prone as #lbs mentioned, it's far more better to use #lbs approach !
Count character occurrences in a string
#include <algorithm>
std::string s = "a(b(c))";
int curlybracket = std::count(s.begin(), s.end(), '(') - std::count(s.begin(), s.end(), ')');
if(curlybracket == 0) /* coool */ else /* fail */
Yust another way to solve the problem